diff --git a/PROJECT b/PROJECT index d6499457f5..283a0233d7 100644 --- a/PROJECT +++ b/PROJECT @@ -151,4 +151,12 @@ resources: kind: AtlasBackupCompliancePolicy path: github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1 version: v1 +- api: + crdVersion: v1 + namespaced: true + domain: mongodb.com + group: atlas + kind: AtlasThirdPartyIntegration + path: github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1 + version: v1 version: "3" diff --git a/api/v1/atlasthirdpartyintegration_types.go b/api/v1/atlasthirdpartyintegration_types.go new file mode 100644 index 0000000000..80d843cb22 --- /dev/null +++ b/api/v1/atlasthirdpartyintegration_types.go @@ -0,0 +1,206 @@ +// Copyright 2025 MongoDB. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/status" +) + +func init() { + SchemeBuilder.Register(&AtlasThirdPartyIntegration{}, &AtlasThirdPartyIntegrationList{}) +} + +// +kubebuilder:object:root=true + +// AtlasThirdPartyIntegration is the Schema for the atlas 3rd party inegrations API. +type AtlasThirdPartyIntegration struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec AtlasThirdPartyIntegrationSpec `json:"spec,omitempty"` + Status status.AtlasThirdPartyIntegrationStatus `json:"status,omitempty"` +} + +// AtlasThirdPartyIntegrationSpec contains the expected configuration for an integration +// +kubebuilder:validation:XValidation:rule="(has(self.externalProjectRef) && !has(self.projectRef)) || (!has(self.externalProjectRef) && has(self.projectRef))",message="must define only one project reference through externalProjectRef or projectRef" +// +kubebuilder:validation:XValidation:rule="(has(self.externalProjectRef) && has(self.connectionSecret)) || !has(self.externalProjectRef)",message="must define a local connection secret when referencing an external project" +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type.size() != 0",message="must define a type of integration" +// +kubebuilder:validation:XValidation:rule="!has(self.datadog) || (self.type == 'DATADOG' && has(self.datadog))",message="only DATADOG type may set datadog fields" +// +kubebuilder:validation:XValidation:rule="!has(self.microsoftTeams) || (self.type == 'MICROSOFT_TEAMS' && has(self.microsoftTeams))",message="only MICROSOFT_TEAMS type may set microsoftTeams fields" +// +kubebuilder:validation:XValidation:rule="!has(self.newRelic) || (self.type == 'NEW_RELIC' && has(self.newRelic))",message="only NEW_RELIC type may set newRelic fields" +// +kubebuilder:validation:XValidation:rule="!has(self.opsGenie) || (self.type == 'OPS_GENIE' && has(self.opsGenie))",message="only OPS_GENIE type may set opsGenie fields" +// +kubebuilder:validation:XValidation:rule="!has(self.prometheus) || (self.type == 'PROMETHEUS' && has(self.prometheus))",message="only PROMETHEUS type may set prometheus fields" +// +kubebuilder:validation:XValidation:rule="!has(self.pagerDuty) || (self.type == 'PAGER_DUTY' && has(self.pagerDuty))",message="only PAGER_DUTY type may set pagerDuty fields" +// +kubebuilder:validation:XValidation:rule="!has(self.slack) || (self.type == 'SLACK' && has(self.slack))",message="only SLACK type may set slack fields" +// +kubebuilder:validation:XValidation:rule="!has(self.victorOps) || (self.type == 'VICTOR_OPS' && has(self.victorOps))",message="only VICTOR_OPS type may set victorOps fields" +// +kubebuilder:validation:XValidation:rule="!has(self.webhook) || (self.type == 'WEBHOOK' && has(self.webhook))",message="only WEBHOOK type may set webhook fields" +type AtlasThirdPartyIntegrationSpec struct { + ProjectDualReference `json:",inline"` + + // Type of the integration + // +kubebuilder:validation:Enum:=DATADOG;MICROSOFT_TEAMS;NEW_RELIC;OPS_GENIE;PAGER_DUTY;PROMETHEUS;SLACK;VICTOR_OPS;WEBHOOK + // +kubebuilder:validation:Required + Type string `json:"type"` + + // Datadog contains the config fields for Datadog's Integration + // +kubebuilder:validation:Optional + Datadog *DatadogIntegration `json:"datadog,omitempty"` + + // MicrosoftTeams contains the config fields for Microsoft Teams's Integration + // +kubebuilder:validation:Optional + MicrosoftTeams *MicrosoftTeamsIntegration `json:"microsoftTeams,omitempty"` + + // NewRelic contains the config fields for New Relic's Integration + // +kubebuilder:validation:Optional + NewRelic *NewRelicIntegration `json:"newRelic,omitempty"` + + // OpsGenie contains the config fields for Ops Genie's Integration + // +kubebuilder:validation:Optional + OpsGenie *OpsGenieIntegration `json:"opsGenie,omitempty"` + + // PagerDuty contains the config fields for PagerDuty's Integration + // +kubebuilder:validation:Optional + PagerDuty *PagerDutyIntegration `json:"pagerDuty,omitempty"` + + // Prometheus contains the config fields for Prometheus's Integration + // +kubebuilder:validation:Optional + Prometheus *PrometheusIntegration `json:"prometheus,omitempty"` + + // Slack contains the config fields for Slack's Integration + // +kubebuilder:validation:Optional + Slack *SlackIntegration `json:"slack,omitempty"` + + // VictorOps contains the config fields for VictorOps's Integration + // +kubebuilder:validation:Optional + VictorOps *VictorOpsIntegration `json:"victorOps,omitempty"` + + // Webhook contains the config fields for Webhook's Integration + // +kubebuilder:validation:Optional + Webhook *WebhookIntegration `json:"webhook,omitempty"` +} + +type DatadogIntegration struct { + // APIKeySecret holds the name of a secret containing the datadog api key + // +kubebuilder:validation:Required + APIKeySecret api.LocalObjectReference `json:"apiKeySecret"` + + // Region is the Datadog region + // +kubebuilder:validation:Required + Region string `json:"region"` + + // SendCollectionLatencyMetrics toggles sending collection latency metrics + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=enabled;disabled + // +kubebuilder:default:=disabled + SendCollectionLatencyMetrics *string `json:"sendCollectionLatencyMetrics"` + + // SendDatabaseMetrics toggles sending database metrics, + // including database and collection names + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=enabled;disabled + // +kubebuilder:default:=disabled + SendDatabaseMetrics *string `json:"sendDatabaseMetrics"` +} + +type MicrosoftTeamsIntegration struct { + // URLSecret holds the name of a secret containing the microsoft teams secret URL + // +kubebuilder:validation:Required + URLSecret api.LocalObjectReference `json:"urlSecret"` +} + +type NewRelicIntegration struct { + // CredentialsSecret holds the name of a secret containing new relic's credentials: + // account id, license key, read and write tokens + // +kubebuilder:validation:Required + CredentialsSecret api.LocalObjectReference `json:"credentialsSecret"` +} + +type OpsGenieIntegration struct { + // APIKeySecret holds the name of a secret containing Ops Genie's API key + // +kubebuilder:validation:Required + APIKeySecret api.LocalObjectReference `json:"apiKeySecret"` + + // Region is the Ops Genie region + // +kubebuilder:validation:Required + Region string `json:"region"` +} + +type PagerDutyIntegration struct { + // ServiceKeySecret holds the name of a secret containing Pager Duty service key + // +kubebuilder:validation:Required + ServiceKeySecret api.LocalObjectReference `json:"serviceKeySecret"` + + // Region is the Pager Duty region + // +kubebuilder:validation:Required + Region string `json:"region"` +} + +type PrometheusIntegration struct { + // PrometheusCredentials holds the name of a secret containing the Prometheus + // username & password + // +kubebuilder:validation:Required + PrometheusCredentials api.LocalObjectReference `json:"prometheusCredentials"` + + // ServiceDiscovery to be used by Prometheus + // +kubebuilder:validation:Enum:=file;http + // +kubebuilder:validation:Required + ServiceDiscovery string `json:"serviceDiscovery"` +} + +type SlackIntegration struct { + // APITokenSecret holds the name of a secret containing the Slack API token + // +kubebuilder:validation:Required + APITokenSecret api.LocalObjectReference `json:"apiTokenSecret"` + + // ChannelName to be used by Prometheus + // +kubebuilder:validation:Required + ChannelName string `json:"channelName"` + + // TeamName flags whether or not Prometheus integration is enabled + // +kubebuilder:validation:Required + TeamName string `json:"teamName"` +} + +type VictorOpsIntegration struct { + // RoutingKey holds VictorOps routing key + // +kubebuilder:validation:Required + RoutingKey api.LocalObjectReference `json:"routingKey"` + + // APIKeySecret is the name of a secret containing Victor Ops API key + // +kubebuilder:validation:Required + APIKeySecret string `json:"apiKeySecret"` +} + +type WebhookIntegration struct { + // URLSecret holds the name of a secret containing Webhook URL and secret + // +kubebuilder:validation:Required + URLSecret api.LocalObjectReference `json:"urlSecret"` +} + +// +kubebuilder:object:root=true + +// AtlasThirdPartyIntegrationList contains a list of Atlas Integrations. +type AtlasThirdPartyIntegrationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []AtlasThirdPartyIntegration `json:"items"` +} + +func (i *AtlasThirdPartyIntegration) ProjectDualRef() *ProjectDualReference { + return &i.Spec.ProjectDualReference +} diff --git a/api/v1/atlasthirdpartyintegration_types_test.go b/api/v1/atlasthirdpartyintegration_types_test.go new file mode 100644 index 0000000000..989fd39d0c --- /dev/null +++ b/api/v1/atlasthirdpartyintegration_types_test.go @@ -0,0 +1,215 @@ +// Copyright 2025 MongoDB. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/runtime" + + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/common" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/cel" +) + +func TestIntegrationCELChecks(t *testing.T) { + for _, tc := range []struct { + title string + obj *AtlasThirdPartyIntegration + expectedErrors []string + }{ + { + title: "fails with no type", + obj: &AtlasThirdPartyIntegration{}, + expectedErrors: []string{"spec: Invalid value: \"object\": must define a type of integration"}, + }, + { + title: "Datadog works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "DATADOG", + Datadog: &DatadogIntegration{ + APIKeySecret: api.LocalObjectReference{ + Name: "api-key-secretname", + }, + Region: "US", + }, + }, + }, + }, + { + title: "Microsoft Teams works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "MICROSOFT_TEAMS", + MicrosoftTeams: &MicrosoftTeamsIntegration{ + URLSecret: api.LocalObjectReference{ + Name: "url-secretname", + }, + }, + }, + }, + }, + { + title: "New Relic works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "NEW_RELIC", + NewRelic: &NewRelicIntegration{ + CredentialsSecret: api.LocalObjectReference{ + Name: "credentials-secretname", + }, + }, + }, + }, + }, + { + title: "Ops Genie works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "OPS_GENIE", + OpsGenie: &OpsGenieIntegration{ + APIKeySecret: api.LocalObjectReference{ + Name: "api-key-secretname", + }, + Region: "US", + }, + }, + }, + }, + { + title: "Pager Duty works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "PAGER_DUTY", + PagerDuty: &PagerDutyIntegration{ + ServiceKeySecret: api.LocalObjectReference{ + Name: "service-key-secretname", + }, + Region: "US", + }, + }, + }, + }, + { + title: "Prometheus duty works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "PROMETHEUS", + Prometheus: &PrometheusIntegration{ + PrometheusCredentials: api.LocalObjectReference{ + Name: "prometheus-credentials", + }, + ServiceDiscovery: "http", + }, + }, + }, + }, + { + title: "Slack works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "SLACK", + Slack: &SlackIntegration{ + APITokenSecret: api.LocalObjectReference{ + Name: "api-tooken-secretname", + }, + ChannelName: "channel", + TeamName: "team", + }, + }, + }, + }, + { + title: "Victor ops works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "VICTOR_OPS", + VictorOps: &VictorOpsIntegration{ + RoutingKey: api.LocalObjectReference{ + Name: "routing-key", + }, + APIKeySecret: "keys-secetname", + }, + }, + }, + }, + { + title: "Webhook works", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "WEBHOOK", + Webhook: &WebhookIntegration{ + URLSecret: api.LocalObjectReference{ + Name: "url-secretname", + }, + }, + }, + }, + }, + { + title: "Prometheus on Pager Duty type fails", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "PAGER_DUTY", + PagerDuty: &PagerDutyIntegration{}, + Prometheus: &PrometheusIntegration{ + PrometheusCredentials: api.LocalObjectReference{ + Name: "prometheus-credentials", + }, + ServiceDiscovery: "http", + }, + }, + }, + expectedErrors: []string{"spec: Invalid value: \"object\": only PROMETHEUS type may set prometheus fields"}, + }, + { + title: "Datadog on Webhook type fails", + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ + Type: "WEBHOOK", + Datadog: &DatadogIntegration{ + APIKeySecret: api.LocalObjectReference{ + Name: "api-key-secretname", + }, + Region: "US", + }, + Webhook: &WebhookIntegration{ + URLSecret: api.LocalObjectReference{ + Name: "url-secretname", + }, + }, + }, + }, + expectedErrors: []string{"spec: Invalid value: \"object\": only DATADOG type may set datadog fields"}, + }, + } { + t.Run(tc.title, func(t *testing.T) { + // inject a project to avoid other CEL validations being hit + tc.obj.Spec.ProjectRef = &common.ResourceRefNamespaced{Name: "some-project"} + unstructuredObject, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.obj) + require.NoError(t, err) + + crdPath := "../../config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml" + validator, err := cel.VersionValidatorFromFile(t, crdPath, "v1") + assert.NoError(t, err) + errs := validator(unstructuredObject, nil) + + require.Equal(t, tc.expectedErrors, cel.ErrorListAsStrings(errs)) + }) + } +} diff --git a/api/v1/project_reference_cel_test.go b/api/v1/project_reference_cel_test.go index b9797662ae..c8b554e3fb 100644 --- a/api/v1/project_reference_cel_test.go +++ b/api/v1/project_reference_cel_test.go @@ -77,6 +77,14 @@ var dualRefCRDs = []struct { }, filename: "atlas.mongodb.com_atlasnetworkpeerings.yaml", }, + { + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ // Avoid triggering integration specific validations + Type: "DATADOG", + }, + }, + filename: "atlas.mongodb.com_atlasthirdpartyintegrations.yaml", + }, } var testCases = []struct { diff --git a/api/v1/status/atlasthirdpartyintegration.go b/api/v1/status/atlasthirdpartyintegration.go new file mode 100644 index 0000000000..3bcf9a7e58 --- /dev/null +++ b/api/v1/status/atlasthirdpartyintegration.go @@ -0,0 +1,45 @@ +// Copyright 2025 MongoDB. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package status + +import ( + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" +) + +// AtlasThirdPartyIntegrationStatus holds the status of an integration +type AtlasThirdPartyIntegrationStatus struct { + api.Common `json:",inline"` + + // ID of the third party integration resource in Atlas + ID string `json:"id"` +} + +// +k8s:deepcopy-gen=false + +type IntegrationStatusOption func(status *AtlasThirdPartyIntegrationStatus) + +func NewAtlasThirdPartyIntegrationStatus(options ...IntegrationStatusOption) AtlasThirdPartyIntegrationStatus { + result := &AtlasThirdPartyIntegrationStatus{} + for i := range options { + options[i](result) + } + return *result +} + +func WithIntegrationID(id string) IntegrationStatusOption { + return func(i *AtlasThirdPartyIntegrationStatus) { + i.ID = id + } +} diff --git a/api/v1/status/zz_generated.deepcopy.go b/api/v1/status/zz_generated.deepcopy.go index ca3c274f20..5ede537a31 100644 --- a/api/v1/status/zz_generated.deepcopy.go +++ b/api/v1/status/zz_generated.deepcopy.go @@ -423,6 +423,22 @@ func (in *AtlasStreamInstanceStatus) DeepCopy() *AtlasStreamInstanceStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AtlasThirdPartyIntegrationStatus) DeepCopyInto(out *AtlasThirdPartyIntegrationStatus) { + *out = *in + in.Common.DeepCopyInto(&out.Common) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasThirdPartyIntegrationStatus. +func (in *AtlasThirdPartyIntegrationStatus) DeepCopy() *AtlasThirdPartyIntegrationStatus { + if in == nil { + return nil + } + out := new(AtlasThirdPartyIntegrationStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AzurePeeringStatus) DeepCopyInto(out *AzurePeeringStatus) { *out = *in diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index b591411454..2e3414e05c 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1925,6 +1925,126 @@ func (in *AtlasTeamList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AtlasThirdPartyIntegration) DeepCopyInto(out *AtlasThirdPartyIntegration) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasThirdPartyIntegration. +func (in *AtlasThirdPartyIntegration) DeepCopy() *AtlasThirdPartyIntegration { + if in == nil { + return nil + } + out := new(AtlasThirdPartyIntegration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AtlasThirdPartyIntegration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AtlasThirdPartyIntegrationList) DeepCopyInto(out *AtlasThirdPartyIntegrationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AtlasThirdPartyIntegration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasThirdPartyIntegrationList. +func (in *AtlasThirdPartyIntegrationList) DeepCopy() *AtlasThirdPartyIntegrationList { + if in == nil { + return nil + } + out := new(AtlasThirdPartyIntegrationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AtlasThirdPartyIntegrationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AtlasThirdPartyIntegrationSpec) DeepCopyInto(out *AtlasThirdPartyIntegrationSpec) { + *out = *in + in.ProjectDualReference.DeepCopyInto(&out.ProjectDualReference) + if in.Datadog != nil { + in, out := &in.Datadog, &out.Datadog + *out = new(DatadogIntegration) + (*in).DeepCopyInto(*out) + } + if in.MicrosoftTeams != nil { + in, out := &in.MicrosoftTeams, &out.MicrosoftTeams + *out = new(MicrosoftTeamsIntegration) + **out = **in + } + if in.NewRelic != nil { + in, out := &in.NewRelic, &out.NewRelic + *out = new(NewRelicIntegration) + **out = **in + } + if in.OpsGenie != nil { + in, out := &in.OpsGenie, &out.OpsGenie + *out = new(OpsGenieIntegration) + **out = **in + } + if in.PagerDuty != nil { + in, out := &in.PagerDuty, &out.PagerDuty + *out = new(PagerDutyIntegration) + **out = **in + } + if in.Prometheus != nil { + in, out := &in.Prometheus, &out.Prometheus + *out = new(PrometheusIntegration) + **out = **in + } + if in.Slack != nil { + in, out := &in.Slack, &out.Slack + *out = new(SlackIntegration) + **out = **in + } + if in.VictorOps != nil { + in, out := &in.VictorOps, &out.VictorOps + *out = new(VictorOpsIntegration) + **out = **in + } + if in.Webhook != nil { + in, out := &in.Webhook, &out.Webhook + *out = new(WebhookIntegration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasThirdPartyIntegrationSpec. +func (in *AtlasThirdPartyIntegrationSpec) DeepCopy() *AtlasThirdPartyIntegrationSpec { + if in == nil { + return nil + } + out := new(AtlasThirdPartyIntegrationSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Auditing) DeepCopyInto(out *Auditing) { *out = *in @@ -2483,6 +2603,32 @@ func (in *Database) DeepCopy() *Database { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatadogIntegration) DeepCopyInto(out *DatadogIntegration) { + *out = *in + out.APIKeySecret = in.APIKeySecret + if in.SendCollectionLatencyMetrics != nil { + in, out := &in.SendCollectionLatencyMetrics, &out.SendCollectionLatencyMetrics + *out = new(string) + **out = **in + } + if in.SendDatabaseMetrics != nil { + in, out := &in.SendDatabaseMetrics, &out.SendDatabaseMetrics + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatadogIntegration. +func (in *DatadogIntegration) DeepCopy() *DatadogIntegration { + if in == nil { + return nil + } + out := new(DatadogIntegration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskGB) DeepCopyInto(out *DiskGB) { *out = *in @@ -2806,6 +2952,22 @@ func (in *MetricThreshold) DeepCopy() *MetricThreshold { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MicrosoftTeamsIntegration) DeepCopyInto(out *MicrosoftTeamsIntegration) { + *out = *in + out.URLSecret = in.URLSecret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MicrosoftTeamsIntegration. +func (in *MicrosoftTeamsIntegration) DeepCopy() *MicrosoftTeamsIntegration { + if in == nil { + return nil + } + out := new(MicrosoftTeamsIntegration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkPeer) DeepCopyInto(out *NetworkPeer) { *out = *in @@ -2821,6 +2983,22 @@ func (in *NetworkPeer) DeepCopy() *NetworkPeer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NewRelicIntegration) DeepCopyInto(out *NewRelicIntegration) { + *out = *in + out.CredentialsSecret = in.CredentialsSecret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NewRelicIntegration. +func (in *NewRelicIntegration) DeepCopy() *NewRelicIntegration { + if in == nil { + return nil + } + out := new(NewRelicIntegration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Notification) DeepCopyInto(out *Notification) { *out = *in @@ -2862,6 +3040,38 @@ func (in *Notification) DeepCopy() *Notification { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpsGenieIntegration) DeepCopyInto(out *OpsGenieIntegration) { + *out = *in + out.APIKeySecret = in.APIKeySecret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpsGenieIntegration. +func (in *OpsGenieIntegration) DeepCopy() *OpsGenieIntegration { + if in == nil { + return nil + } + out := new(OpsGenieIntegration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PagerDutyIntegration) DeepCopyInto(out *PagerDutyIntegration) { + *out = *in + out.ServiceKeySecret = in.ServiceKeySecret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PagerDutyIntegration. +func (in *PagerDutyIntegration) DeepCopy() *PagerDutyIntegration { + if in == nil { + return nil + } + out := new(PagerDutyIntegration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateEndpoint) DeepCopyInto(out *PrivateEndpoint) { *out = *in @@ -3022,6 +3232,22 @@ func (in *ProjectSettings) DeepCopy() *ProjectSettings { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusIntegration) DeepCopyInto(out *PrometheusIntegration) { + *out = *in + out.PrometheusCredentials = in.PrometheusCredentials +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusIntegration. +func (in *PrometheusIntegration) DeepCopy() *PrometheusIntegration { + if in == nil { + return nil + } + out := new(PrometheusIntegration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Resource) DeepCopyInto(out *Resource) { *out = *in @@ -3299,6 +3525,22 @@ func (in *ServerlessSpec) DeepCopy() *ServerlessSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SlackIntegration) DeepCopyInto(out *SlackIntegration) { + *out = *in + out.APITokenSecret = in.APITokenSecret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SlackIntegration. +func (in *SlackIntegration) DeepCopy() *SlackIntegration { + if in == nil { + return nil + } + out := new(SlackIntegration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Source) DeepCopyInto(out *Source) { *out = *in @@ -3631,6 +3873,22 @@ func (in *VectorSearch) DeepCopy() *VectorSearch { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VictorOpsIntegration) DeepCopyInto(out *VictorOpsIntegration) { + *out = *in + out.RoutingKey = in.RoutingKey +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VictorOpsIntegration. +func (in *VictorOpsIntegration) DeepCopy() *VictorOpsIntegration { + if in == nil { + return nil + } + out := new(VictorOpsIntegration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *View) DeepCopyInto(out *View) { *out = *in @@ -3645,3 +3903,19 @@ func (in *View) DeepCopy() *View { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebhookIntegration) DeepCopyInto(out *WebhookIntegration) { + *out = *in + out.URLSecret = in.URLSecret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookIntegration. +func (in *WebhookIntegration) DeepCopy() *WebhookIntegration { + if in == nil { + return nil + } + out := new(WebhookIntegration) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml new file mode 100644 index 0000000000..d84c8053aa --- /dev/null +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -0,0 +1,392 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.17.2 + name: atlasthirdpartyintegrations.atlas.mongodb.com +spec: + group: atlas.mongodb.com + names: + kind: AtlasThirdPartyIntegration + listKind: AtlasThirdPartyIntegrationList + plural: atlasthirdpartyintegrations + singular: atlasthirdpartyintegration + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: AtlasThirdPartyIntegration is the Schema for the atlas 3rd party + inegrations API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: AtlasThirdPartyIntegrationSpec contains the expected configuration + for an integration + properties: + connectionSecret: + description: Name of the secret containing Atlas API private and public + keys + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + datadog: + description: Datadog contains the config fields for Datadog's Integration + properties: + apiKeySecret: + description: APIKeySecret holds the name of a secret containing + the datadog api key + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + region: + description: Region is the Datadog region + type: string + sendCollectionLatencyMetrics: + default: disabled + description: SendCollectionLatencyMetrics toggles sending collection + latency metrics + enum: + - enabled + - disabled + type: string + sendDatabaseMetrics: + default: disabled + description: |- + SendDatabaseMetrics toggles sending database metrics, + including database and collection names + enum: + - enabled + - disabled + type: string + required: + - apiKeySecret + - region + type: object + externalProjectRef: + description: |- + "externalProjectRef" holds the parent Atlas project ID. + Mutually exclusive with the "projectRef" field + properties: + id: + description: ID is the Atlas project ID + type: string + required: + - id + type: object + microsoftTeams: + description: MicrosoftTeams contains the config fields for Microsoft + Teams's Integration + properties: + urlSecret: + description: URLSecret holds the name of a secret containing the + microsoft teams secret URL + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + required: + - urlSecret + type: object + newRelic: + description: NewRelic contains the config fields for New Relic's Integration + properties: + credentialsSecret: + description: |- + CredentialsSecret holds the name of a secret containing new relic's credentials: + account id, license key, read and write tokens + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + required: + - credentialsSecret + type: object + opsGenie: + description: OpsGenie contains the config fields for Ops Genie's Integration + properties: + apiKeySecret: + description: APIKeySecret holds the name of a secret containing + Ops Genie's API key + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + region: + description: Region is the Ops Genie region + type: string + required: + - apiKeySecret + - region + type: object + pagerDuty: + description: PagerDuty contains the config fields for PagerDuty's + Integration + properties: + region: + description: Region is the Pager Duty region + type: string + serviceKeySecret: + description: ServiceKeySecret holds the name of a secret containing + Pager Duty service key + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + required: + - region + - serviceKeySecret + type: object + projectRef: + description: |- + "projectRef" is a reference to the parent AtlasProject resource. + Mutually exclusive with the "externalProjectRef" field + properties: + name: + description: Name is the name of the Kubernetes Resource + type: string + namespace: + description: Namespace is the namespace of the Kubernetes Resource + type: string + required: + - name + type: object + prometheus: + description: Prometheus contains the config fields for Prometheus's + Integration + properties: + prometheusCredentials: + description: |- + PrometheusCredentials holds the name of a secret containing the Prometheus + username & password + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + serviceDiscovery: + description: ServiceDiscovery to be used by Prometheus + enum: + - file + - http + type: string + required: + - prometheusCredentials + - serviceDiscovery + type: object + slack: + description: Slack contains the config fields for Slack's Integration + properties: + apiTokenSecret: + description: APITokenSecret holds the name of a secret containing + the Slack API token + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + channelName: + description: ChannelName to be used by Prometheus + type: string + teamName: + description: TeamName flags whether or not Prometheus integration + is enabled + type: string + required: + - apiTokenSecret + - channelName + - teamName + type: object + type: + description: Type of the integration + enum: + - DATADOG + - MICROSOFT_TEAMS + - NEW_RELIC + - OPS_GENIE + - PAGER_DUTY + - PROMETHEUS + - SLACK + - VICTOR_OPS + - WEBHOOK + type: string + victorOps: + description: VictorOps contains the config fields for VictorOps's + Integration + properties: + apiKeySecret: + description: APIKeySecret is the name of a secret containing Victor + Ops API key + type: string + routingKey: + description: RoutingKey holds VictorOps routing key + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + required: + - apiKeySecret + - routingKey + type: object + webhook: + description: Webhook contains the config fields for Webhook's Integration + properties: + urlSecret: + description: URLSecret holds the name of a secret containing Webhook + URL and secret + properties: + name: + description: |- + Name of the resource being referred to + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + required: + - urlSecret + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: must define only one project reference through externalProjectRef + or projectRef + rule: (has(self.externalProjectRef) && !has(self.projectRef)) || (!has(self.externalProjectRef) + && has(self.projectRef)) + - message: must define a local connection secret when referencing an external + project + rule: (has(self.externalProjectRef) && has(self.connectionSecret)) || + !has(self.externalProjectRef) + - message: must define a type of integration + rule: has(self.type) && self.type.size() != 0 + - message: only DATADOG type may set datadog fields + rule: '!has(self.datadog) || (self.type == ''DATADOG'' && has(self.datadog))' + - message: only MICROSOFT_TEAMS type may set microsoftTeams fields + rule: '!has(self.microsoftTeams) || (self.type == ''MICROSOFT_TEAMS'' + && has(self.microsoftTeams))' + - message: only NEW_RELIC type may set newRelic fields + rule: '!has(self.newRelic) || (self.type == ''NEW_RELIC'' && has(self.newRelic))' + - message: only OPS_GENIE type may set opsGenie fields + rule: '!has(self.opsGenie) || (self.type == ''OPS_GENIE'' && has(self.opsGenie))' + - message: only PROMETHEUS type may set prometheus fields + rule: '!has(self.prometheus) || (self.type == ''PROMETHEUS'' && has(self.prometheus))' + - message: only PAGER_DUTY type may set pagerDuty fields + rule: '!has(self.pagerDuty) || (self.type == ''PAGER_DUTY'' && has(self.pagerDuty))' + - message: only SLACK type may set slack fields + rule: '!has(self.slack) || (self.type == ''SLACK'' && has(self.slack))' + - message: only VICTOR_OPS type may set victorOps fields + rule: '!has(self.victorOps) || (self.type == ''VICTOR_OPS'' && has(self.victorOps))' + - message: only WEBHOOK type may set webhook fields + rule: '!has(self.webhook) || (self.type == ''WEBHOOK'' && has(self.webhook))' + status: + description: AtlasThirdPartyIntegrationStatus holds the status of an integration + properties: + conditions: + description: Conditions is the list of statuses showing the current + state of the Atlas Custom Resource + items: + description: Condition describes the state of an Atlas Custom Resource + at a certain point. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of Atlas Custom Resource condition. + type: string + required: + - status + - type + type: object + type: array + id: + description: ID of the third party integration resource in Atlas + type: string + observedGeneration: + description: |- + ObservedGeneration indicates the generation of the resource specification that the Atlas Operator is aware of. + The Atlas Operator updates this field to the 'metadata.generation' as soon as it starts reconciliation of the resource. + format: int64 + type: integer + required: + - conditions + - id + type: object + type: object + served: true + storage: true diff --git a/config/rbac/atlasthirdpartyintegration_editor_role.yaml b/config/rbac/atlasthirdpartyintegration_editor_role.yaml new file mode 100644 index 0000000000..5d747bb103 --- /dev/null +++ b/config/rbac/atlasthirdpartyintegration_editor_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to edit atlasthirdpartyintegrations. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasthirdpartyintegration-editor-role +rules: +- apiGroups: + - atlas.mongodb.com + resources: + - atlasthirdpartyintegrations + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - atlas.mongodb.com + resources: + - atlasthirdpartyintegrations/status + verbs: + - get diff --git a/config/rbac/atlasthirdpartyintegration_viewer_role.yaml b/config/rbac/atlasthirdpartyintegration_viewer_role.yaml new file mode 100644 index 0000000000..2e68684a4f --- /dev/null +++ b/config/rbac/atlasthirdpartyintegration_viewer_role.yaml @@ -0,0 +1,23 @@ +# permissions for end users to view atlasthirdpartyintegrations. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasthirdpartyintegration-viewer-role +rules: +- apiGroups: + - atlas.mongodb.com + resources: + - atlasthirdpartyintegrations + verbs: + - get + - list + - watch +- apiGroups: + - atlas.mongodb.com + resources: + - atlasthirdpartyintegrations/status + verbs: + - get diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index b012a9e1c5..0a5e0758c4 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -22,6 +22,8 @@ resources: # default, aiding admins in cluster management. Those roles are # not used by the Project itself. You can comment the following lines # if you do not want those helpers be installed with your Project. +- atlasthirdpartyintegration_editor_role.yaml +- atlasthirdpartyintegration_viewer_role.yaml - atlasnetworkcontainer_editor_role.yaml - atlasnetworkcontainer_viewer_role.yaml - atlasipaccesslist_editor_role.yaml diff --git a/config/samples/atlas_v1_atlasthirdpartyintegration.yaml b/config/samples/atlas_v1_atlasthirdpartyintegration.yaml new file mode 100644 index 0000000000..9342854ec7 --- /dev/null +++ b/config/samples/atlas_v1_atlasthirdpartyintegration.yaml @@ -0,0 +1,143 @@ +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: DATADOG + datadog: + apiKeySecret: + name: "secret-ref" + region: "string" +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + externalProjectRef: + id: "project-id" + connectionSecret: "conn-secret-ref" + type: MICROSOFT_TEAMS + microsoftTeams: + urlSecret: + name: "secret-ref" +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: NEW_RELIC + newRelic: + credentialsSecret: + name: "secret-ref" +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: OPS_GENIE + opsGenie: + apiKeySecret: + name: "secret-ref" + region: "string" +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: PAGER_DUTY + pagerDuty: + serviceKeySecret: + name: "secret-ref" + region: "string" +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: PROMETHEUS + prometheus: + prometheusCredentials: + name: "secret-ref" + serviceDiscovery: "string" + enabled: true +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: SLACK + slack: + apiTokenSecret: + name: "secret-ref" + channelName: "channel-name" + teamName: "team-name" +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: VICTOR_OPS + victorOps: + routingKey: + name: "string" + apiKeySecret: "secret-ref" +--- +apiVersion: atlas.mongodb.com/v1 +kind: AtlasIntegration +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-sample +spec: + projectRef: + name: my-atlas-project + type: WEBHOOK + webhook: + urlSecret: + name: "secret-ref" diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 7773335c1c..2642576192 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -19,4 +19,6 @@ resources: - atlas_v1_atlassearchindexconfigs.yaml - atlas_v1_atlasbackupcompliancepolicy.yaml - atlas_v1_atlascustomrole.yaml + - atlas_v1_atlasintegration.yaml + - atlas_v1_atlasthirdpartyintegration.yaml # +kubebuilder:scaffold:manifestskustomizesamples