From bb3b303e77c8b48cf2232597f9905407f10d372c Mon Sep 17 00:00:00 2001 From: Michael Burman Date: Mon, 16 Mar 2026 16:33:37 +0200 Subject: [PATCH 1/5] Change regexp to allow wider version ranges, including HCD 2.0.x and only verify the ServerVersion structure, not specific versions --- CHANGELOG.md | 1 + Makefile | 2 +- .../v1beta1/cassandradatacenter_types.go | 2 +- ...dra.datastax.com_cassandradatacenters.yaml | 2 +- .../v1beta1/cassandradatacenter_webhook.go | 21 -------------- pkg/images/images.go | 29 +------------------ pkg/images/images_test.go | 9 ------ 7 files changed, 5 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 537784bfb..bcca87cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Changelog for Cass Operator, new PRs should update the `main / unreleased` secti ## unreleased +* [CHANGE] [#905](https://github.com/k8ssandra/cass-operator/issues/905) Relax the ServerVersion checks to structure only without separating OSS/DSE/HCD. * [FEATURE] [#893](https://github.com/k8ssandra/cass-operator/issues/893) Add support for maxUnavailable (Kubernetes 1.35 and up). This allows to make changes to the Cassandra pods in parallel, thus speeding up changes in larger clusters. Allows integer or percentage setting, but will never target more than one rack at a time. * [ENHANCEMENT] [#888](https://github.com/k8ssandra/cass-operator/issues/888) Add new metrics around all calls to the mgmt-api. This allows to track if some calls are taking longer to execute than expected. diff --git a/Makefile b/Makefile index bf16358c0..c29c60ee7 100644 --- a/Makefile +++ b/Makefile @@ -275,7 +275,7 @@ CONTROLLER_TOOLS_VERSION ?= v0.19.0 OPERATOR_SDK_VERSION ?= 1.42.0 HELM_VERSION ?= 3.19.4 OPM_VERSION ?= 1.61.0 -GOLANGCI_LINT_VERSION ?= v2.10.1 +GOLANGCI_LINT_VERSION ?= v2.11.3 ENVTEST_VERSION ?= $(shell go list -m -f "{{ .Version }}" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf "release-%d.%d", $$2, $$3}') ENVTEST_K8S_VERSION ?= $(shell go list -m -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d", $$3}') diff --git a/apis/cassandra/v1beta1/cassandradatacenter_types.go b/apis/cassandra/v1beta1/cassandradatacenter_types.go index 83aeaa1d0..df0e23f4e 100644 --- a/apis/cassandra/v1beta1/cassandradatacenter_types.go +++ b/apis/cassandra/v1beta1/cassandradatacenter_types.go @@ -121,7 +121,7 @@ type CassandraDatacenterSpec struct { // Version string for config builder, // used to generate Cassandra server configuration - // +kubebuilder:validation:Pattern=(6\.[89]\.\d+)|(3\.11\.\d+)|(4\.\d+\.\d+)|(5\.\d+\.\d+)|(1\.\d+\.\d+) + // +kubebuilder:validation:Pattern=(\d+\.\d+\.\d+) ServerVersion string `json:"serverVersion"` // Cassandra server image name. Use of ImageConfig to match ServerVersion is recommended instead of this value. diff --git a/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml b/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml index e77540772..e2abe981f 100644 --- a/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml +++ b/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml @@ -9883,7 +9883,7 @@ spec: description: |- Version string for config builder, used to generate Cassandra server configuration - pattern: (6\.[89]\.\d+)|(3\.11\.\d+)|(4\.\d+\.\d+)|(5\.\d+\.\d+)|(1\.\d+\.\d+) + pattern: (\d+\.\d+\.\d+) type: string serviceAccount: description: Deprecated DeprecatedServiceAccount Use ServiceAccountName diff --git a/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook.go b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook.go index 7753e44d0..501a592a0 100644 --- a/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook.go +++ b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook.go @@ -19,7 +19,6 @@ import ( "github.com/google/go-cmp/cmp" api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" - "github.com/k8ssandra/cass-operator/pkg/images" ) // log is for logging in this package. @@ -104,32 +103,12 @@ func (v *CassandraDatacenterCustomValidator) ValidateDelete(ctx context.Context, // ValidateSingleDatacenter checks that no values are improperly set on a CassandraDatacenter func ValidateSingleDatacenter(dc *api.CassandraDatacenter) error { - // Ensure serverVersion and serverType are compatible - - if dc.Spec.ServerType == "dse" { - if !images.IsDseVersionSupported(dc.Spec.ServerVersion) { - return attemptedTo("use unsupported DSE version '%s'", dc.Spec.ServerVersion) - } - } - - if dc.Spec.ServerType == "hcd" { - if !images.IsHCDVersionSupported(dc.Spec.ServerVersion) { - return attemptedTo("use unsupported HCD version '%s'", dc.Spec.ServerVersion) - } - } - if dc.Spec.ServerType == "cassandra" && dc.Spec.DseWorkloads != nil { if dc.Spec.DseWorkloads.AnalyticsEnabled || dc.Spec.DseWorkloads.GraphEnabled || dc.Spec.DseWorkloads.SearchEnabled { return attemptedTo("enable DSE workloads if server type is Cassandra") } } - if dc.Spec.ServerType == "cassandra" { - if !images.IsOssVersionSupported(dc.Spec.ServerVersion) { - return attemptedTo("use unsupported Cassandra version '%s'", dc.Spec.ServerVersion) - } - } - isDse := dc.Spec.ServerType == "dse" isCassandra3 := dc.Spec.ServerType == "cassandra" && strings.HasPrefix(dc.Spec.ServerVersion, "3.") diff --git a/pkg/images/images.go b/pkg/images/images.go index 0be2ebe17..fbd5cee80 100644 --- a/pkg/images/images.go +++ b/pkg/images/images.go @@ -6,7 +6,6 @@ package images import ( "fmt" "os" - "regexp" "strings" corev1 "k8s.io/api/core/v1" @@ -27,9 +26,6 @@ type imageRegistry struct { } const ( - ValidDseVersionRegexp = "(6\\.[89]\\.\\d+)" - ValidHcdVersionRegexp = "(1\\.\\d+\\.\\d+)" - ValidOssVersionRegexp = "(3\\.11\\.\\d+)|(4\\.\\d+\\.\\d+)|(5\\.\\d+\\.\\d+)" DefaultCassandraRepository = "k8ssandra/cass-management-api" DefaultDSERepository = "datastax/dse-mgmtapi-6_8" DefaultHCDRepository = "datastax/hcd" @@ -73,21 +69,6 @@ func (i *imageRegistry) loadImageConfig(content []byte) (*configv1beta1.ImageCon return parsedImageConfig, nil } -func IsDseVersionSupported(version string) bool { - validVersions := regexp.MustCompile(ValidDseVersionRegexp) - return validVersions.MatchString(version) -} - -func IsOssVersionSupported(version string) bool { - validVersions := regexp.MustCompile(ValidOssVersionRegexp) - return validVersions.MatchString(version) -} - -func IsHCDVersionSupported(version string) bool { - validVersions := regexp.MustCompile(ValidHcdVersionRegexp) - return validVersions.MatchString(version) -} - func (i *imageRegistry) splitRegistry(image string) (registry string, imageNoRegistry string) { comps := strings.Split(image, "/") @@ -230,17 +211,9 @@ func (i *imageRegistry) GetCassandraImage(serverType, version string) (string, e switch serverType { case "dse": - if !IsDseVersionSupported(version) { - return "", fmt.Errorf("server 'dse' and version '%s' do not work together", version) - } case "cassandra": - if !IsOssVersionSupported(version) { - return "", fmt.Errorf("server 'cassandra' and version '%s' do not work together", version) - } case "hcd": - if !IsHCDVersionSupported(version) { - return "", fmt.Errorf("server 'hcd' and version '%s' do not work together", version) - } + break default: return "", fmt.Errorf("server type '%s' is not supported", serverType) } diff --git a/pkg/images/images_test.go b/pkg/images/images_test.go index fe89fc28a..43caa704f 100644 --- a/pkg/images/images_test.go +++ b/pkg/images/images_test.go @@ -168,15 +168,6 @@ func TestDefaultRepositories(t *testing.T) { assert.Equal("datastax/dse-mgmtapi-6_8:6.8.17", path) } -func TestOssValidVersions(t *testing.T) { - assert := assert.New(t) - assert.True(IsOssVersionSupported("4.0.0")) - assert.True(IsOssVersionSupported("4.1.0")) - assert.False(IsOssVersionSupported("4.0")) - assert.False(IsOssVersionSupported("4.1")) - assert.False(IsOssVersionSupported("6.8.0")) -} - func TestPullPolicyOverride(t *testing.T) { assert := require.New(t) imageConfigFile := filepath.Join("..", "..", "tests", "testdata", "image_config_parsing.yaml") From 05a232b80ad4e58f0f9c38971124ec952c08643b Mon Sep 17 00:00:00 2001 From: Michael Burman Date: Mon, 16 Mar 2026 19:54:04 +0200 Subject: [PATCH 2/5] =?UTF-8?q?Fix=20CHANGELOG=20from=20the=20master=C2=A0?= =?UTF-8?q?branch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcca87cc9..eccc52046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,12 +14,12 @@ Changelog for Cass Operator, new PRs should update the `main / unreleased` secti * [CHANGE] [#905](https://github.com/k8ssandra/cass-operator/issues/905) Relax the ServerVersion checks to structure only without separating OSS/DSE/HCD. * [FEATURE] [#893](https://github.com/k8ssandra/cass-operator/issues/893) Add support for maxUnavailable (Kubernetes 1.35 and up). This allows to make changes to the Cassandra pods in parallel, thus speeding up changes in larger clusters. Allows integer or percentage setting, but will never target more than one rack at a time. * [ENHANCEMENT] [#888](https://github.com/k8ssandra/cass-operator/issues/888) Add new metrics around all calls to the mgmt-api. This allows to track if some calls are taking longer to execute than expected. +* [ENHANCEMENT] [#873](https://github.com/k8ssandra/cass-operator/issues/873) Allow replacing multiple previously bootstrapped nodes in parallel. Also, the CassandraTask to replace pod accepts RackName as alternative to PodName as filtering rule. ## v1.29.1 * [BUGFIX] [#899](https://github.com/k8ssandra/cass-operator/issues/899) Skip webhook startup when the manager is launched without `--webhook-cert-path` (Helm chart behavior). * [BUGFIX] [#887](https://github.com/k8ssandra/cass-operator/issues/887) Prevents infinite loop when seed refresh times out during node failures, allowing the operator to recover. -* [ENHANCEMENT] [#873](https://github.com/k8ssandra/cass-operator/issues/873) Allow replacing multiple previously bootstrapped nodes in parallel. Also, the CassandraTask to replace pod accepts RackName as alternative to PodName as filtering rule. ## v1.29.0 From 142f8c8b9096e65ecc533af9036f284b11362f44 Mon Sep 17 00:00:00 2001 From: Michael Burman Date: Tue, 17 Mar 2026 10:09:09 +0200 Subject: [PATCH 3/5] Fix unit test --- .../construct_podtemplatespec_test.go | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/pkg/reconciliation/construct_podtemplatespec_test.go b/pkg/reconciliation/construct_podtemplatespec_test.go index e4b622953..a37331be7 100644 --- a/pkg/reconciliation/construct_podtemplatespec_test.go +++ b/pkg/reconciliation/construct_podtemplatespec_test.go @@ -1580,26 +1580,6 @@ func Test_makeImage(t *testing.T) { want: "datastax.jfrog.io/secret-debug-image/dse-server:6.8.0-test123", errString: "", }, - { - name: "test unknown dse version", - args: args{ - serverImage: "", - serverType: "dse", - serverVersion: "6.7.0", - }, - want: "", - errString: "server 'dse' and version '6.7.0' do not work together", - }, - { - name: "test unknown cassandra version", - args: args{ - serverImage: "", - serverType: "cassandra", - serverVersion: "3.10.0", - }, - want: "", - errString: "server 'cassandra' and version '3.10.0' do not work together", - }, { name: "test fallback", args: args{ From f738a595ec3abd6edb0f2c9500f06f0da2981c87 Mon Sep 17 00:00:00 2001 From: Michael Burman Date: Mon, 23 Mar 2026 14:40:22 +0200 Subject: [PATCH 4/5] Fix webhook test --- .../cassandradatacenter_webhook_test.go | 65 ------------------- 1 file changed, 65 deletions(-) diff --git a/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook_test.go b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook_test.go index b1f30335a..37aeae866 100644 --- a/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook_test.go +++ b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook_test.go @@ -75,45 +75,6 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, errString: "", }, - { - name: "DSE 7.0.0 invalid", - dc: &api.CassandraDatacenter{ - ObjectMeta: metav1.ObjectMeta{ - Name: "exampleDC", - }, - Spec: api.CassandraDatacenterSpec{ - ServerType: "dse", - ServerVersion: "7.0.0", - }, - }, - errString: "use unsupported DSE version '7.0.0'", - }, - { - name: "DSE Invalid", - dc: &api.CassandraDatacenter{ - ObjectMeta: metav1.ObjectMeta{ - Name: "exampleDC", - }, - Spec: api.CassandraDatacenterSpec{ - ServerType: "dse", - ServerVersion: "4.8.0", - }, - }, - errString: "use unsupported DSE version '4.8.0'", - }, - { - name: "DSE 5 Invalid", - dc: &api.CassandraDatacenter{ - ObjectMeta: metav1.ObjectMeta{ - Name: "exampleDC", - }, - Spec: api.CassandraDatacenterSpec{ - ServerType: "dse", - ServerVersion: "5.0.0", - }, - }, - errString: "use unsupported DSE version '5.0.0'", - }, { name: "Cassandra valid", dc: &api.CassandraDatacenter{ @@ -166,32 +127,6 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, errString: "", }, - { - name: "Cassandra Invalid", - dc: &api.CassandraDatacenter{ - ObjectMeta: metav1.ObjectMeta{ - Name: "exampleDC", - }, - Spec: api.CassandraDatacenterSpec{ - ServerType: "cassandra", - ServerVersion: "6.8.0", - }, - }, - errString: "use unsupported Cassandra version '6.8.0'", - }, - { - name: "Cassandra Invalid too", - dc: &api.CassandraDatacenter{ - ObjectMeta: metav1.ObjectMeta{ - Name: "exampleDC", - }, - Spec: api.CassandraDatacenterSpec{ - ServerType: "cassandra", - ServerVersion: "7.0.0", - }, - }, - errString: "use unsupported Cassandra version '7.0.0'", - }, { name: "Dse Workloads in Cassandra Invalid", dc: &api.CassandraDatacenter{ From 454555eb610a4c6f38bd3530728899356ec55ceb Mon Sep 17 00:00:00 2001 From: Michael Burman Date: Mon, 23 Mar 2026 18:01:09 +0200 Subject: [PATCH 5/5] Remove regexp from the webhook e2e test --- tests/webhook_validation/webhook_validation_suite_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/webhook_validation/webhook_validation_suite_test.go b/tests/webhook_validation/webhook_validation_suite_test.go index 40f96473f..c5fc1e6c2 100644 --- a/tests/webhook_validation/webhook_validation_suite_test.go +++ b/tests/webhook_validation/webhook_validation_suite_test.go @@ -81,11 +81,6 @@ var _ = Describe(testName, func() { FormatOutput(json) ns.WaitForOutputAndLog(step, k, "Ready", 30) - step = "attempt to use invalid dse version" - json = "{\"spec\": {\"serverType\": \"dse\", \"serverVersion\": \"6.7.0\"}}" - k = kubectl.PatchMerge(dcResource, json) - ns.ExecAndLogAndExpectErrorString(step, k, - `spec.serverVersion: Invalid value: "6.7.0": spec.serverVersion in body should match '(6\.[89]\.\d+)|(3\.11\.\d+)|(4\.\d+\.\d+)|(5\.\d+\.\d+)|(1\.\d+\.\d+)'`) step = "attempt to change the cluster name" json = "{\"spec\": {\"clusterName\": \"NewName\"}}" k = kubectl.PatchMerge(dcResource, json)