diff --git a/internal/kubernetes/operator/project/project.go b/internal/kubernetes/operator/project/project.go index 2a4a5fa51b..1832dfc6fd 100644 --- a/internal/kubernetes/operator/project/project.go +++ b/internal/kubernetes/operator/project/project.go @@ -589,10 +589,6 @@ func buildEncryptionAtRest(encProvider store.EncryptionAtRestDescriber, projectI Enabled: data.AwsKms.Enabled, Region: data.AwsKms.GetRegion(), Valid: data.AwsKms.Valid, - SecretRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("aws-credentials-"), dictionary), - Namespace: targetNamespace, - }, }, AzureKeyVault: akov2.AzureKeyVault{ Enabled: data.AzureKeyVault.Enabled, @@ -600,36 +596,49 @@ func buildEncryptionAtRest(encProvider store.EncryptionAtRestDescriber, projectI AzureEnvironment: data.AzureKeyVault.GetAzureEnvironment(), ResourceGroupName: data.AzureKeyVault.GetResourceGroupName(), TenantID: data.AzureKeyVault.GetTenantID(), - SecretRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("azure-credentials-"), dictionary), - Namespace: targetNamespace, - }, }, GoogleCloudKms: akov2.GoogleCloudKms{ Enabled: data.GoogleCloudKms.Enabled, - SecretRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("gcp-credentials-"), dictionary), - Namespace: targetNamespace, - }, }, } - secret := []*corev1.Secret{ - secrets.NewAtlasSecretBuilder(ref.AwsKms.SecretRef.Name, ref.AwsKms.SecretRef.Namespace, dictionary). + var ss []*corev1.Secret + switch { + case data.AwsKms.Enabled != nil && *data.AwsKms.Enabled: + ref.AwsKms.SecretRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("aws-credentials-"), dictionary), + Namespace: targetNamespace, + } + + ss = append(ss, secrets.NewAtlasSecretBuilder(ref.AwsKms.SecretRef.Name, ref.AwsKms.SecretRef.Namespace, dictionary). WithData(map[string][]byte{"CustomerMasterKeyID": []byte(""), "RoleID": []byte("")}). WithProjectLabels(projectID, projectName). - Build(), - secrets.NewAtlasSecretBuilder(ref.AzureKeyVault.SecretRef.Name, ref.AzureKeyVault.SecretRef.Namespace, dictionary). + Build()) + + case data.AzureKeyVault.Enabled != nil && *data.AzureKeyVault.Enabled: + ref.AzureKeyVault.SecretRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("azure-credentials-"), dictionary), + Namespace: targetNamespace, + } + + ss = append(ss, secrets.NewAtlasSecretBuilder(ref.AzureKeyVault.SecretRef.Name, ref.AzureKeyVault.SecretRef.Namespace, dictionary). WithData(map[string][]byte{"SubscriptionID": []byte(""), "KeyVaultName": []byte(""), "KeyIdentifier": []byte(""), "Secret": []byte("")}). WithProjectLabels(projectID, projectName). - Build(), - secrets.NewAtlasSecretBuilder(ref.GoogleCloudKms.SecretRef.Name, ref.GoogleCloudKms.SecretRef.Namespace, dictionary). + Build()) + + case data.GoogleCloudKms.Enabled != nil && *data.GoogleCloudKms.Enabled: + ref.AzureKeyVault.SecretRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("gcp-credentials-"), dictionary), + Namespace: targetNamespace, + } + + ss = append(ss, secrets.NewAtlasSecretBuilder(ref.GoogleCloudKms.SecretRef.Name, ref.GoogleCloudKms.SecretRef.Namespace, dictionary). WithData(map[string][]byte{"ServiceAccountKey": []byte(""), "KeyVersionResourceID": []byte("")}). WithProjectLabels(projectID, projectName). - Build(), + Build()) } - return ref, secret, nil + return ref, ss, nil } func buildCloudProviderAccessRoles(cpaProvider store.CloudProviderAccessRoleLister, projectID string) ([]akov2.CloudProviderAccessRole, error) { @@ -730,70 +739,92 @@ func buildAlertConfigurations(acProvider atlas.AlertConfigurationLister, project for _, atlasNotification := range atlasNotifications { akoNotification := akov2.Notification{ - APITokenRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("api-token-"), dictionary), - Namespace: targetNamespace, - }, - ChannelName: atlas.StringOrEmpty(atlasNotification.ChannelName), - DatadogAPIKeyRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("datadog-api-key-"), dictionary), - Namespace: targetNamespace, - }, - DatadogRegion: atlas.StringOrEmpty(atlasNotification.DatadogRegion), - DelayMin: atlasNotification.DelayMin, - EmailAddress: atlas.StringOrEmpty(atlasNotification.EmailAddress), - EmailEnabled: atlasNotification.EmailEnabled, - IntervalMin: pointer.GetOrDefault(atlasNotification.IntervalMin, 0), - MobileNumber: atlas.StringOrEmpty(atlasNotification.MobileNumber), - OpsGenieAPIKeyRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("ops-genie-api-key-"), dictionary), - Namespace: targetNamespace, - }, + ChannelName: atlas.StringOrEmpty(atlasNotification.ChannelName), + DatadogRegion: atlas.StringOrEmpty(atlasNotification.DatadogRegion), + DelayMin: atlasNotification.DelayMin, + EmailAddress: atlas.StringOrEmpty(atlasNotification.EmailAddress), + EmailEnabled: atlasNotification.EmailEnabled, + IntervalMin: pointer.GetOrDefault(atlasNotification.IntervalMin, 0), + MobileNumber: atlas.StringOrEmpty(atlasNotification.MobileNumber), OpsGenieRegion: atlas.StringOrEmpty(atlasNotification.OpsGenieRegion), - ServiceKeyRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("service-key-"), dictionary), - Namespace: targetNamespace, - }, - SMSEnabled: atlasNotification.SmsEnabled, - TeamID: atlas.StringOrEmpty(atlasNotification.TeamId), - TeamName: atlas.StringOrEmpty(atlasNotification.TeamName), - TypeName: atlas.StringOrEmpty(atlasNotification.TypeName), - Username: atlas.StringOrEmpty(atlasNotification.Username), - VictorOpsSecretRef: akov2common.ResourceRefNamespaced{ - Name: resources.NormalizeAtlasName(generateName("victor-ops-credentials-"), dictionary), - Namespace: targetNamespace, - }, - Roles: atlasNotification.Roles, + SMSEnabled: atlasNotification.SmsEnabled, + TeamID: atlas.StringOrEmpty(atlasNotification.TeamId), + TeamName: atlas.StringOrEmpty(atlasNotification.TeamName), + TypeName: atlas.StringOrEmpty(atlasNotification.TypeName), + Username: atlas.StringOrEmpty(atlasNotification.Username), + Roles: atlasNotification.Roles, } - akoNotifications = append(akoNotifications, akoNotification) - akoSecrets = append(akoSecrets, []*corev1.Secret{ - secrets.NewAtlasSecretBuilder(akoNotification.APITokenRef.Name, akoNotification.APITokenRef.Namespace, dictionary). - WithData(map[string][]byte{"APIToken": []byte("")}). - WithProjectLabels(projectID, projectName). - WithNotifierID(atlasNotification.NotifierId). - Build(), - secrets.NewAtlasSecretBuilder(akoNotification.DatadogAPIKeyRef.Name, akoNotification.DatadogAPIKeyRef.Namespace, dictionary). - WithData(map[string][]byte{"DatadogAPIKey": []byte("")}). - WithProjectLabels(projectID, projectName). - WithNotifierID(atlasNotification.NotifierId). - Build(), - secrets.NewAtlasSecretBuilder(akoNotification.OpsGenieAPIKeyRef.Name, akoNotification.OpsGenieAPIKeyRef.Namespace, dictionary). - WithData(map[string][]byte{"OpsGenieAPIKey": []byte("")}). - WithProjectLabels(projectID, projectName). - WithNotifierID(atlasNotification.NotifierId). - Build(), - secrets.NewAtlasSecretBuilder(akoNotification.ServiceKeyRef.Name, akoNotification.ServiceKeyRef.Namespace, dictionary). - WithData(map[string][]byte{"ServiceKey": []byte("")}). - WithProjectLabels(projectID, projectName). - WithNotifierID(atlasNotification.NotifierId). - Build(), - secrets.NewAtlasSecretBuilder(akoNotification.VictorOpsSecretRef.Name, akoNotification.VictorOpsSecretRef.Namespace, dictionary). - WithData(map[string][]byte{"VictorOpsAPIKey": []byte(""), "VictorOpsRoutingKey": []byte("")}). - WithProjectLabels(projectID, projectName). - WithNotifierID(atlasNotification.NotifierId). - Build(), - }...) + if atlasNotification.TypeName != nil { + switch *atlasNotification.TypeName { + case pagerDutyIntegrationType: + akoNotification.ServiceKeyRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("service-key-"), dictionary), + Namespace: targetNamespace, + } + + akoSecrets = append(akoSecrets, + secrets.NewAtlasSecretBuilder(akoNotification.ServiceKeyRef.Name, akoNotification.ServiceKeyRef.Namespace, dictionary). + WithData(map[string][]byte{"ServiceKey": []byte("")}). + WithProjectLabels(projectID, projectName). + WithNotifierLabels(atlasNotification.NotifierId, pagerDutyIntegrationType). + Build()) + + case slackIntegrationType: + akoNotification.APITokenRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("api-token-"), dictionary), + Namespace: targetNamespace, + } + + akoSecrets = append(akoSecrets, + secrets.NewAtlasSecretBuilder(akoNotification.APITokenRef.Name, akoNotification.APITokenRef.Namespace, dictionary). + WithData(map[string][]byte{"APIToken": []byte("")}). + WithProjectLabels(projectID, projectName). + WithNotifierLabels(atlasNotification.NotifierId, slackIntegrationType). + Build()) + + case datadogIntegrationType: + akoNotification.DatadogAPIKeyRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("datadog-api-key-"), dictionary), + Namespace: targetNamespace, + } + + akoSecrets = append(akoSecrets, + secrets.NewAtlasSecretBuilder(akoNotification.DatadogAPIKeyRef.Name, akoNotification.DatadogAPIKeyRef.Namespace, dictionary). + WithData(map[string][]byte{"DatadogAPIKey": []byte("")}). + WithProjectLabels(projectID, projectName). + WithNotifierLabels(atlasNotification.NotifierId, datadogIntegrationType). + Build()) + + case opsGenieIntegrationType: + akoNotification.OpsGenieAPIKeyRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("ops-genie-api-key-"), dictionary), + Namespace: targetNamespace, + } + + akoSecrets = append(akoSecrets, + secrets.NewAtlasSecretBuilder(akoNotification.OpsGenieAPIKeyRef.Name, akoNotification.OpsGenieAPIKeyRef.Namespace, dictionary). + WithData(map[string][]byte{"OpsGenieAPIKey": []byte("")}). + WithProjectLabels(projectID, projectName). + WithNotifierLabels(atlasNotification.NotifierId, opsGenieIntegrationType). + Build()) + + case victorOpsIntegrationType: + akoNotification.VictorOpsSecretRef = akov2common.ResourceRefNamespaced{ + Name: resources.NormalizeAtlasName(generateName("victor-ops-credentials-"), dictionary), + Namespace: targetNamespace, + } + + akoSecrets = append(akoSecrets, + secrets.NewAtlasSecretBuilder(akoNotification.VictorOpsSecretRef.Name, akoNotification.VictorOpsSecretRef.Namespace, dictionary). + WithData(map[string][]byte{"VictorOpsAPIKey": []byte(""), "VictorOpsRoutingKey": []byte("")}). + WithProjectLabels(projectID, projectName). + WithNotifierLabels(atlasNotification.NotifierId, victorOpsIntegrationType). + Build()) + } + } + + akoNotifications = append(akoNotifications, akoNotification) } return akoNotifications, akoSecrets diff --git a/internal/kubernetes/operator/project/project_test.go b/internal/kubernetes/operator/project/project_test.go index 788c221de0..96292493f1 100644 --- a/internal/kubernetes/operator/project/project_test.go +++ b/internal/kubernetes/operator/project/project_test.go @@ -38,6 +38,7 @@ import ( akov2provider "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/provider" akov2status "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/status" akov2toptr "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/util/toptr" + "github.com/stretchr/testify/assert" atlasv2 "go.mongodb.org/atlas-sdk/v20231115002/admin" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -337,13 +338,13 @@ func TestBuildAtlasProject(t *testing.T) { { APITokenRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.AlertConfigurations[0].Notifications[0].APITokenRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.AlertConfigurations[0].Notifications[0].APITokenRef.Namespace, }, ChannelName: atlas.StringOrEmpty(alertConfigs[0].Notifications[0].ChannelName), DatadogRegion: atlas.StringOrEmpty(alertConfigs[0].Notifications[0].DatadogRegion), DatadogAPIKeyRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.AlertConfigurations[0].Notifications[0].DatadogAPIKeyRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.AlertConfigurations[0].Notifications[0].DatadogAPIKeyRef.Namespace, }, DelayMin: alertConfigs[0].Notifications[0].DelayMin, EmailAddress: atlas.StringOrEmpty(alertConfigs[0].Notifications[0].EmailAddress), @@ -353,11 +354,11 @@ func TestBuildAtlasProject(t *testing.T) { OpsGenieRegion: atlas.StringOrEmpty(alertConfigs[0].Notifications[0].OpsGenieRegion), OpsGenieAPIKeyRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.AlertConfigurations[0].Notifications[0].OpsGenieAPIKeyRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.AlertConfigurations[0].Notifications[0].OpsGenieAPIKeyRef.Namespace, }, ServiceKeyRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.AlertConfigurations[0].Notifications[0].ServiceKeyRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.AlertConfigurations[0].Notifications[0].ServiceKeyRef.Namespace, }, SMSEnabled: alertConfigs[0].Notifications[0].SmsEnabled, TeamID: atlas.StringOrEmpty(alertConfigs[0].Notifications[0].TeamId), @@ -367,7 +368,7 @@ func TestBuildAtlasProject(t *testing.T) { Roles: alertConfigs[0].Notifications[0].Roles, VictorOpsSecretRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.AlertConfigurations[0].Notifications[0].VictorOpsSecretRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.AlertConfigurations[0].Notifications[0].VictorOpsSecretRef.Namespace, }, }, } @@ -494,20 +495,20 @@ func TestBuildAtlasProject(t *testing.T) { AwsKms: akov2.AwsKms{ SecretRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.EncryptionAtRest.AwsKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.EncryptionAtRest.AwsKms.SecretRef.Namespace, }, }, AzureKeyVault: akov2.AzureKeyVault{ SecretRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.EncryptionAtRest.AzureKeyVault.SecretRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.EncryptionAtRest.AzureKeyVault.SecretRef.Namespace, }, }, GoogleCloudKms: akov2.GoogleCloudKms{ Enabled: encryptionAtRest.GoogleCloudKms.Enabled, SecretRef: akov2common.ResourceRefNamespaced{ Name: gotProject.Spec.EncryptionAtRest.GoogleCloudKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: gotProject.Spec.EncryptionAtRest.GoogleCloudKms.SecretRef.Namespace, }, }, }, @@ -563,13 +564,8 @@ func TestBuildAtlasProject(t *testing.T) { }, } - if diff := deep.Equal(expectedProject, gotProject); diff != nil { - t.Fatalf("Project mismatch: %v", diff) - } - - if diff := deep.Equal(expectedTeams, gotTeams); diff != nil { - t.Fatalf("Teams mismatch: %v", diff) - } + assert.Equal(t, expectedProject, gotProject) + assert.Equal(t, expectedTeams, gotTeams) }) } @@ -796,19 +792,19 @@ func Test_buildEncryptionAtREST(t *testing.T) { Valid: data.AwsKms.Valid, SecretRef: akov2common.ResourceRefNamespaced{ Name: got.AwsKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.AwsKms.SecretRef.Namespace, }, }, AzureKeyVault: akov2.AzureKeyVault{ SecretRef: akov2common.ResourceRefNamespaced{ Name: got.AzureKeyVault.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.AzureKeyVault.SecretRef.Namespace, }, }, GoogleCloudKms: akov2.GoogleCloudKms{ SecretRef: akov2common.ResourceRefNamespaced{ Name: got.GoogleCloudKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.GoogleCloudKms.SecretRef.Namespace, }, }, } @@ -837,20 +833,20 @@ func Test_buildEncryptionAtREST(t *testing.T) { AwsKms: akov2.AwsKms{ SecretRef: akov2common.ResourceRefNamespaced{ Name: got.AwsKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.AwsKms.SecretRef.Namespace, }, }, AzureKeyVault: akov2.AzureKeyVault{ SecretRef: akov2common.ResourceRefNamespaced{ Name: got.AzureKeyVault.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.AzureKeyVault.SecretRef.Namespace, }, }, GoogleCloudKms: akov2.GoogleCloudKms{ Enabled: data.GoogleCloudKms.Enabled, SecretRef: akov2common.ResourceRefNamespaced{ Name: got.GoogleCloudKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.GoogleCloudKms.SecretRef.Namespace, }, }, } @@ -886,7 +882,7 @@ func Test_buildEncryptionAtREST(t *testing.T) { AwsKms: akov2.AwsKms{ SecretRef: akov2common.ResourceRefNamespaced{ Name: got.AwsKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.AwsKms.SecretRef.Namespace, }, }, AzureKeyVault: akov2.AzureKeyVault{ @@ -897,13 +893,13 @@ func Test_buildEncryptionAtREST(t *testing.T) { TenantID: data.AzureKeyVault.GetTenantID(), SecretRef: akov2common.ResourceRefNamespaced{ Name: got.AzureKeyVault.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.AzureKeyVault.SecretRef.Namespace, }, }, GoogleCloudKms: akov2.GoogleCloudKms{ SecretRef: akov2common.ResourceRefNamespaced{ Name: got.GoogleCloudKms.SecretRef.Name, - Namespace: targetNamespace, + Namespace: got.GoogleCloudKms.SecretRef.Namespace, }, }, } diff --git a/internal/kubernetes/operator/secrets/secrets.go b/internal/kubernetes/operator/secrets/secrets.go index d9238e76a6..380b3250ef 100644 --- a/internal/kubernetes/operator/secrets/secrets.go +++ b/internal/kubernetes/operator/secrets/secrets.go @@ -21,15 +21,16 @@ import ( ) const ( - TypeLabelKey = "atlas.mongodb.com/type" - ProjectIDLabelKey = "atlas.mongodb.com/project-id" - ProjectNameLabelKey = "atlas.mongodb.com/project-name" - NotifierIDLabelKey = "atlas.mongodb.com/notifier-id" - CredLabelVal = "credentials" - PasswordField = "password" - CredPrivateAPIKey = "privateApiKey" - CredPublicAPIKey = "publicApiKey" - CredOrgID = "orgId" + TypeLabelKey = "atlas.mongodb.com/type" + ProjectIDLabelKey = "atlas.mongodb.com/project-id" + ProjectNameLabelKey = "atlas.mongodb.com/project-name" + NotifierIDLabelKey = "atlas.mongodb.com/notifier-id" + NotifierNameLabelKey = "atlas.mongodb.com/notifier-type-name" + CredLabelVal = "credentials" + PasswordField = "password" + CredPrivateAPIKey = "privateApiKey" + CredPublicAPIKey = "publicApiKey" + CredOrgID = "orgId" ) type AtlasSecretBuilder func() (*corev1.Secret, map[string]string) @@ -70,13 +71,14 @@ func (a AtlasSecretBuilder) WithProjectLabels(id, name string) AtlasSecretBuilde }) } -func (a AtlasSecretBuilder) WithNotifierID(id *string) AtlasSecretBuilder { +func (a AtlasSecretBuilder) WithNotifierLabels(id *string, typeName string) AtlasSecretBuilder { return AtlasSecretBuilder(func() (*corev1.Secret, map[string]string) { s, d := a() if id == nil { return s, d } s.Labels[NotifierIDLabelKey] = resources.NormalizeAtlasName(*id, d) + s.Labels[NotifierNameLabelKey] = typeName // don't normalize type name, as it is already a short form return s, d }) }