From 89864872bc1ec8abbfe0cdd5a5763f65ed454f5d Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Mon, 10 Mar 2025 14:55:07 +0100 Subject: [PATCH 01/15] CLOUDP-305560: Add Atlas Integration CRD Signed-off-by: jose.vazquez --- PROJECT | 8 + api/v1/atlasintegration_types.go | 187 +++++++++++ api/v1/atlasintegration_types_test.go | 181 +++++++++++ api/v1/project_reference_cel_test.go | 8 + api/v1/status/integration.go | 31 ++ api/v1/status/zz_generated.deepcopy.go | 16 + api/v1/zz_generated.deepcopy.go | 260 +++++++++++++++ .../atlas.mongodb.com_atlasintegrations.yaml | 304 ++++++++++++++++++ config/rbac/atlasintegration_editor_role.yaml | 27 ++ config/rbac/atlasintegration_viewer_role.yaml | 23 ++ config/rbac/kustomization.yaml | 4 + config/samples/atlas_v1_atlasintegration.yaml | 9 + config/samples/kustomization.yaml | 1 + 13 files changed, 1059 insertions(+) create mode 100644 api/v1/atlasintegration_types.go create mode 100644 api/v1/atlasintegration_types_test.go create mode 100644 api/v1/status/integration.go create mode 100644 config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml create mode 100644 config/rbac/atlasintegration_editor_role.yaml create mode 100644 config/rbac/atlasintegration_viewer_role.yaml create mode 100644 config/samples/atlas_v1_atlasintegration.yaml diff --git a/PROJECT b/PROJECT index f428398354..d780789fe6 100644 --- a/PROJECT +++ b/PROJECT @@ -143,4 +143,12 @@ resources: kind: AtlasNetworkPeering path: github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1 version: v1 +- api: + crdVersion: v1 + namespaced: true + domain: mongodb.com + group: atlas + kind: AtlasIntegration + path: github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1 + version: v1 version: "3" diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go new file mode 100644 index 0000000000..1ffbfa48e4 --- /dev/null +++ b/api/v1/atlasintegration_types.go @@ -0,0 +1,187 @@ +/* +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/v1/status" +) + +func init() { + SchemeBuilder.Register(&AtlasIntegration{}, &AtlasIntegrationList{}) +} + +// +kubebuilder:object:root=true + +// AtlasIntegration is the Schema for the atlas 3rd party inegrations API. +type AtlasIntegration struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec AtlasIntegrationSpec `json:"spec,omitempty"` + Status status.AtlasIntegrationStatus `json:"status,omitempty"` +} + +// AtlasIntegrationSpec 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 AtlasIntegrationSpec struct { + ProjectDualReference `json:",inline"` + + // ID of the integration in Atlas. May be omitted to create a new one. + // +kubebuilder:validation:Optional + ID *string `json:"id"` + + // 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 *DatadogIntegration `json:"datadog,omitempty"` + + MicrosoftTeams *MicrosoftTeamsIntegration `json:"microsoftTeams,omitempty"` + + NewRelic *NewRelicIntegration `json:"newRelic,omitempty"` + + OpsGenie *OpsGenieIntegration `json:"opsGenie,omitempty"` + + PagerDuty *PagerDutyIntegration `json:"pagerDuty,omitempty"` + + Prometheus *PrometheusIntegration `json:"prometheus,omitempty"` + + Slack *SlackIntegration `json:"slack,omitempty"` + + VictorOps *VictorOpsIntegration `json:"victorOps,omitempty"` + + Webhook *WebhookIntegration `json:"webhook,omitempty"` +} + +type DatadogIntegration struct { + // APIKeySecret is the name of a secret containing the datadog api key + // +kubebuilder:validation:Required + APIKeySecret string `json:"apiKeySecret"` + + // Region is the Datadog region + // +kubebuilder:validation:Required + Region string `json:"region"` + + // SendCollectionLatencyMetrics flags whether or not to send collection latency metrics + // +kubebuilder:validation:Required + SendCollectionLatencyMetrics bool `json:"sendCollectionLatencyMetrics"` + + // SendDatabaseMetrics flags whether or not to send database metrics + // +kubebuilder:validation:Required + SendDatabaseMetrics bool `json:"sendDatabaseMetrics"` +} + +type MicrosoftTeamsIntegration struct { + // URLSecret is the name of a secret containing the microsoft teams secret URL + // +kubebuilder:validation:Required + URLSecret string `json:"apiKeySecret"` +} + +type NewRelicIntegration struct { + // CredentialsSecret is the name of a secret containing new relic's credentials: + // account id, license key, read and write tokens + // +kubebuilder:validation:Required + CredentialsSecret string `json:"credentialsSecret"` +} + +type OpsGenieIntegration struct { + // APIKeySecret is the name of a secret containing Ops Genie's API key + // +kubebuilder:validation:Required + APIKeySecret string `json:"apiKeySecret"` + + // Region is the Ops Genie region + // +kubebuilder:validation:Required + Region string `json:"region"` +} + +type PagerDutyIntegration struct { + // ServiceKeySecret is the name of a secret containing Pager Duty service key + // +kubebuilder:validation:Required + ServiceKeySecret string `json:"serviceKeySecret"` + + // Region is the Pager Duty region + // +kubebuilder:validation:Required + Region string `json:"region"` +} + +type PrometheusIntegration struct { + // UsernameSecret is the name of a secret containing the Prometehus username + // +kubebuilder:validation:Required + UsernameSecret string `json:"usernameSecret"` + + // ServiceDiscovery to be used by Prometheus + // +kubebuilder:validation:Enum:=file;http + // +kubebuilder:validation:Required + ServiceDiscovery string `json:"region"` + + // Enabled flags whether or not Prometheus integration is enabled + // +kubebuilder:validation:Required + Enabled bool `json:"sendCollectionLatencyMetrics"` +} + +type SlackIntegration struct { + // APITokenSecret is the name of a secret containing the Slack API token + // +kubebuilder:validation:Required + APITokenSecret string `json:"usernameSecret"` + + // 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 { + // KeysSecret is the name of a secret containing Victor Ops API and routing keys + // +kubebuilder:validation:Required + KeysSecret string `json:"keySecret"` +} + +type WebhookIntegration struct { + // URLSecret is the name of a secret containing Webhook URL and secret + // +kubebuilder:validation:Required + URLSecret string `json:"keySecret"` +} + +// +kubebuilder:object:root=true + +// AtlasIntegrationList contains a list of Atlas Integrations. +type AtlasIntegrationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []AtlasIntegration `json:"items"` +} + +func (i *AtlasIntegration) ProjectDualRef() *ProjectDualReference { + return &i.Spec.ProjectDualReference +} diff --git a/api/v1/atlasintegration_types_test.go b/api/v1/atlasintegration_types_test.go new file mode 100644 index 0000000000..e54b1a87b5 --- /dev/null +++ b/api/v1/atlasintegration_types_test.go @@ -0,0 +1,181 @@ +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/v1/common" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/cel" +) + +func TestIntegrationCELChecks(t *testing.T) { + for _, tc := range []struct { + title string + obj *AtlasIntegration + expectedErrors []string + }{ + { + title: "fails with no type", + obj: &AtlasIntegration{}, + expectedErrors: []string{"spec: Invalid value: \"object\": must define a type of integration"}, + }, + { + title: "Datadog works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "DATADOG", + Datadog: &DatadogIntegration{ + APIKeySecret: "api-key-secretname", + Region: "US", + SendCollectionLatencyMetrics: false, + SendDatabaseMetrics: false, + }, + }, + }, + }, + { + title: "Microsoft Teams works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "MICROSOFT_TEAMS", + MicrosoftTeams: &MicrosoftTeamsIntegration{ + URLSecret: "url-secretname", + }, + }, + }, + }, + { + title: "New Relic works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "NEW_RELIC", + NewRelic: &NewRelicIntegration{ + CredentialsSecret: "credentials-secretname", + }, + }, + }, + }, + { + title: "Ops Genie works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "OPS_GENIE", + OpsGenie: &OpsGenieIntegration{ + APIKeySecret: "api-key-secretname", + Region: "US", + }, + }, + }, + }, + { + title: "Pager Duty works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "PAGER_DUTY", + PagerDuty: &PagerDutyIntegration{ + ServiceKeySecret: "service-key-secretname", + Region: "US", + }, + }, + }, + }, + { + title: "Prometheus duty works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "PROMETHEUS", + Prometheus: &PrometheusIntegration{ + UsernameSecret: "username-secretname", + ServiceDiscovery: "http", + Enabled: false, + }, + }, + }, + }, + { + title: "Slack works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "SLACK", + Slack: &SlackIntegration{ + APITokenSecret: "api-tooken-secretname", + ChannelName: "channel", + TeamName: "team", + }, + }, + }, + }, + { + title: "Victor ops works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "VICTOR_OPS", + VictorOps: &VictorOpsIntegration{ + KeysSecret: "keys-secetname", + }, + }, + }, + }, + { + title: "Webhook works", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "WEBHOOK", + Webhook: &WebhookIntegration{ + URLSecret: "url-secretname", + }, + }, + }, + }, + { + title: "Prometheus on Pager Duty type fails", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "PAGER_DUTY", + PagerDuty: &PagerDutyIntegration{}, + Prometheus: &PrometheusIntegration{ + UsernameSecret: "username-secretname", + ServiceDiscovery: "http", + Enabled: false, + }, + }, + }, + expectedErrors: []string{"spec: Invalid value: \"object\": only PROMETHEUS type may set prometheus fields"}, + }, + { + title: "Datadog on Webhook type fails", + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ + Type: "WEBHOOK", + Datadog: &DatadogIntegration{ + APIKeySecret: "api-key-secretname", + Region: "US", + SendCollectionLatencyMetrics: false, + SendDatabaseMetrics: false, + }, + Webhook: &WebhookIntegration{ + URLSecret: "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_atlasintegrations.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 604d763602..24ac7a24d1 100644 --- a/api/v1/project_reference_cel_test.go +++ b/api/v1/project_reference_cel_test.go @@ -63,6 +63,14 @@ var dualRefCRDs = []struct { }, filename: "atlas.mongodb.com_atlasnetworkpeerings.yaml", }, + { + obj: &AtlasIntegration{ + Spec: AtlasIntegrationSpec{ // Avoid triggering integration specific validations + Type: "DATADOG", + }, + }, + filename: "atlas.mongodb.com_atlasintegrations.yaml", + }, } var testCases = []struct { diff --git a/api/v1/status/integration.go b/api/v1/status/integration.go new file mode 100644 index 0000000000..946819b8c8 --- /dev/null +++ b/api/v1/status/integration.go @@ -0,0 +1,31 @@ +package status + +import ( + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" +) + +// AtlasIntegrationStatus holds the status of an integration +type AtlasIntegrationStatus struct { + api.Common `json:",inline"` + + // ID of the 3rd party integration resource in Atlas + ID string `json:"id"` +} + +// +k8s:deepcopy-gen=false + +type IntegrationStatusOption func(status *AtlasIntegrationStatus) + +func NewAtlasIntegrationStatus(options ...IntegrationStatusOption) AtlasIntegrationStatus { + result := &AtlasIntegrationStatus{} + for i := range options { + options[i](result) + } + return *result +} + +func WithIntegrationID(id string) IntegrationStatusOption { + return func(i *AtlasIntegrationStatus) { + i.ID = id + } +} diff --git a/api/v1/status/zz_generated.deepcopy.go b/api/v1/status/zz_generated.deepcopy.go index dfa79b2633..2a1a668b2d 100644 --- a/api/v1/status/zz_generated.deepcopy.go +++ b/api/v1/status/zz_generated.deepcopy.go @@ -197,6 +197,22 @@ func (in *AtlasIPAccessListStatus) DeepCopy() *AtlasIPAccessListStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AtlasIntegrationStatus) DeepCopyInto(out *AtlasIntegrationStatus) { + *out = *in + in.Common.DeepCopyInto(&out.Common) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasIntegrationStatus. +func (in *AtlasIntegrationStatus) DeepCopy() *AtlasIntegrationStatus { + if in == nil { + return nil + } + out := new(AtlasIntegrationStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AtlasNetworkContainerStatus) DeepCopyInto(out *AtlasNetworkContainerStatus) { *out = *in diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 1eb7108046..899d2e080d 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1106,6 +1106,131 @@ func (in *AtlasIPAccessListSpec) DeepCopy() *AtlasIPAccessListSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AtlasIntegration) DeepCopyInto(out *AtlasIntegration) { + *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 AtlasIntegration. +func (in *AtlasIntegration) DeepCopy() *AtlasIntegration { + if in == nil { + return nil + } + out := new(AtlasIntegration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AtlasIntegration) 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 *AtlasIntegrationList) DeepCopyInto(out *AtlasIntegrationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AtlasIntegration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasIntegrationList. +func (in *AtlasIntegrationList) DeepCopy() *AtlasIntegrationList { + if in == nil { + return nil + } + out := new(AtlasIntegrationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AtlasIntegrationList) 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 *AtlasIntegrationSpec) DeepCopyInto(out *AtlasIntegrationSpec) { + *out = *in + in.ProjectDualReference.DeepCopyInto(&out.ProjectDualReference) + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Datadog != nil { + in, out := &in.Datadog, &out.Datadog + *out = new(DatadogIntegration) + **out = **in + } + 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 AtlasIntegrationSpec. +func (in *AtlasIntegrationSpec) DeepCopy() *AtlasIntegrationSpec { + if in == nil { + return nil + } + out := new(AtlasIntegrationSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AtlasNetworkContainer) DeepCopyInto(out *AtlasNetworkContainer) { *out = *in @@ -2477,6 +2602,21 @@ 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 +} + +// 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 @@ -2800,6 +2940,21 @@ 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 +} + +// 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 @@ -2815,6 +2970,21 @@ 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 +} + +// 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 @@ -2856,6 +3026,36 @@ 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 +} + +// 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 +} + +// 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 @@ -3016,6 +3216,21 @@ 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 +} + +// 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 @@ -3293,6 +3508,21 @@ 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 +} + +// 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 @@ -3625,6 +3855,21 @@ 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 +} + +// 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 @@ -3639,3 +3884,18 @@ 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 +} + +// 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_atlasintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml new file mode 100644 index 0000000000..2f90afc530 --- /dev/null +++ b/config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml @@ -0,0 +1,304 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: atlasintegrations.atlas.mongodb.com +spec: + group: atlas.mongodb.com + names: + kind: AtlasIntegration + listKind: AtlasIntegrationList + plural: atlasintegrations + singular: atlasintegration + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: AtlasIntegration 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: AtlasIntegrationSpec 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: + properties: + apiKeySecret: + description: APIKeySecret is the name of a secret containing the + datadog api key + type: string + region: + description: Region is the Datadog region + type: string + sendCollectionLatencyMetrics: + description: SendCollectionLatencyMetrics flags whether or not + to send collection latency metrics + type: boolean + sendDatabaseMetrics: + description: SendDatabaseMetrics flags whether or not to send + database metrics + type: boolean + required: + - apiKeySecret + - region + - sendCollectionLatencyMetrics + - sendDatabaseMetrics + 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 + id: + description: ID of the integration in Atlas. May be omitted to create + a new one. + type: string + microsoftTeams: + properties: + apiKeySecret: + description: URLSecret is the name of a secret containing the + microsoft teams secret URL + type: string + required: + - apiKeySecret + type: object + newRelic: + properties: + credentialsSecret: + description: |- + CredentialsSecret is the name of a secret containing new relic's credentials: + account id, license key, read and write tokens + type: string + required: + - credentialsSecret + type: object + opsGenie: + properties: + apiKeySecret: + description: APIKeySecret is the name of a secret containing Ops + Genie's API key + type: string + region: + description: Region is the Ops Genie region + type: string + required: + - apiKeySecret + - region + type: object + pagerDuty: + properties: + region: + description: Region is the Pager Duty region + type: string + serviceKeySecret: + description: ServiceKeySecret is the name of a secret containing + Pager Duty service key + type: string + 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: + properties: + region: + description: ServiceDiscovery to be used by Prometheus + enum: + - file + - http + type: string + sendCollectionLatencyMetrics: + description: Enabled flags whether or not Prometheus integration + is enabled + type: boolean + usernameSecret: + description: UsernameSecret is the name of a secret containing + the Prometehus username + type: string + required: + - region + - sendCollectionLatencyMetrics + - usernameSecret + type: object + slack: + properties: + channelName: + description: ChannelName to be used by Prometheus + type: string + teamName: + description: TeamName flags whether or not Prometheus integration + is enabled + type: string + usernameSecret: + description: APITokenSecret is the name of a secret containing + the Slack API token + type: string + required: + - channelName + - teamName + - usernameSecret + 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: + properties: + keySecret: + description: KeysSecret is the name of a secret containing Victor + Ops API and routing keys + type: string + required: + - keySecret + type: object + webhook: + properties: + keySecret: + description: URLSecret is the name of a secret containing Webhook + URL and secret + type: string + required: + - keySecret + 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: AtlasIntegrationStatus 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 3rd 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/atlasintegration_editor_role.yaml b/config/rbac/atlasintegration_editor_role.yaml new file mode 100644 index 0000000000..841c3e15c2 --- /dev/null +++ b/config/rbac/atlasintegration_editor_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to edit atlasintegrations. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-editor-role +rules: +- apiGroups: + - atlas.mongodb.com + resources: + - atlasintegrations + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - atlas.mongodb.com + resources: + - atlasintegrations/status + verbs: + - get diff --git a/config/rbac/atlasintegration_viewer_role.yaml b/config/rbac/atlasintegration_viewer_role.yaml new file mode 100644 index 0000000000..82740ee0d8 --- /dev/null +++ b/config/rbac/atlasintegration_viewer_role.yaml @@ -0,0 +1,23 @@ +# permissions for end users to view atlasintegrations. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: mongodb-atlas-kubernetes + app.kubernetes.io/managed-by: kustomize + name: atlasintegration-viewer-role +rules: +- apiGroups: + - atlas.mongodb.com + resources: + - atlasintegrations + verbs: + - get + - list + - watch +- apiGroups: + - atlas.mongodb.com + resources: + - atlasintegrations/status + verbs: + - get diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index b012a9e1c5..4d1047f65b 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. +- atlasintegration_editor_role.yaml +- atlasintegration_viewer_role.yaml - atlasnetworkcontainer_editor_role.yaml - atlasnetworkcontainer_viewer_role.yaml - atlasipaccesslist_editor_role.yaml @@ -52,3 +54,5 @@ resources: - atlasdeployment_viewer_role.yaml - atlasnetworkpeering_editor_role.yaml - atlasnetworkpeering_viewer_role.yaml + + diff --git a/config/samples/atlas_v1_atlasintegration.yaml b/config/samples/atlas_v1_atlasintegration.yaml new file mode 100644 index 0000000000..a1e3810331 --- /dev/null +++ b/config/samples/atlas_v1_atlasintegration.yaml @@ -0,0 +1,9 @@ +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: + # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 8c532fc5a4..e1434ce2d0 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -11,4 +11,5 @@ resources: - atlas_v1_atlasipaccesslist.yaml - atlas_v1_atlasnetworkcontainer.yaml - atlas_v1_atlasnetworkpeering.yaml + - atlas_v1_atlasintegration.yaml # +kubebuilder:scaffold:manifestskustomizesamples From 09a1459dc374e8d5c238a147690db27f6c0a7e7d Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 15:47:51 +0100 Subject: [PATCH 02/15] Rename main CRD types Signed-off-by: jose.vazquez --- api/v1/atlasintegration_types.go | 22 +- api/v1/atlasintegration_types_test.go | 48 +-- api/v1/project_reference_cel_test.go | 4 +- api/v1/status/integration.go | 12 +- api/v1/status/zz_generated.deepcopy.go | 32 +- api/v1/zz_generated.deepcopy.go | 250 +++++++------- ...ngodb.com_atlasthirdpartyintegrations.yaml | 304 ++++++++++++++++++ 7 files changed, 488 insertions(+), 184 deletions(-) create mode 100644 config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go index 1ffbfa48e4..4007e1a2e2 100644 --- a/api/v1/atlasintegration_types.go +++ b/api/v1/atlasintegration_types.go @@ -23,21 +23,21 @@ import ( ) func init() { - SchemeBuilder.Register(&AtlasIntegration{}, &AtlasIntegrationList{}) + SchemeBuilder.Register(&AtlasThirdPartyIntegration{}, &AtlasThirdPartyIntegrationList{}) } // +kubebuilder:object:root=true -// AtlasIntegration is the Schema for the atlas 3rd party inegrations API. -type AtlasIntegration struct { +// AtlasThirdPartyIntegration is the Schema for the atlas 3rd party inegrations API. +type AtlasThirdPartyIntegration struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec AtlasIntegrationSpec `json:"spec,omitempty"` - Status status.AtlasIntegrationStatus `json:"status,omitempty"` + Spec AtlasThirdPartyIntegrationSpec `json:"spec,omitempty"` + Status status.AtlasThirdPartyIntegrationStatus `json:"status,omitempty"` } -// AtlasIntegrationSpec contains the expected configuration for an integration +// 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" @@ -50,7 +50,7 @@ type AtlasIntegration struct { // +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 AtlasIntegrationSpec struct { +type AtlasThirdPartyIntegrationSpec struct { ProjectDualReference `json:",inline"` // ID of the integration in Atlas. May be omitted to create a new one. @@ -175,13 +175,13 @@ type WebhookIntegration struct { // +kubebuilder:object:root=true -// AtlasIntegrationList contains a list of Atlas Integrations. -type AtlasIntegrationList struct { +// AtlasThirdPartyIntegrationList contains a list of Atlas Integrations. +type AtlasThirdPartyIntegrationList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []AtlasIntegration `json:"items"` + Items []AtlasThirdPartyIntegration `json:"items"` } -func (i *AtlasIntegration) ProjectDualRef() *ProjectDualReference { +func (i *AtlasThirdPartyIntegration) ProjectDualRef() *ProjectDualReference { return &i.Spec.ProjectDualReference } diff --git a/api/v1/atlasintegration_types_test.go b/api/v1/atlasintegration_types_test.go index e54b1a87b5..e1f8d3c958 100644 --- a/api/v1/atlasintegration_types_test.go +++ b/api/v1/atlasintegration_types_test.go @@ -14,18 +14,18 @@ import ( func TestIntegrationCELChecks(t *testing.T) { for _, tc := range []struct { title string - obj *AtlasIntegration + obj *AtlasThirdPartyIntegration expectedErrors []string }{ { title: "fails with no type", - obj: &AtlasIntegration{}, + obj: &AtlasThirdPartyIntegration{}, expectedErrors: []string{"spec: Invalid value: \"object\": must define a type of integration"}, }, { title: "Datadog works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "DATADOG", Datadog: &DatadogIntegration{ APIKeySecret: "api-key-secretname", @@ -38,8 +38,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Microsoft Teams works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "MICROSOFT_TEAMS", MicrosoftTeams: &MicrosoftTeamsIntegration{ URLSecret: "url-secretname", @@ -49,8 +49,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "New Relic works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "NEW_RELIC", NewRelic: &NewRelicIntegration{ CredentialsSecret: "credentials-secretname", @@ -60,8 +60,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Ops Genie works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "OPS_GENIE", OpsGenie: &OpsGenieIntegration{ APIKeySecret: "api-key-secretname", @@ -72,8 +72,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Pager Duty works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "PAGER_DUTY", PagerDuty: &PagerDutyIntegration{ ServiceKeySecret: "service-key-secretname", @@ -84,8 +84,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Prometheus duty works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "PROMETHEUS", Prometheus: &PrometheusIntegration{ UsernameSecret: "username-secretname", @@ -97,8 +97,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Slack works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "SLACK", Slack: &SlackIntegration{ APITokenSecret: "api-tooken-secretname", @@ -110,8 +110,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Victor ops works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "VICTOR_OPS", VictorOps: &VictorOpsIntegration{ KeysSecret: "keys-secetname", @@ -121,8 +121,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Webhook works", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "WEBHOOK", Webhook: &WebhookIntegration{ URLSecret: "url-secretname", @@ -132,8 +132,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Prometheus on Pager Duty type fails", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "PAGER_DUTY", PagerDuty: &PagerDutyIntegration{}, Prometheus: &PrometheusIntegration{ @@ -147,8 +147,8 @@ func TestIntegrationCELChecks(t *testing.T) { }, { title: "Datadog on Webhook type fails", - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ Type: "WEBHOOK", Datadog: &DatadogIntegration{ APIKeySecret: "api-key-secretname", diff --git a/api/v1/project_reference_cel_test.go b/api/v1/project_reference_cel_test.go index 24ac7a24d1..5429f00e2a 100644 --- a/api/v1/project_reference_cel_test.go +++ b/api/v1/project_reference_cel_test.go @@ -64,8 +64,8 @@ var dualRefCRDs = []struct { filename: "atlas.mongodb.com_atlasnetworkpeerings.yaml", }, { - obj: &AtlasIntegration{ - Spec: AtlasIntegrationSpec{ // Avoid triggering integration specific validations + obj: &AtlasThirdPartyIntegration{ + Spec: AtlasThirdPartyIntegrationSpec{ // Avoid triggering integration specific validations Type: "DATADOG", }, }, diff --git a/api/v1/status/integration.go b/api/v1/status/integration.go index 946819b8c8..a0d40b8f61 100644 --- a/api/v1/status/integration.go +++ b/api/v1/status/integration.go @@ -4,8 +4,8 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" ) -// AtlasIntegrationStatus holds the status of an integration -type AtlasIntegrationStatus struct { +// AtlasThirdPartyIntegrationStatus holds the status of an integration +type AtlasThirdPartyIntegrationStatus struct { api.Common `json:",inline"` // ID of the 3rd party integration resource in Atlas @@ -14,10 +14,10 @@ type AtlasIntegrationStatus struct { // +k8s:deepcopy-gen=false -type IntegrationStatusOption func(status *AtlasIntegrationStatus) +type IntegrationStatusOption func(status *AtlasThirdPartyIntegrationStatus) -func NewAtlasIntegrationStatus(options ...IntegrationStatusOption) AtlasIntegrationStatus { - result := &AtlasIntegrationStatus{} +func NewAtlasThirdPartyIntegrationStatus(options ...IntegrationStatusOption) AtlasThirdPartyIntegrationStatus { + result := &AtlasThirdPartyIntegrationStatus{} for i := range options { options[i](result) } @@ -25,7 +25,7 @@ func NewAtlasIntegrationStatus(options ...IntegrationStatusOption) AtlasIntegrat } func WithIntegrationID(id string) IntegrationStatusOption { - return func(i *AtlasIntegrationStatus) { + 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 2a1a668b2d..293ef919a1 100644 --- a/api/v1/status/zz_generated.deepcopy.go +++ b/api/v1/status/zz_generated.deepcopy.go @@ -197,22 +197,6 @@ func (in *AtlasIPAccessListStatus) DeepCopy() *AtlasIPAccessListStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AtlasIntegrationStatus) DeepCopyInto(out *AtlasIntegrationStatus) { - *out = *in - in.Common.DeepCopyInto(&out.Common) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasIntegrationStatus. -func (in *AtlasIntegrationStatus) DeepCopy() *AtlasIntegrationStatus { - if in == nil { - return nil - } - out := new(AtlasIntegrationStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AtlasNetworkContainerStatus) DeepCopyInto(out *AtlasNetworkContainerStatus) { *out = *in @@ -433,6 +417,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 899d2e080d..d466c25a01 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1106,131 +1106,6 @@ func (in *AtlasIPAccessListSpec) DeepCopy() *AtlasIPAccessListSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AtlasIntegration) DeepCopyInto(out *AtlasIntegration) { - *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 AtlasIntegration. -func (in *AtlasIntegration) DeepCopy() *AtlasIntegration { - if in == nil { - return nil - } - out := new(AtlasIntegration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *AtlasIntegration) 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 *AtlasIntegrationList) DeepCopyInto(out *AtlasIntegrationList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]AtlasIntegration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtlasIntegrationList. -func (in *AtlasIntegrationList) DeepCopy() *AtlasIntegrationList { - if in == nil { - return nil - } - out := new(AtlasIntegrationList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *AtlasIntegrationList) 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 *AtlasIntegrationSpec) DeepCopyInto(out *AtlasIntegrationSpec) { - *out = *in - in.ProjectDualReference.DeepCopyInto(&out.ProjectDualReference) - if in.ID != nil { - in, out := &in.ID, &out.ID - *out = new(string) - **out = **in - } - if in.Datadog != nil { - in, out := &in.Datadog, &out.Datadog - *out = new(DatadogIntegration) - **out = **in - } - 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 AtlasIntegrationSpec. -func (in *AtlasIntegrationSpec) DeepCopy() *AtlasIntegrationSpec { - if in == nil { - return nil - } - out := new(AtlasIntegrationSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AtlasNetworkContainer) DeepCopyInto(out *AtlasNetworkContainer) { *out = *in @@ -2044,6 +1919,131 @@ 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.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Datadog != nil { + in, out := &in.Datadog, &out.Datadog + *out = new(DatadogIntegration) + **out = **in + } + 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 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..5a754bb584 --- /dev/null +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -0,0 +1,304 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + 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: + properties: + apiKeySecret: + description: APIKeySecret is the name of a secret containing the + datadog api key + type: string + region: + description: Region is the Datadog region + type: string + sendCollectionLatencyMetrics: + description: SendCollectionLatencyMetrics flags whether or not + to send collection latency metrics + type: boolean + sendDatabaseMetrics: + description: SendDatabaseMetrics flags whether or not to send + database metrics + type: boolean + required: + - apiKeySecret + - region + - sendCollectionLatencyMetrics + - sendDatabaseMetrics + 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 + id: + description: ID of the integration in Atlas. May be omitted to create + a new one. + type: string + microsoftTeams: + properties: + apiKeySecret: + description: URLSecret is the name of a secret containing the + microsoft teams secret URL + type: string + required: + - apiKeySecret + type: object + newRelic: + properties: + credentialsSecret: + description: |- + CredentialsSecret is the name of a secret containing new relic's credentials: + account id, license key, read and write tokens + type: string + required: + - credentialsSecret + type: object + opsGenie: + properties: + apiKeySecret: + description: APIKeySecret is the name of a secret containing Ops + Genie's API key + type: string + region: + description: Region is the Ops Genie region + type: string + required: + - apiKeySecret + - region + type: object + pagerDuty: + properties: + region: + description: Region is the Pager Duty region + type: string + serviceKeySecret: + description: ServiceKeySecret is the name of a secret containing + Pager Duty service key + type: string + 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: + properties: + region: + description: ServiceDiscovery to be used by Prometheus + enum: + - file + - http + type: string + sendCollectionLatencyMetrics: + description: Enabled flags whether or not Prometheus integration + is enabled + type: boolean + usernameSecret: + description: UsernameSecret is the name of a secret containing + the Prometehus username + type: string + required: + - region + - sendCollectionLatencyMetrics + - usernameSecret + type: object + slack: + properties: + channelName: + description: ChannelName to be used by Prometheus + type: string + teamName: + description: TeamName flags whether or not Prometheus integration + is enabled + type: string + usernameSecret: + description: APITokenSecret is the name of a secret containing + the Slack API token + type: string + required: + - channelName + - teamName + - usernameSecret + 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: + properties: + keySecret: + description: KeysSecret is the name of a secret containing Victor + Ops API and routing keys + type: string + required: + - keySecret + type: object + webhook: + properties: + keySecret: + description: URLSecret is the name of a secret containing Webhook + URL and secret + type: string + required: + - keySecret + 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 3rd 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 From 0a10b24d590ba38d826b22f55c9d8aa17be21ef4 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 15:53:16 +0100 Subject: [PATCH 03/15] Remove ID from spec --- api/v1/atlasintegration_types.go | 4 ---- api/v1/status/integration.go | 2 +- api/v1/zz_generated.deepcopy.go | 5 ----- .../atlas.mongodb.com_atlasthirdpartyintegrations.yaml | 6 +----- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go index 4007e1a2e2..facc4a68b9 100644 --- a/api/v1/atlasintegration_types.go +++ b/api/v1/atlasintegration_types.go @@ -53,10 +53,6 @@ type AtlasThirdPartyIntegration struct { type AtlasThirdPartyIntegrationSpec struct { ProjectDualReference `json:",inline"` - // ID of the integration in Atlas. May be omitted to create a new one. - // +kubebuilder:validation:Optional - ID *string `json:"id"` - // Type of the integration // +kubebuilder:validation:Enum:=DATADOG;MICROSOFT_TEAMS;NEW_RELIC;OPS_GENIE;PAGER_DUTY;PROMETHEUS;SLACK;VICTOR_OPS;WEBHOOK // +kubebuilder:validation:Required diff --git a/api/v1/status/integration.go b/api/v1/status/integration.go index a0d40b8f61..d7af6bf962 100644 --- a/api/v1/status/integration.go +++ b/api/v1/status/integration.go @@ -8,7 +8,7 @@ import ( type AtlasThirdPartyIntegrationStatus struct { api.Common `json:",inline"` - // ID of the 3rd party integration resource in Atlas + // ID of the third party integration resource in Atlas ID string `json:"id"` } diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index d466c25a01..6c707d6b28 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1982,11 +1982,6 @@ func (in *AtlasThirdPartyIntegrationList) DeepCopyObject() runtime.Object { func (in *AtlasThirdPartyIntegrationSpec) DeepCopyInto(out *AtlasThirdPartyIntegrationSpec) { *out = *in in.ProjectDualReference.DeepCopyInto(&out.ProjectDualReference) - if in.ID != nil { - in, out := &in.ID, &out.ID - *out = new(string) - **out = **in - } if in.Datadog != nil { in, out := &in.Datadog, &out.Datadog *out = new(DatadogIntegration) diff --git a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml index 5a754bb584..874698b267 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -87,10 +87,6 @@ spec: required: - id type: object - id: - description: ID of the integration in Atlas. May be omitted to create - a new one. - type: string microsoftTeams: properties: apiKeySecret: @@ -287,7 +283,7 @@ spec: type: object type: array id: - description: ID of the 3rd party integration resource in Atlas + description: ID of the third party integration resource in Atlas type: string observedGeneration: description: |- From 8fec04099f3a9c015d177bc8dd868f3367d8a2b8 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 16:04:43 +0100 Subject: [PATCH 04/15] Fix sub fields comments --- api/v1/atlasintegration_types.go | 18 ++++++++++++++++++ ...ongodb.com_atlasthirdpartyintegrations.yaml | 13 +++++++++++++ 2 files changed, 31 insertions(+) diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go index facc4a68b9..4bb91b4632 100644 --- a/api/v1/atlasintegration_types.go +++ b/api/v1/atlasintegration_types.go @@ -58,22 +58,40 @@ type AtlasThirdPartyIntegrationSpec struct { // +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"` } diff --git a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml index 874698b267..d9e73a574e 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -54,6 +54,7 @@ spec: - name type: object datadog: + description: Datadog contains the config fields for Datadog's Integration properties: apiKeySecret: description: APIKeySecret is the name of a secret containing the @@ -88,6 +89,8 @@ spec: - id type: object microsoftTeams: + description: MicrosoftTeams contains the config fields for Microsoft + Teams's Integration properties: apiKeySecret: description: URLSecret is the name of a secret containing the @@ -97,6 +100,7 @@ spec: - apiKeySecret type: object newRelic: + description: NewRelic contains the config fields for New Relic's Integration properties: credentialsSecret: description: |- @@ -107,6 +111,7 @@ spec: - credentialsSecret type: object opsGenie: + description: OpsGenie contains the config fields for Ops Genie's Integration properties: apiKeySecret: description: APIKeySecret is the name of a secret containing Ops @@ -120,6 +125,8 @@ spec: - region type: object pagerDuty: + description: PagerDuty contains the config fields for PagerDuty's + Integration properties: region: description: Region is the Pager Duty region @@ -147,6 +154,8 @@ spec: - name type: object prometheus: + description: Prometheus contains the config fields for Prometheus's + Integration properties: region: description: ServiceDiscovery to be used by Prometheus @@ -168,6 +177,7 @@ spec: - usernameSecret type: object slack: + description: Slack contains the config fields for Slack's Integration properties: channelName: description: ChannelName to be used by Prometheus @@ -199,6 +209,8 @@ spec: - WEBHOOK type: string victorOps: + description: VictorOps contains the config fields for VictorOps's + Integration properties: keySecret: description: KeysSecret is the name of a secret containing Victor @@ -208,6 +220,7 @@ spec: - keySecret type: object webhook: + description: Webhook contains the config fields for Webhook's Integration properties: keySecret: description: URLSecret is the name of a secret containing Webhook From 7b68dae7c126dfff77baa607cb5bdfc91a44b071 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 16:28:09 +0100 Subject: [PATCH 05/15] Fix flag types --- api/v1/atlasintegration_types.go | 17 +++++++++----- api/v1/atlasintegration_types_test.go | 12 ++++------ api/v1/zz_generated.deepcopy.go | 12 +++++++++- ...ngodb.com_atlasthirdpartyintegrations.yaml | 23 ++++++++++++------- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go index 4bb91b4632..0effb32240 100644 --- a/api/v1/atlasintegration_types.go +++ b/api/v1/atlasintegration_types.go @@ -104,13 +104,18 @@ type DatadogIntegration struct { // +kubebuilder:validation:Required Region string `json:"region"` - // SendCollectionLatencyMetrics flags whether or not to send collection latency metrics - // +kubebuilder:validation:Required - SendCollectionLatencyMetrics bool `json:"sendCollectionLatencyMetrics"` + // SendCollectionLatencyMetrics toggles sending collection latency metrics + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=enabled;disabled + // +kubebuilder:default:=disabled + SendCollectionLatencyMetrics *string `json:"sendCollectionLatencyMetrics"` - // SendDatabaseMetrics flags whether or not to send database metrics - // +kubebuilder:validation:Required - SendDatabaseMetrics bool `json:"sendDatabaseMetrics"` + // 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 { diff --git a/api/v1/atlasintegration_types_test.go b/api/v1/atlasintegration_types_test.go index e1f8d3c958..f80a6ace8b 100644 --- a/api/v1/atlasintegration_types_test.go +++ b/api/v1/atlasintegration_types_test.go @@ -28,10 +28,8 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "DATADOG", Datadog: &DatadogIntegration{ - APIKeySecret: "api-key-secretname", - Region: "US", - SendCollectionLatencyMetrics: false, - SendDatabaseMetrics: false, + APIKeySecret: "api-key-secretname", + Region: "US", }, }, }, @@ -151,10 +149,8 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "WEBHOOK", Datadog: &DatadogIntegration{ - APIKeySecret: "api-key-secretname", - Region: "US", - SendCollectionLatencyMetrics: false, - SendDatabaseMetrics: false, + APIKeySecret: "api-key-secretname", + Region: "US", }, Webhook: &WebhookIntegration{ URLSecret: "url-secretname", diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 6c707d6b28..a422e2b9f8 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1985,7 +1985,7 @@ func (in *AtlasThirdPartyIntegrationSpec) DeepCopyInto(out *AtlasThirdPartyInteg if in.Datadog != nil { in, out := &in.Datadog, &out.Datadog *out = new(DatadogIntegration) - **out = **in + (*in).DeepCopyInto(*out) } if in.MicrosoftTeams != nil { in, out := &in.MicrosoftTeams, &out.MicrosoftTeams @@ -2600,6 +2600,16 @@ func (in *Database) DeepCopy() *Database { // 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 + 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. diff --git a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml index d9e73a574e..ffffee930e 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -64,18 +64,25 @@ spec: description: Region is the Datadog region type: string sendCollectionLatencyMetrics: - description: SendCollectionLatencyMetrics flags whether or not - to send collection latency metrics - type: boolean + default: disabled + description: SendCollectionLatencyMetrics toggles sending collection + latency metrics + enum: + - enabled + - disabled + type: string sendDatabaseMetrics: - description: SendDatabaseMetrics flags whether or not to send - database metrics - type: boolean + default: disabled + description: |- + SendDatabaseMetrics toggles sending database metrics, + including database and collection names + enum: + - enabled + - disabled + type: string required: - apiKeySecret - region - - sendCollectionLatencyMetrics - - sendDatabaseMetrics type: object externalProjectRef: description: |- From 0a7682fcab7d0eed614cad85024cc62f0738742a Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 17:17:48 +0100 Subject: [PATCH 06/15] Fix EOLs --- config/rbac/kustomization.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index 4d1047f65b..faa2e0440b 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -54,5 +54,3 @@ resources: - atlasdeployment_viewer_role.yaml - atlasnetworkpeering_editor_role.yaml - atlasnetworkpeering_viewer_role.yaml - - From e3d0d6aa5d800ef5f66f71a2160933344f6bbd21 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 17:18:11 +0100 Subject: [PATCH 07/15] Fix Prometheus credentials ref --- api/v1/atlasintegration_types.go | 5 +++-- api/v1/atlasintegration_types_test.go | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go index 0effb32240..09d7450adc 100644 --- a/api/v1/atlasintegration_types.go +++ b/api/v1/atlasintegration_types.go @@ -152,9 +152,10 @@ type PagerDutyIntegration struct { } type PrometheusIntegration struct { - // UsernameSecret is the name of a secret containing the Prometehus username + // PrometheusCredentials is the name of a secret containing the Prometheus + // username & password // +kubebuilder:validation:Required - UsernameSecret string `json:"usernameSecret"` + PrometheusCredentials string `json:"prometheusCredentials"` // ServiceDiscovery to be used by Prometheus // +kubebuilder:validation:Enum:=file;http diff --git a/api/v1/atlasintegration_types_test.go b/api/v1/atlasintegration_types_test.go index f80a6ace8b..e945c5d29c 100644 --- a/api/v1/atlasintegration_types_test.go +++ b/api/v1/atlasintegration_types_test.go @@ -86,9 +86,9 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "PROMETHEUS", Prometheus: &PrometheusIntegration{ - UsernameSecret: "username-secretname", - ServiceDiscovery: "http", - Enabled: false, + PrometheusCredentials: "prometheus-credentials", + ServiceDiscovery: "http", + Enabled: false, }, }, }, @@ -135,9 +135,9 @@ func TestIntegrationCELChecks(t *testing.T) { Type: "PAGER_DUTY", PagerDuty: &PagerDutyIntegration{}, Prometheus: &PrometheusIntegration{ - UsernameSecret: "username-secretname", - ServiceDiscovery: "http", - Enabled: false, + PrometheusCredentials: "prometheus-credentials", + ServiceDiscovery: "http", + Enabled: false, }, }, }, From 12462b9d7327f141f8d81a611cad933b9ba17f90 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 17:21:43 +0100 Subject: [PATCH 08/15] Fix VictorOps fields --- api/v1/atlasintegration_types.go | 8 ++++++-- api/v1/atlasintegration_types_test.go | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go index 09d7450adc..3aea5854af 100644 --- a/api/v1/atlasintegration_types.go +++ b/api/v1/atlasintegration_types.go @@ -182,9 +182,13 @@ type SlackIntegration struct { } type VictorOpsIntegration struct { - // KeysSecret is the name of a secret containing Victor Ops API and routing keys + // RoutingKey is VictorOps routing key // +kubebuilder:validation:Required - KeysSecret string `json:"keySecret"` + RoutingKey string `json:"routingKey"` + + // APIKeySecret is the name of a secret containing Victor Ops API key + // +kubebuilder:validation:Required + APIKeySecret string `json:"apiKeySecret"` } type WebhookIntegration struct { diff --git a/api/v1/atlasintegration_types_test.go b/api/v1/atlasintegration_types_test.go index e945c5d29c..fda9a2ce9d 100644 --- a/api/v1/atlasintegration_types_test.go +++ b/api/v1/atlasintegration_types_test.go @@ -112,7 +112,8 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "VICTOR_OPS", VictorOps: &VictorOpsIntegration{ - KeysSecret: "keys-secetname", + RoutingKey: "routing-key", + APIKeySecret: "keys-secetname", }, }, }, From cb28f1c1e558eba08995162d6395b4deb757c5a8 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 17:54:31 +0100 Subject: [PATCH 09/15] Fix sample and YAML annotated names --- api/v1/atlasintegration_types.go | 10 +- config/samples/atlas_v1_atlasintegration.yaml | 127 +++++++++++++++++- 2 files changed, 131 insertions(+), 6 deletions(-) diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasintegration_types.go index 3aea5854af..0c8ad42057 100644 --- a/api/v1/atlasintegration_types.go +++ b/api/v1/atlasintegration_types.go @@ -121,7 +121,7 @@ type DatadogIntegration struct { type MicrosoftTeamsIntegration struct { // URLSecret is the name of a secret containing the microsoft teams secret URL // +kubebuilder:validation:Required - URLSecret string `json:"apiKeySecret"` + URLSecret string `json:"urlSecret"` } type NewRelicIntegration struct { @@ -160,17 +160,17 @@ type PrometheusIntegration struct { // ServiceDiscovery to be used by Prometheus // +kubebuilder:validation:Enum:=file;http // +kubebuilder:validation:Required - ServiceDiscovery string `json:"region"` + ServiceDiscovery string `json:"serviceDiscovery"` // Enabled flags whether or not Prometheus integration is enabled // +kubebuilder:validation:Required - Enabled bool `json:"sendCollectionLatencyMetrics"` + Enabled bool `json:"enabled"` } type SlackIntegration struct { // APITokenSecret is the name of a secret containing the Slack API token // +kubebuilder:validation:Required - APITokenSecret string `json:"usernameSecret"` + APITokenSecret string `json:"apiTokenSecret"` // ChannelName to be used by Prometheus // +kubebuilder:validation:Required @@ -194,7 +194,7 @@ type VictorOpsIntegration struct { type WebhookIntegration struct { // URLSecret is the name of a secret containing Webhook URL and secret // +kubebuilder:validation:Required - URLSecret string `json:"keySecret"` + URLSecret string `json:"urlSecret"` } // +kubebuilder:object:root=true diff --git a/config/samples/atlas_v1_atlasintegration.yaml b/config/samples/atlas_v1_atlasintegration.yaml index a1e3810331..754d4c5a2f 100644 --- a/config/samples/atlas_v1_atlasintegration.yaml +++ b/config/samples/atlas_v1_atlasintegration.yaml @@ -6,4 +6,129 @@ metadata: app.kubernetes.io/managed-by: kustomize name: atlasintegration-sample spec: - # TODO(user): Add fields here + projectRef: + name: my-atlas-project + type: DATADOG + datadog: + apiKeySecret: "datadog-apikey-secret-ref" + region: "datadog-region" +--- +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: "ms-url-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: "ms-url-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: "ops-genie-apikey-secret-ref" + region: "ops-genie-region" +--- +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: "pagerduty-service-key-secret-ref" + region: "pagerduty-region" +--- +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: "prometheus-credentials-ref" + serviceDiscovery: "serice-discovery" + 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: "slack-apitoken-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: "victorops-routingkey" + apiKeySecret: "victorops-apikey-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: "webhook-urlsecret-ref" From 67fa744298d5d9fe57a4f89070749f8691384926 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Wed, 19 Mar 2025 18:04:54 +0100 Subject: [PATCH 10/15] Fix examples and YAML field names --- ...ngodb.com_atlasthirdpartyintegrations.yaml | 55 ++++++++++--------- config/samples/atlas_v1_atlasintegration.yaml | 28 +++++----- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml index ffffee930e..90cf98d50a 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -99,12 +99,12 @@ spec: description: MicrosoftTeams contains the config fields for Microsoft Teams's Integration properties: - apiKeySecret: + urlSecret: description: URLSecret is the name of a secret containing the microsoft teams secret URL type: string required: - - apiKeySecret + - urlSecret type: object newRelic: description: NewRelic contains the config fields for New Relic's Integration @@ -164,28 +164,33 @@ spec: description: Prometheus contains the config fields for Prometheus's Integration properties: - region: + enabled: + description: Enabled flags whether or not Prometheus integration + is enabled + type: boolean + prometheusCredentials: + description: |- + PrometheusCredentials is the name of a secret containing the Prometheus + username & password + type: string + serviceDiscovery: description: ServiceDiscovery to be used by Prometheus enum: - file - http type: string - sendCollectionLatencyMetrics: - description: Enabled flags whether or not Prometheus integration - is enabled - type: boolean - usernameSecret: - description: UsernameSecret is the name of a secret containing - the Prometehus username - type: string required: - - region - - sendCollectionLatencyMetrics - - usernameSecret + - enabled + - prometheusCredentials + - serviceDiscovery type: object slack: description: Slack contains the config fields for Slack's Integration properties: + apiTokenSecret: + description: APITokenSecret is the name of a secret containing + the Slack API token + type: string channelName: description: ChannelName to be used by Prometheus type: string @@ -193,14 +198,10 @@ spec: description: TeamName flags whether or not Prometheus integration is enabled type: string - usernameSecret: - description: APITokenSecret is the name of a secret containing - the Slack API token - type: string required: + - apiTokenSecret - channelName - teamName - - usernameSecret type: object type: description: Type of the integration @@ -219,22 +220,26 @@ spec: description: VictorOps contains the config fields for VictorOps's Integration properties: - keySecret: - description: KeysSecret is the name of a secret containing Victor - Ops API and routing keys + apiKeySecret: + description: APIKeySecret is the name of a secret containing Victor + Ops API key + type: string + routingKey: + description: RoutingKey is VictorOps routing key type: string required: - - keySecret + - apiKeySecret + - routingKey type: object webhook: description: Webhook contains the config fields for Webhook's Integration properties: - keySecret: + urlSecret: description: URLSecret is the name of a secret containing Webhook URL and secret type: string required: - - keySecret + - urlSecret type: object required: - type diff --git a/config/samples/atlas_v1_atlasintegration.yaml b/config/samples/atlas_v1_atlasintegration.yaml index 754d4c5a2f..81ce2dde92 100644 --- a/config/samples/atlas_v1_atlasintegration.yaml +++ b/config/samples/atlas_v1_atlasintegration.yaml @@ -10,8 +10,8 @@ spec: name: my-atlas-project type: DATADOG datadog: - apiKeySecret: "datadog-apikey-secret-ref" - region: "datadog-region" + apiKeySecret: "secret-ref" + region: "string" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -26,7 +26,7 @@ spec: connectionSecret: "conn-secret-ref" type: MICROSOFT_TEAMS microsoftTeams: - urlSecret: "ms-url-secret-ref" + urlSecret: "secret-ref" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -40,7 +40,7 @@ spec: name: my-atlas-project type: NEW_RELIC newRelic: - credentialsSecret: "ms-url-secret-ref" + credentialsSecret: "secret-ref" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -54,8 +54,8 @@ spec: name: my-atlas-project type: OPS_GENIE opsGenie: - apiKeySecret: "ops-genie-apikey-secret-ref" - region: "ops-genie-region" + apiKeySecret: "secret-ref" + region: "string" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -69,8 +69,8 @@ spec: name: my-atlas-project type: PAGER_DUTY pagerDuty: - serviceKeySecret: "pagerduty-service-key-secret-ref" - region: "pagerduty-region" + serviceKeySecret: "secret-ref" + region: "string" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -84,8 +84,8 @@ spec: name: my-atlas-project type: PROMETHEUS prometheus: - prometheusCredentials: "prometheus-credentials-ref" - serviceDiscovery: "serice-discovery" + prometheusCredentials: "secret-ref" + serviceDiscovery: "string" enabled: true --- apiVersion: atlas.mongodb.com/v1 @@ -100,7 +100,7 @@ spec: name: my-atlas-project type: SLACK slack: - apiTokenSecret: "slack-apitoken-secret-ref" + apiTokenSecret: "secret-ref" channelName: "channel-name" teamName: "team-name" --- @@ -116,8 +116,8 @@ spec: name: my-atlas-project type: VICTOR_OPS victorOps: - routingKey: "victorops-routingkey" - apiKeySecret: "victorops-apikey-secret-ref" + routingKey: "string" + apiKeySecret: "secret-ref" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -131,4 +131,4 @@ spec: name: my-atlas-project type: WEBHOOK webhook: - urlSecret: "webhook-urlsecret-ref" + urlSecret: "secret-ref" From 0a8dfcf206f581ab1f4e16daf325eee0708f188c Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Thu, 20 Mar 2025 14:20:13 +0100 Subject: [PATCH 11/15] Raname CRD files as per renamed kind Signed-off-by: jose.vazquez --- PROJECT | 2 +- ...go => atlasthirdpartyintegration_types.go} | 0 ... atlasthirdpartyintegration_types_test.go} | 2 +- api/v1/project_reference_cel_test.go | 2 +- .../atlas.mongodb.com_atlasintegrations.yaml | 304 ------------------ ...lasthirdpartyintegration_editor_role.yaml} | 8 +- ...lasthirdpartyintegration_viewer_role.yaml} | 8 +- config/rbac/kustomization.yaml | 2 + ... atlas_v1_atlasthirdpartyintegration.yaml} | 0 config/samples/kustomization.yaml | 2 +- 10 files changed, 14 insertions(+), 316 deletions(-) rename api/v1/{atlasintegration_types.go => atlasthirdpartyintegration_types.go} (100%) rename api/v1/{atlasintegration_types_test.go => atlasthirdpartyintegration_types_test.go} (98%) delete mode 100644 config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml rename config/rbac/{atlasintegration_editor_role.yaml => atlasthirdpartyintegration_editor_role.yaml} (67%) rename config/rbac/{atlasintegration_viewer_role.yaml => atlasthirdpartyintegration_viewer_role.yaml} (64%) rename config/samples/{atlas_v1_atlasintegration.yaml => atlas_v1_atlasthirdpartyintegration.yaml} (100%) diff --git a/PROJECT b/PROJECT index d780789fe6..9b03ce7792 100644 --- a/PROJECT +++ b/PROJECT @@ -148,7 +148,7 @@ resources: namespaced: true domain: mongodb.com group: atlas - kind: AtlasIntegration + kind: AtlasThirdPartyIntegration path: github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1 version: v1 version: "3" diff --git a/api/v1/atlasintegration_types.go b/api/v1/atlasthirdpartyintegration_types.go similarity index 100% rename from api/v1/atlasintegration_types.go rename to api/v1/atlasthirdpartyintegration_types.go diff --git a/api/v1/atlasintegration_types_test.go b/api/v1/atlasthirdpartyintegration_types_test.go similarity index 98% rename from api/v1/atlasintegration_types_test.go rename to api/v1/atlasthirdpartyintegration_types_test.go index fda9a2ce9d..3fbccfa580 100644 --- a/api/v1/atlasintegration_types_test.go +++ b/api/v1/atlasthirdpartyintegration_types_test.go @@ -167,7 +167,7 @@ func TestIntegrationCELChecks(t *testing.T) { unstructuredObject, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.obj) require.NoError(t, err) - crdPath := "../../config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml" + crdPath := "../../config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml" validator, err := cel.VersionValidatorFromFile(t, crdPath, "v1") assert.NoError(t, err) errs := validator(unstructuredObject, nil) diff --git a/api/v1/project_reference_cel_test.go b/api/v1/project_reference_cel_test.go index 5429f00e2a..453c39c1cb 100644 --- a/api/v1/project_reference_cel_test.go +++ b/api/v1/project_reference_cel_test.go @@ -69,7 +69,7 @@ var dualRefCRDs = []struct { Type: "DATADOG", }, }, - filename: "atlas.mongodb.com_atlasintegrations.yaml", + filename: "atlas.mongodb.com_atlasthirdpartyintegrations.yaml", }, } diff --git a/config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml deleted file mode 100644 index 2f90afc530..0000000000 --- a/config/crd/bases/atlas.mongodb.com_atlasintegrations.yaml +++ /dev/null @@ -1,304 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - name: atlasintegrations.atlas.mongodb.com -spec: - group: atlas.mongodb.com - names: - kind: AtlasIntegration - listKind: AtlasIntegrationList - plural: atlasintegrations - singular: atlasintegration - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: AtlasIntegration 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: AtlasIntegrationSpec 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: - properties: - apiKeySecret: - description: APIKeySecret is the name of a secret containing the - datadog api key - type: string - region: - description: Region is the Datadog region - type: string - sendCollectionLatencyMetrics: - description: SendCollectionLatencyMetrics flags whether or not - to send collection latency metrics - type: boolean - sendDatabaseMetrics: - description: SendDatabaseMetrics flags whether or not to send - database metrics - type: boolean - required: - - apiKeySecret - - region - - sendCollectionLatencyMetrics - - sendDatabaseMetrics - 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 - id: - description: ID of the integration in Atlas. May be omitted to create - a new one. - type: string - microsoftTeams: - properties: - apiKeySecret: - description: URLSecret is the name of a secret containing the - microsoft teams secret URL - type: string - required: - - apiKeySecret - type: object - newRelic: - properties: - credentialsSecret: - description: |- - CredentialsSecret is the name of a secret containing new relic's credentials: - account id, license key, read and write tokens - type: string - required: - - credentialsSecret - type: object - opsGenie: - properties: - apiKeySecret: - description: APIKeySecret is the name of a secret containing Ops - Genie's API key - type: string - region: - description: Region is the Ops Genie region - type: string - required: - - apiKeySecret - - region - type: object - pagerDuty: - properties: - region: - description: Region is the Pager Duty region - type: string - serviceKeySecret: - description: ServiceKeySecret is the name of a secret containing - Pager Duty service key - type: string - 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: - properties: - region: - description: ServiceDiscovery to be used by Prometheus - enum: - - file - - http - type: string - sendCollectionLatencyMetrics: - description: Enabled flags whether or not Prometheus integration - is enabled - type: boolean - usernameSecret: - description: UsernameSecret is the name of a secret containing - the Prometehus username - type: string - required: - - region - - sendCollectionLatencyMetrics - - usernameSecret - type: object - slack: - properties: - channelName: - description: ChannelName to be used by Prometheus - type: string - teamName: - description: TeamName flags whether or not Prometheus integration - is enabled - type: string - usernameSecret: - description: APITokenSecret is the name of a secret containing - the Slack API token - type: string - required: - - channelName - - teamName - - usernameSecret - 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: - properties: - keySecret: - description: KeysSecret is the name of a secret containing Victor - Ops API and routing keys - type: string - required: - - keySecret - type: object - webhook: - properties: - keySecret: - description: URLSecret is the name of a secret containing Webhook - URL and secret - type: string - required: - - keySecret - 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: AtlasIntegrationStatus 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 3rd 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/atlasintegration_editor_role.yaml b/config/rbac/atlasthirdpartyintegration_editor_role.yaml similarity index 67% rename from config/rbac/atlasintegration_editor_role.yaml rename to config/rbac/atlasthirdpartyintegration_editor_role.yaml index 841c3e15c2..5d747bb103 100644 --- a/config/rbac/atlasintegration_editor_role.yaml +++ b/config/rbac/atlasthirdpartyintegration_editor_role.yaml @@ -1,16 +1,16 @@ -# permissions for end users to edit atlasintegrations. +# 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: atlasintegration-editor-role + name: atlasthirdpartyintegration-editor-role rules: - apiGroups: - atlas.mongodb.com resources: - - atlasintegrations + - atlasthirdpartyintegrations verbs: - create - delete @@ -22,6 +22,6 @@ rules: - apiGroups: - atlas.mongodb.com resources: - - atlasintegrations/status + - atlasthirdpartyintegrations/status verbs: - get diff --git a/config/rbac/atlasintegration_viewer_role.yaml b/config/rbac/atlasthirdpartyintegration_viewer_role.yaml similarity index 64% rename from config/rbac/atlasintegration_viewer_role.yaml rename to config/rbac/atlasthirdpartyintegration_viewer_role.yaml index 82740ee0d8..2e68684a4f 100644 --- a/config/rbac/atlasintegration_viewer_role.yaml +++ b/config/rbac/atlasthirdpartyintegration_viewer_role.yaml @@ -1,16 +1,16 @@ -# permissions for end users to view atlasintegrations. +# 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: atlasintegration-viewer-role + name: atlasthirdpartyintegration-viewer-role rules: - apiGroups: - atlas.mongodb.com resources: - - atlasintegrations + - atlasthirdpartyintegrations verbs: - get - list @@ -18,6 +18,6 @@ rules: - apiGroups: - atlas.mongodb.com resources: - - atlasintegrations/status + - atlasthirdpartyintegrations/status verbs: - get diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index faa2e0440b..df27ca1b2f 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 - atlasintegration_editor_role.yaml - atlasintegration_viewer_role.yaml - atlasnetworkcontainer_editor_role.yaml diff --git a/config/samples/atlas_v1_atlasintegration.yaml b/config/samples/atlas_v1_atlasthirdpartyintegration.yaml similarity index 100% rename from config/samples/atlas_v1_atlasintegration.yaml rename to config/samples/atlas_v1_atlasthirdpartyintegration.yaml diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index e1434ce2d0..41fda3eae9 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -11,5 +11,5 @@ resources: - atlas_v1_atlasipaccesslist.yaml - atlas_v1_atlasnetworkcontainer.yaml - atlas_v1_atlasnetworkpeering.yaml - - atlas_v1_atlasintegration.yaml + - atlas_v1_atlasthirdpartyintegration.yaml # +kubebuilder:scaffold:manifestskustomizesamples From 8337527f3ce1ea4e84e19113d146a0340743e05e Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Fri, 21 Mar 2025 15:11:58 +0100 Subject: [PATCH 12/15] Remove duplicate RBAC entries after rename --- config/rbac/kustomization.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index df27ca1b2f..0a5e0758c4 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -24,8 +24,6 @@ resources: # if you do not want those helpers be installed with your Project. - atlasthirdpartyintegration_editor_role.yaml - atlasthirdpartyintegration_viewer_role.yaml -- atlasintegration_editor_role.yaml -- atlasintegration_viewer_role.yaml - atlasnetworkcontainer_editor_role.yaml - atlasnetworkcontainer_viewer_role.yaml - atlasipaccesslist_editor_role.yaml From f4039775b398ad337486213b2ece465913a142db Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Fri, 21 Mar 2025 15:13:06 +0100 Subject: [PATCH 13/15] Rename status go file --- api/v1/status/{integration.go => atlasthirdpartyintegration.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename api/v1/status/{integration.go => atlasthirdpartyintegration.go} (100%) diff --git a/api/v1/status/integration.go b/api/v1/status/atlasthirdpartyintegration.go similarity index 100% rename from api/v1/status/integration.go rename to api/v1/status/atlasthirdpartyintegration.go From befb2fde7a410666e5832d5616bcd27cc64c8bb5 Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Fri, 21 Mar 2025 15:17:40 +0100 Subject: [PATCH 14/15] remove enabled prometheus flag --- api/v1/atlasthirdpartyintegration_types.go | 4 ---- api/v1/atlasthirdpartyintegration_types_test.go | 2 -- .../bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml | 5 ----- 3 files changed, 11 deletions(-) diff --git a/api/v1/atlasthirdpartyintegration_types.go b/api/v1/atlasthirdpartyintegration_types.go index 0c8ad42057..999ba50cd3 100644 --- a/api/v1/atlasthirdpartyintegration_types.go +++ b/api/v1/atlasthirdpartyintegration_types.go @@ -161,10 +161,6 @@ type PrometheusIntegration struct { // +kubebuilder:validation:Enum:=file;http // +kubebuilder:validation:Required ServiceDiscovery string `json:"serviceDiscovery"` - - // Enabled flags whether or not Prometheus integration is enabled - // +kubebuilder:validation:Required - Enabled bool `json:"enabled"` } type SlackIntegration struct { diff --git a/api/v1/atlasthirdpartyintegration_types_test.go b/api/v1/atlasthirdpartyintegration_types_test.go index 3fbccfa580..f71b919ebb 100644 --- a/api/v1/atlasthirdpartyintegration_types_test.go +++ b/api/v1/atlasthirdpartyintegration_types_test.go @@ -88,7 +88,6 @@ func TestIntegrationCELChecks(t *testing.T) { Prometheus: &PrometheusIntegration{ PrometheusCredentials: "prometheus-credentials", ServiceDiscovery: "http", - Enabled: false, }, }, }, @@ -138,7 +137,6 @@ func TestIntegrationCELChecks(t *testing.T) { Prometheus: &PrometheusIntegration{ PrometheusCredentials: "prometheus-credentials", ServiceDiscovery: "http", - Enabled: false, }, }, }, diff --git a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml index 90cf98d50a..ba87e54461 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -164,10 +164,6 @@ spec: description: Prometheus contains the config fields for Prometheus's Integration properties: - enabled: - description: Enabled flags whether or not Prometheus integration - is enabled - type: boolean prometheusCredentials: description: |- PrometheusCredentials is the name of a secret containing the Prometheus @@ -180,7 +176,6 @@ spec: - http type: string required: - - enabled - prometheusCredentials - serviceDiscovery type: object From 64fafbd844f9fb97f7e609f1ac61ef8b18a870db Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Mon, 24 Mar 2025 17:20:17 +0100 Subject: [PATCH 15/15] Use local object ref for all secrets --- api/v1/atlasthirdpartyintegration_types.go | 37 +++--- .../atlasthirdpartyintegration_types_test.go | 65 ++++++---- api/v1/zz_generated.deepcopy.go | 9 ++ ...ngodb.com_atlasthirdpartyintegrations.yaml | 112 ++++++++++++++---- .../atlas_v1_atlasthirdpartyintegration.yaml | 27 +++-- 5 files changed, 183 insertions(+), 67 deletions(-) diff --git a/api/v1/atlasthirdpartyintegration_types.go b/api/v1/atlasthirdpartyintegration_types.go index 999ba50cd3..9e58d31650 100644 --- a/api/v1/atlasthirdpartyintegration_types.go +++ b/api/v1/atlasthirdpartyintegration_types.go @@ -19,6 +19,7 @@ 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" ) @@ -96,9 +97,9 @@ type AtlasThirdPartyIntegrationSpec struct { } type DatadogIntegration struct { - // APIKeySecret is the name of a secret containing the datadog api key + // APIKeySecret holds the name of a secret containing the datadog api key // +kubebuilder:validation:Required - APIKeySecret string `json:"apiKeySecret"` + APIKeySecret api.LocalObjectReference `json:"apiKeySecret"` // Region is the Datadog region // +kubebuilder:validation:Required @@ -119,22 +120,22 @@ type DatadogIntegration struct { } type MicrosoftTeamsIntegration struct { - // URLSecret is the name of a secret containing the microsoft teams secret URL + // URLSecret holds the name of a secret containing the microsoft teams secret URL // +kubebuilder:validation:Required - URLSecret string `json:"urlSecret"` + URLSecret api.LocalObjectReference `json:"urlSecret"` } type NewRelicIntegration struct { - // CredentialsSecret is the name of a secret containing new relic's credentials: + // CredentialsSecret holds the name of a secret containing new relic's credentials: // account id, license key, read and write tokens // +kubebuilder:validation:Required - CredentialsSecret string `json:"credentialsSecret"` + CredentialsSecret api.LocalObjectReference `json:"credentialsSecret"` } type OpsGenieIntegration struct { - // APIKeySecret is the name of a secret containing Ops Genie's API key + // APIKeySecret holds the name of a secret containing Ops Genie's API key // +kubebuilder:validation:Required - APIKeySecret string `json:"apiKeySecret"` + APIKeySecret api.LocalObjectReference `json:"apiKeySecret"` // Region is the Ops Genie region // +kubebuilder:validation:Required @@ -142,9 +143,9 @@ type OpsGenieIntegration struct { } type PagerDutyIntegration struct { - // ServiceKeySecret is the name of a secret containing Pager Duty service key + // ServiceKeySecret holds the name of a secret containing Pager Duty service key // +kubebuilder:validation:Required - ServiceKeySecret string `json:"serviceKeySecret"` + ServiceKeySecret api.LocalObjectReference `json:"serviceKeySecret"` // Region is the Pager Duty region // +kubebuilder:validation:Required @@ -152,10 +153,10 @@ type PagerDutyIntegration struct { } type PrometheusIntegration struct { - // PrometheusCredentials is the name of a secret containing the Prometheus + // PrometheusCredentials holds the name of a secret containing the Prometheus // username & password // +kubebuilder:validation:Required - PrometheusCredentials string `json:"prometheusCredentials"` + PrometheusCredentials api.LocalObjectReference `json:"prometheusCredentials"` // ServiceDiscovery to be used by Prometheus // +kubebuilder:validation:Enum:=file;http @@ -164,9 +165,9 @@ type PrometheusIntegration struct { } type SlackIntegration struct { - // APITokenSecret is the name of a secret containing the Slack API token + // APITokenSecret holds the name of a secret containing the Slack API token // +kubebuilder:validation:Required - APITokenSecret string `json:"apiTokenSecret"` + APITokenSecret api.LocalObjectReference `json:"apiTokenSecret"` // ChannelName to be used by Prometheus // +kubebuilder:validation:Required @@ -178,9 +179,9 @@ type SlackIntegration struct { } type VictorOpsIntegration struct { - // RoutingKey is VictorOps routing key + // RoutingKey holds VictorOps routing key // +kubebuilder:validation:Required - RoutingKey string `json:"routingKey"` + RoutingKey api.LocalObjectReference `json:"routingKey"` // APIKeySecret is the name of a secret containing Victor Ops API key // +kubebuilder:validation:Required @@ -188,9 +189,9 @@ type VictorOpsIntegration struct { } type WebhookIntegration struct { - // URLSecret is the name of a secret containing Webhook URL and secret + // URLSecret holds the name of a secret containing Webhook URL and secret // +kubebuilder:validation:Required - URLSecret string `json:"urlSecret"` + URLSecret api.LocalObjectReference `json:"urlSecret"` } // +kubebuilder:object:root=true diff --git a/api/v1/atlasthirdpartyintegration_types_test.go b/api/v1/atlasthirdpartyintegration_types_test.go index f71b919ebb..f0fac26636 100644 --- a/api/v1/atlasthirdpartyintegration_types_test.go +++ b/api/v1/atlasthirdpartyintegration_types_test.go @@ -7,6 +7,7 @@ import ( "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" ) @@ -28,8 +29,10 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "DATADOG", Datadog: &DatadogIntegration{ - APIKeySecret: "api-key-secretname", - Region: "US", + APIKeySecret: api.LocalObjectReference{ + Name: "api-key-secretname", + }, + Region: "US", }, }, }, @@ -40,7 +43,9 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "MICROSOFT_TEAMS", MicrosoftTeams: &MicrosoftTeamsIntegration{ - URLSecret: "url-secretname", + URLSecret: api.LocalObjectReference{ + Name: "url-secretname", + }, }, }, }, @@ -51,7 +56,9 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "NEW_RELIC", NewRelic: &NewRelicIntegration{ - CredentialsSecret: "credentials-secretname", + CredentialsSecret: api.LocalObjectReference{ + Name: "credentials-secretname", + }, }, }, }, @@ -62,8 +69,10 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "OPS_GENIE", OpsGenie: &OpsGenieIntegration{ - APIKeySecret: "api-key-secretname", - Region: "US", + APIKeySecret: api.LocalObjectReference{ + Name: "api-key-secretname", + }, + Region: "US", }, }, }, @@ -74,8 +83,10 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "PAGER_DUTY", PagerDuty: &PagerDutyIntegration{ - ServiceKeySecret: "service-key-secretname", - Region: "US", + ServiceKeySecret: api.LocalObjectReference{ + Name: "service-key-secretname", + }, + Region: "US", }, }, }, @@ -86,8 +97,10 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "PROMETHEUS", Prometheus: &PrometheusIntegration{ - PrometheusCredentials: "prometheus-credentials", - ServiceDiscovery: "http", + PrometheusCredentials: api.LocalObjectReference{ + Name: "prometheus-credentials", + }, + ServiceDiscovery: "http", }, }, }, @@ -98,9 +111,11 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "SLACK", Slack: &SlackIntegration{ - APITokenSecret: "api-tooken-secretname", - ChannelName: "channel", - TeamName: "team", + APITokenSecret: api.LocalObjectReference{ + Name: "api-tooken-secretname", + }, + ChannelName: "channel", + TeamName: "team", }, }, }, @@ -111,7 +126,9 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "VICTOR_OPS", VictorOps: &VictorOpsIntegration{ - RoutingKey: "routing-key", + RoutingKey: api.LocalObjectReference{ + Name: "routing-key", + }, APIKeySecret: "keys-secetname", }, }, @@ -123,7 +140,9 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "WEBHOOK", Webhook: &WebhookIntegration{ - URLSecret: "url-secretname", + URLSecret: api.LocalObjectReference{ + Name: "url-secretname", + }, }, }, }, @@ -135,8 +154,10 @@ func TestIntegrationCELChecks(t *testing.T) { Type: "PAGER_DUTY", PagerDuty: &PagerDutyIntegration{}, Prometheus: &PrometheusIntegration{ - PrometheusCredentials: "prometheus-credentials", - ServiceDiscovery: "http", + PrometheusCredentials: api.LocalObjectReference{ + Name: "prometheus-credentials", + }, + ServiceDiscovery: "http", }, }, }, @@ -148,11 +169,15 @@ func TestIntegrationCELChecks(t *testing.T) { Spec: AtlasThirdPartyIntegrationSpec{ Type: "WEBHOOK", Datadog: &DatadogIntegration{ - APIKeySecret: "api-key-secretname", - Region: "US", + APIKeySecret: api.LocalObjectReference{ + Name: "api-key-secretname", + }, + Region: "US", }, Webhook: &WebhookIntegration{ - URLSecret: "url-secretname", + URLSecret: api.LocalObjectReference{ + Name: "url-secretname", + }, }, }, }, diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index a422e2b9f8..5f79d00e45 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -2600,6 +2600,7 @@ func (in *Database) DeepCopy() *Database { // 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) @@ -2948,6 +2949,7 @@ func (in *MetricThreshold) DeepCopy() *MetricThreshold { // 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. @@ -2978,6 +2980,7 @@ func (in *NetworkPeer) DeepCopy() *NetworkPeer { // 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. @@ -3034,6 +3037,7 @@ func (in *Notification) DeepCopy() *Notification { // 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. @@ -3049,6 +3053,7 @@ func (in *OpsGenieIntegration) DeepCopy() *OpsGenieIntegration { // 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. @@ -3224,6 +3229,7 @@ func (in *ProjectSettings) DeepCopy() *ProjectSettings { // 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. @@ -3516,6 +3522,7 @@ func (in *ServerlessSpec) DeepCopy() *ServerlessSpec { // 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. @@ -3863,6 +3870,7 @@ func (in *VectorSearch) DeepCopy() *VectorSearch { // 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. @@ -3893,6 +3901,7 @@ func (in *View) DeepCopy() *View { // 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. diff --git a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml index ba87e54461..bf3b877ed5 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasthirdpartyintegrations.yaml @@ -57,9 +57,17 @@ spec: description: Datadog contains the config fields for Datadog's Integration properties: apiKeySecret: - description: APIKeySecret is the name of a secret containing the - datadog api key - type: string + 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 @@ -100,9 +108,17 @@ spec: Teams's Integration properties: urlSecret: - description: URLSecret is the name of a secret containing the + description: URLSecret holds the name of a secret containing the microsoft teams secret URL - type: string + 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 @@ -111,9 +127,17 @@ spec: properties: credentialsSecret: description: |- - CredentialsSecret is the name of a secret containing new relic's credentials: + CredentialsSecret holds the name of a secret containing new relic's credentials: account id, license key, read and write tokens - type: string + 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 @@ -121,9 +145,17 @@ spec: description: OpsGenie contains the config fields for Ops Genie's Integration properties: apiKeySecret: - description: APIKeySecret is the name of a secret containing Ops - Genie's API key - type: string + 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 @@ -139,9 +171,17 @@ spec: description: Region is the Pager Duty region type: string serviceKeySecret: - description: ServiceKeySecret is the name of a secret containing + description: ServiceKeySecret holds the name of a secret containing Pager Duty service key - type: string + 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 @@ -166,9 +206,17 @@ spec: properties: prometheusCredentials: description: |- - PrometheusCredentials is the name of a secret containing the Prometheus + PrometheusCredentials holds the name of a secret containing the Prometheus username & password - type: string + 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: @@ -183,9 +231,17 @@ spec: description: Slack contains the config fields for Slack's Integration properties: apiTokenSecret: - description: APITokenSecret is the name of a secret containing + description: APITokenSecret holds the name of a secret containing the Slack API token - type: string + 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 @@ -220,8 +276,16 @@ spec: Ops API key type: string routingKey: - description: RoutingKey is VictorOps routing key - type: string + 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 @@ -230,9 +294,17 @@ spec: description: Webhook contains the config fields for Webhook's Integration properties: urlSecret: - description: URLSecret is the name of a secret containing Webhook + description: URLSecret holds the name of a secret containing Webhook URL and secret - type: string + 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 diff --git a/config/samples/atlas_v1_atlasthirdpartyintegration.yaml b/config/samples/atlas_v1_atlasthirdpartyintegration.yaml index 81ce2dde92..9342854ec7 100644 --- a/config/samples/atlas_v1_atlasthirdpartyintegration.yaml +++ b/config/samples/atlas_v1_atlasthirdpartyintegration.yaml @@ -10,7 +10,8 @@ spec: name: my-atlas-project type: DATADOG datadog: - apiKeySecret: "secret-ref" + apiKeySecret: + name: "secret-ref" region: "string" --- apiVersion: atlas.mongodb.com/v1 @@ -26,7 +27,8 @@ spec: connectionSecret: "conn-secret-ref" type: MICROSOFT_TEAMS microsoftTeams: - urlSecret: "secret-ref" + urlSecret: + name: "secret-ref" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -40,7 +42,8 @@ spec: name: my-atlas-project type: NEW_RELIC newRelic: - credentialsSecret: "secret-ref" + credentialsSecret: + name: "secret-ref" --- apiVersion: atlas.mongodb.com/v1 kind: AtlasIntegration @@ -54,7 +57,8 @@ spec: name: my-atlas-project type: OPS_GENIE opsGenie: - apiKeySecret: "secret-ref" + apiKeySecret: + name: "secret-ref" region: "string" --- apiVersion: atlas.mongodb.com/v1 @@ -69,7 +73,8 @@ spec: name: my-atlas-project type: PAGER_DUTY pagerDuty: - serviceKeySecret: "secret-ref" + serviceKeySecret: + name: "secret-ref" region: "string" --- apiVersion: atlas.mongodb.com/v1 @@ -84,7 +89,8 @@ spec: name: my-atlas-project type: PROMETHEUS prometheus: - prometheusCredentials: "secret-ref" + prometheusCredentials: + name: "secret-ref" serviceDiscovery: "string" enabled: true --- @@ -100,7 +106,8 @@ spec: name: my-atlas-project type: SLACK slack: - apiTokenSecret: "secret-ref" + apiTokenSecret: + name: "secret-ref" channelName: "channel-name" teamName: "team-name" --- @@ -116,7 +123,8 @@ spec: name: my-atlas-project type: VICTOR_OPS victorOps: - routingKey: "string" + routingKey: + name: "string" apiKeySecret: "secret-ref" --- apiVersion: atlas.mongodb.com/v1 @@ -131,4 +139,5 @@ spec: name: my-atlas-project type: WEBHOOK webhook: - urlSecret: "secret-ref" + urlSecret: + name: "secret-ref"