diff --git a/CHANGELOG/CHANGELOG-1.13.md b/CHANGELOG/CHANGELOG-1.13.md index 8b07c7d4f..9e23d8599 100644 --- a/CHANGELOG/CHANGELOG-1.13.md +++ b/CHANGELOG/CHANGELOG-1.13.md @@ -13,6 +13,10 @@ Changelog for the K8ssandra Operator, new PRs should update the `unreleased` sec When cutting a new release, update the `unreleased` heading to the tag being generated and date, like `## vX.Y.Z - YYYY-MM-DD` and create a new placeholder section for `unreleased` entries. +## unreleased + +* [BUGFIX] [#1235](https://github.com/k8ssandra/k8ssandra-operator/issues/1235) Prevent operator from modifying the spec when superUserRef is not set. Also, remove the injection to mount secrets to cassandra container. + ## v1.13.0 - 2024-02-24 * [ENHANCEMENT] [#1159](https://github.com/k8ssandra/k8ssandra-operator/issues/1159) Replicate bucket key secrets to namespaces hosting clusters diff --git a/controllers/k8ssandra/dcconfigs.go b/controllers/k8ssandra/dcconfigs.go index 2d59eaba4..344398f16 100644 --- a/controllers/k8ssandra/dcconfigs.go +++ b/controllers/k8ssandra/dcconfigs.go @@ -6,7 +6,6 @@ import ( "github.com/go-logr/logr" api "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" - k8ssandraapi "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" "github.com/k8ssandra/k8ssandra-operator/pkg/cassandra" "github.com/k8ssandra/k8ssandra-operator/pkg/reaper" "github.com/k8ssandra/k8ssandra-operator/pkg/telemetry" @@ -32,6 +31,7 @@ func (r *K8ssandraClusterReconciler) createDatacenterConfigs( dcConfig := cassandra.Coalesce(kc.CassClusterName(), kc.Spec.Cassandra.DeepCopy(), dcTemplate.DeepCopy()) dcConfig.ExternalSecrets = kc.Spec.UseExternalSecrets() + dcConfig.SuperuserSecretRef.Name = SuperuserSecretName(kc) dcKey := types.NamespacedName{Namespace: utils.FirstNonEmptyString(dcConfig.Meta.Namespace, kcKey.Namespace), Name: dcConfig.Meta.Name} dcLogger := logger.WithValues("CassandraDatacenter", dcKey, "K8SContext", dcConfig.K8sContext) @@ -84,7 +84,7 @@ func (r *K8ssandraClusterReconciler) createDatacenterConfigs( // The new metrics endpoint is available since 3.11.13 and 4.0.4. // If MCAC is disabled and the new metrics endpoint is not available then we should return an error. mergedTelemetrySpec := MergeTelemetrySpecs(kc, dcTemplate) - if !mergedTelemetrySpec.IsMcacEnabled() && !telemetry.IsNewMetricsEndpointAvailable(dcConfig.ServerVersion.String()) && kc.Spec.Cassandra.ServerType == k8ssandraapi.ServerDistributionCassandra { + if !mergedTelemetrySpec.IsMcacEnabled() && !telemetry.IsNewMetricsEndpointAvailable(dcConfig.ServerVersion.String()) && kc.Spec.Cassandra.ServerType == api.ServerDistributionCassandra { return dcConfigs, errors.New("new metrics endpoint is only available since Cassandra 3.11.13/4.0.4, so MCAC cannot be disabled") } else { logger.Info("new metrics endpoint is available, so MCAC can be disabled", "serverVersion", kc.Spec.Cassandra.ServerVersion) diff --git a/controllers/k8ssandra/k8ssandracluster_controller_test.go b/controllers/k8ssandra/k8ssandracluster_controller_test.go index 1484240ac..2e622a4dd 100644 --- a/controllers/k8ssandra/k8ssandracluster_controller_test.go +++ b/controllers/k8ssandra/k8ssandracluster_controller_test.go @@ -186,7 +186,6 @@ func createSingleDcCluster(t *testing.T, ctx context.Context, f *framework.Frame require.True(dc.Spec.PodTemplateSpec.Spec.SecurityContext.RunAsUser != nil && *dc.Spec.PodTemplateSpec.Spec.SecurityContext.RunAsUser == 999, "pod security context was not properly set") require.True(dc.Spec.ManagementApiAuth.Insecure != nil, "management api auth was not properly set") - verifySecretAnnotationAdded(t, f, ctx, dcKey, secret.DefaultSuperuserSecretName(kc.SanitizedName())) lastTransitionTime := metav1.Now() t.Log("update datacenter status to scaling up") @@ -421,7 +420,6 @@ func applyClusterTemplateConfigs(t *testing.T, ctx context.Context, f *framework // assert.Equal(*kc.Spec.Cassandra.DatacenterOptions.StorageConfig, dc1.Spec.StorageConfig) assert.Equal(dc1Size, dc1.Spec.Size) assert.Equal(dc1.Spec.SuperuserSecretName, superUserSecretName) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, superUserSecretName) t.Log("update dc1 status to ready") err = f.SetDatacenterStatusReady(ctx, dc1Key) @@ -441,7 +439,6 @@ func applyClusterTemplateConfigs(t *testing.T, ctx context.Context, f *framework // assert.Equal(*kc.Spec.Cassandra.DatacenterOptions.StorageConfig, dc2.Spec.StorageConfig) assert.Equal(dc2Size, dc2.Spec.Size) assert.Equal(dc1.Spec.SuperuserSecretName, superUserSecretName) - verifySecretAnnotationAdded(t, f, ctx, dc2Key, superUserSecretName) t.Log("deleting K8ssandraCluster") err = f.DeleteK8ssandraCluster(ctx, client.ObjectKey{Namespace: kc.Namespace, Name: kc.Name}, timeout, interval) @@ -573,7 +570,6 @@ func applyDatacenterTemplateConfigs(t *testing.T, ctx context.Context, f *framew t.Log("check that dc1 was created") dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) t.Log("verify configuration of dc1") dc1 := &cassdcapi.CassandraDatacenter{} @@ -602,7 +598,6 @@ func applyDatacenterTemplateConfigs(t *testing.T, ctx context.Context, f *framew dc2 := &cassdcapi.CassandraDatacenter{} err = f.Get(ctx, dc2Key, dc2) require.NoError(err, "failed to get dc2") - verifySecretAnnotationAdded(t, f, ctx, dc2Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) assert.Equal(kc.Name, dc2.Spec.ClusterName) assert.Equal(serverVersion, dc2.Spec.ServerVersion) @@ -736,7 +731,6 @@ func applyClusterTemplateAndDatacenterTemplateConfigs(t *testing.T, ctx context. // assert.Equal(*kc.Spec.Cassandra.DatacenterOptions.StorageConfig, dc1.Spec.StorageConfig) assert.Equal(kc.Spec.Cassandra.DatacenterOptions.Networking.ToCassNetworkingConfig(), dc1.Spec.Networking) assert.Equal(dc1Size, dc1.Spec.Size) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) t.Log("update dc1 status to ready") err = f.SetDatacenterStatusReady(ctx, dc1Key) @@ -758,8 +752,6 @@ func applyClusterTemplateAndDatacenterTemplateConfigs(t *testing.T, ctx context. assert.Equal(dc2Size, dc2.Spec.Size) assert.Equal(*dc2.Spec.CDC.PulsarServiceUrl, "pulsar://test-url") - verifySecretAnnotationAdded(t, f, ctx, dc2Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) - t.Log("deleting K8ssandraCluster") err = f.DeleteK8ssandraCluster(ctx, client.ObjectKey{Namespace: kc.Namespace, Name: kc.Name}, timeout, interval) require.NoError(err, "failed to delete K8ssandraCluster") @@ -831,8 +823,6 @@ func createMultiDcCluster(t *testing.T, ctx context.Context, f *framework.Framew dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) - t.Log("update datacenter status to scaling up") err = f.PatchDatacenterStatus(ctx, dc1Key, func(dc *cassdcapi.CassandraDatacenter) { dc.SetCondition(cassdcapi.DatacenterCondition{ @@ -890,8 +880,6 @@ func createMultiDcCluster(t *testing.T, ctx context.Context, f *framework.Framew err = f.SetDatacenterStatusReady(ctx, dc2Key) require.NoError(err, "failed to set dc2 status ready") - verifySecretAnnotationAdded(t, f, ctx, dc2Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) - t.Log("check that dc2 was rebuilt") verifyRebuildTaskCreated(ctx, t, f, dc2Key, dc1Key) rebuildTaskKey := framework.NewClusterKey(f.DataPlaneContexts[1], kc.Namespace, "dc2-rebuild") @@ -1123,7 +1111,6 @@ func createSingleDcCassandra4ClusterWithStargate(t *testing.T, ctx context.Conte require.NoError(err, "failed to unmarshall CassandraDatacenter config") jvmOpts := dcConfig["cassandra-env-sh"].(map[string]interface{})["additional-jvm-opts"].([]interface{}) require.Contains(jvmOpts, "-Dcassandra.allow_alter_rf_during_range_movement=true") - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) err = f.Get(ctx, kcKey, kc) require.NoError(err, "failed to get K8ssandraCluster") @@ -1233,7 +1220,6 @@ func createMultiDcClusterWithStargate(t *testing.T, ctx context.Context, f *fram t.Log("check that dc1 was created") dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) t.Log("update datacenter status to scaling up") err = f.PatchDatacenterStatus(ctx, dc1Key, func(dc *cassdcapi.CassandraDatacenter) { @@ -1310,7 +1296,6 @@ func createMultiDcClusterWithStargate(t *testing.T, ctx context.Context, f *fram t.Log("update dc2 status to ready") err = f.SetDatacenterStatusReady(ctx, dc2Key) require.NoError(err, "failed to update dc2 status to ready") - verifySecretAnnotationAdded(t, f, ctx, dc2Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) t.Log("check that dc2 was rebuilt") verifyRebuildTaskCreated(ctx, t, f, dc2Key, dc1Key) @@ -1602,7 +1587,6 @@ func applyClusterWithEncryptionOptions(t *testing.T, ctx context.Context, f *fra t.Log("check that dc1 was created") dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) t.Log("verify configuration of dc1") dc1 := &cassdcapi.CassandraDatacenter{} @@ -2111,21 +2095,6 @@ func verifySystemReplicationAnnotationSet(ctx context.Context, t *testing.T, f * assert.Eventually(t, systemReplicationAnnotationIsSet(t, f, ctx, kc), timeout, interval, "Failed to verify that the system replication annotation was set correctly") } -func verifySecretAnnotationAdded(t *testing.T, f *framework.Framework, ctx context.Context, dcKey framework.ClusterKey, secretName string) { - t.Logf("check that the superuser secret annotation is added") - assert.Eventually(t, secretAnnotationAdded(t, f, ctx, dcKey, getCassDcAnnotations, secretName), timeout, interval, " failed to verify cassdc secret annotation added") -} - -func getCassDcAnnotations(t *testing.T, f *framework.Framework, ctx context.Context, key framework.ClusterKey) map[string]string { - dc := &cassdcapi.CassandraDatacenter{} - err := f.Get(ctx, key, dc) - if err != nil { - t.Logf("failed to get CassandraDatacenter: %v", err) - } - - return dc.Spec.PodTemplateSpec.Annotations -} - func secretAnnotationAdded(t *testing.T, f *framework.Framework, ctx context.Context, key framework.ClusterKey, annFn func(t *testing.T, f *framework.Framework, ctx context.Context, key framework.ClusterKey) map[string]string, secretName string) func() bool { return func() bool { @@ -2302,7 +2271,6 @@ func convertSystemReplicationAnnotation(t *testing.T, ctx context.Context, f *fr t.Log("check that the datacenter was created") dcKey := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[1]} require.Eventually(f.DatacenterExists(ctx, dcKey), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dcKey, secret.DefaultSuperuserSecretName(kc.SanitizedName())) lastTransitionTime := metav1.Now() @@ -2418,7 +2386,6 @@ func changeClusterNameFails(t *testing.T, ctx context.Context, f *framework.Fram t.Log("check that dc1 was never created") dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) k8c := &api.K8ssandraCluster{} err = f.Client.Get(ctx, client.ObjectKey{Namespace: namespace, Name: clusterName}, k8c) @@ -2525,7 +2492,6 @@ func injectContainersAndVolumes(t *testing.T, ctx context.Context, f *framework. t.Log("check that dc1 was never created") dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) dc := &cassdcapi.CassandraDatacenter{} err = f.Get(ctx, dc1Key, dc) @@ -2625,7 +2591,6 @@ func createMultiDcDseCluster(t *testing.T, ctx context.Context, f *framework.Fra t.Log("check that dc2 was created") dc2Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc2"}, K8sContext: f.DataPlaneContexts[1]} require.Eventually(f.DatacenterExists(ctx, dc2Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc2Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) t.Log("check that dc1 has not been created yet") dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} @@ -2639,7 +2604,6 @@ func createMultiDcDseCluster(t *testing.T, ctx context.Context, f *framework.Fra t.Log("check that dc1 was created") require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, secret.DefaultSuperuserSecretName(kc.SanitizedName())) t.Log("update dc1 status to ready") err = f.SetDatacenterStatusReady(ctx, dc1Key) diff --git a/controllers/k8ssandra/medusa_reconciler_test.go b/controllers/k8ssandra/medusa_reconciler_test.go index 91580a3e5..0ae56c662 100644 --- a/controllers/k8ssandra/medusa_reconciler_test.go +++ b/controllers/k8ssandra/medusa_reconciler_test.go @@ -170,8 +170,6 @@ func createMultiDcClusterWithMedusa(t *testing.T, ctx context.Context, f *framew dc1Key := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} require.Eventually(f.DatacenterExists(ctx, dc1Key), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dc1Key, cassandraUserSecret) - t.Log("verify the config map exists and has the contents from the MedusaConfiguration object") defaultPrefix := kc.Spec.Medusa.StorageProperties.Prefix verifyConfigMap(require, ctx, f, namespace, defaultPrefix) @@ -309,7 +307,6 @@ func createMultiDcClusterWithMedusa(t *testing.T, ctx context.Context, f *framew setRebuildTaskFinished(ctx, t, f, rebuildTaskKey, dc2Key) checkMedusaObjectsCompliance(t, f, dc2, kc) - verifySecretAnnotationAdded(t, f, ctx, dc2Key, cassandraUserSecret) t.Log("check that the K8ssandraCluster status is updated") require.Eventually(func() bool { diff --git a/controllers/k8ssandra/secrets.go b/controllers/k8ssandra/secrets.go index a3e95214c..9722314da 100644 --- a/controllers/k8ssandra/secrets.go +++ b/controllers/k8ssandra/secrets.go @@ -2,8 +2,6 @@ package k8ssandra import ( "context" - "fmt" - "time" "github.com/go-logr/logr" api "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" @@ -12,8 +10,6 @@ import ( "github.com/k8ssandra/k8ssandra-operator/pkg/secret" "github.com/k8ssandra/k8ssandra-operator/pkg/utils" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "sigs.k8s.io/controller-runtime/pkg/client" ) func (r *K8ssandraClusterReconciler) reconcileSuperuserSecret(ctx context.Context, kc *api.K8ssandraCluster, logger logr.Logger) result.ReconcileResult { @@ -29,34 +25,21 @@ func (r *K8ssandraClusterReconciler) reconcileSuperuserSecret(ctx context.Contex // to turn on authentication later on, since kc.Spec.Cassandra.SuperuserSecretRef is immutable. // Finally, creating the superuser secret when auth is disabled does not do any harm: no credentials will be // required to connect to Cassandra nodes by CQL nor JMX. - if kc.Spec.Cassandra.SuperuserSecretRef.Name == "" { - patch := client.MergeFromWithOptions(kc.DeepCopy(), client.MergeFromWithOptimisticLock{}) - kc.Spec.Cassandra.SuperuserSecretRef.Name = secret.DefaultSuperuserSecretName(kc.SanitizedName()) - if err := r.Patch(ctx, kc, patch); err != nil { - if errors.IsConflict(err) { - return result.RequeueSoon(1 * time.Second) - } - return result.Error(fmt.Errorf("failed to set default superuser secret name: %v", err)) - } - - kc.Spec.Cassandra.SuperuserSecretRef.Name = secret.DefaultSuperuserSecretName(kc.SanitizedName()) - logger.Info("Setting default superuser secret", "SuperuserSecretName", kc.Spec.Cassandra.SuperuserSecretRef.Name) - } - - if err := secret.ReconcileSecret(ctx, r.Client, kc.Spec.Cassandra.SuperuserSecretRef.Name, utils.GetKey(kc)); err != nil { + if err := secret.ReconcileSecret(ctx, r.Client, SuperuserSecretName(kc), utils.GetKey(kc)); err != nil { logger.Error(err, "Failed to verify existence of superuserSecret") return result.Error(err) } - err := secret.AddInjectionAnnotationCassandraContainers(&kc.Spec.Cassandra.Meta.Pods, kc.Spec.Cassandra.SuperuserSecretRef.Name) - if err != nil { - logger.Error(err, "Failed to add superuser injection annotation") - return result.Error(err) - } - return result.Continue() } +func SuperuserSecretName(kc *api.K8ssandraCluster) string { + if kc.Spec.Cassandra.SuperuserSecretRef.Name == "" { + return secret.DefaultSuperuserSecretName(kc.SanitizedName()) + } + return kc.Spec.Cassandra.SuperuserSecretRef.Name +} + func (r *K8ssandraClusterReconciler) reconcileReaperSecrets(ctx context.Context, kc *api.K8ssandraCluster, logger logr.Logger) result.ReconcileResult { if kc.Spec.Reaper != nil { // Reaper secrets are only required when authentication is enabled on the cluster diff --git a/pkg/secret/inject.go b/pkg/secret/inject.go index 2750baf98..a0d99413a 100644 --- a/pkg/secret/inject.go +++ b/pkg/secret/inject.go @@ -19,10 +19,6 @@ type SecretInjection struct { Containers []string `json:"containers,omitempty"` } -func AddInjectionAnnotationCassandraContainers(t *meta.Tags, secretName string) error { - return AddInjectionAnnotation(t, secretName, []string{"cassandra"}) -} - func AddInjectionAnnotationMedusaContainers(t *meta.Tags, secretName string) error { return AddInjectionAnnotation(t, secretName, []string{"medusa", "medusa-restore"}) }