diff --git a/.github/workflows/test_and_build_image.yaml b/.github/workflows/test_and_build_image.yaml index c5f446a14..0892b4292 100644 --- a/.github/workflows/test_and_build_image.yaml +++ b/.github/workflows/test_and_build_image.yaml @@ -28,16 +28,16 @@ jobs: with: go-version-file: 'go.mod' cache: true - - name: Create temporary directory for yq install - run: | - mkdir ${{ runner.temp }}/yq - - name: Install yq - working-directory: ${{ runner.temp }}/yq - run: | - sudo rm /bin/yq - wget https://github.com/mikefarah/yq/releases/download/v4.11.2/yq_linux_amd64.tar.gz - tar -xzf yq_linux_amd64.tar.gz - sudo mv ./yq_linux_amd64 /usr/bin/yq + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: latest + # GHA requires longer timeout + args: --timeout=10m + # Optional: show only new issues if it's a pull request. The default value is `false`. + only-new-issues: ${{ github.event_name == 'pull_request' }} + skip-pkg-cache: true + skip-build-cache: true - name: Run unit and integration tests run: | export PATH=$GOROOT/bin:$GOPATH/bin:$PATH diff --git a/CHANGELOG/CHANGELOG-1.10.md b/CHANGELOG/CHANGELOG-1.10.md index 256acf7aa..7a05a8fd8 100644 --- a/CHANGELOG/CHANGELOG-1.10.md +++ b/CHANGELOG/CHANGELOG-1.10.md @@ -16,4 +16,5 @@ When cutting a new release, update the `unreleased` heading to the tag being gen ## unreleased * [BUGFIX] [#1060](https://github.com/k8ssandra/k8ssandra-operator/issues/1060) Fix restore mapping shuffling nodes when restoring in place -* [BUGFIX] [#1061](https://github.com/k8ssandra/k8ssandra-operator/issues/1061) Point to cass-config-builder 1.0.7 for arm64 compatibility \ No newline at end of file +* [BUGFIX] [#1061](https://github.com/k8ssandra/k8ssandra-operator/issues/1061) Point to cass-config-builder 1.0.7 for arm64 compatibility +* [ENHANCEMENT] [#956](https://github.com/k8ssandra/k8ssandra-operator/issues/956) Enable linting in the project diff --git a/Makefile b/Makefile index 2e801ca83..e248c66d1 100644 --- a/Makefile +++ b/Makefile @@ -124,20 +124,28 @@ help: ## Display this help. ##@ Development +.PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=k8ssandra-operator webhook paths="./..." output:crd:artifacts:config=config/crd/bases +.PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." +.PHONY: fmt fmt: ## Run go fmt against code. go fmt ./... +.PHONY: vet vet: ## Run go vet against code. go vet ./... +.PHONY: lint +lint: golangci-lint ## Run golangci-lint against code. + $(GOLANGCI_LINT) run ./... + ENVTEST_ASSETS_DIR=$(shell pwd)/testbin -test: manifests generate fmt vet envtest ## Run tests. +test: manifests generate fmt vet lint envtest ## Run tests. ifdef TEST @echo Running test $(TEST) KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $(GO_FLAGS) ./apis/... ./pkg/... ./test/yq/... ./controllers/... -run="$(TEST)" -covermode=atomic -coverprofile coverage.out @@ -310,11 +318,13 @@ $(LOCALBIN): KUSTOMIZE ?= $(LOCALBIN)/kustomize CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen ENVTEST ?= $(LOCALBIN)/setup-envtest +GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint # TODO Add linting to the GHA also ## Tool Versions -CERT_MANAGER_VERSION ?= v1.9.1 -KUSTOMIZE_VERSION ?= v4.5.7 -CONTROLLER_TOOLS_VERSION ?= v0.11.4 +CERT_MANAGER_VERSION ?= v1.12.2 +KUSTOMIZE_VERSION ?= v5.0.3 +CONTROLLER_TOOLS_VERSION ?= v0.12.0 +GOLINT_VERSION ?= 1.54.2 cert-manager: ## Install cert-manager to the cluster kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml @@ -370,17 +380,29 @@ create-clientconfig: --dest-context kind-k8ssandra-0; \ done - KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" .PHONY: kustomize -kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. +kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading. $(KUSTOMIZE): $(LOCALBIN) + @if test -x $(LOCALBIN)/kustomize && ! $(LOCALBIN)/kustomize version | grep -q $(KUSTOMIZE_VERSION); then \ + echo "$(LOCALBIN)/kustomize version is not expected $(KUSTOMIZE_VERSION). Removing it before installing."; \ + rm -rf $(LOCALBIN)/kustomize; \ + fi test -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } .PHONY: controller-gen -controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. +controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten. $(CONTROLLER_GEN): $(LOCALBIN) - test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) + test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \ + GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) + +.PHONY: golangci-lint +golangci-lint: + @if test -x $(LOCALBIN)/golangci-lint && ! $(LOCALBIN)/golangci-lint version | grep -q $(GOLINT_VERSION); then \ + echo "$(LOCALBIN)/golangci-lint version is not expected $(GOLINT_VERSION). Removing it before installing."; \ + rm -rf $(LOCALBIN)/golangci-lint; \ + fi + test -s $(LOCALBIN)/golangci-lint || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v$(GOLINT_VERSION) .PHONY: envtest envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. diff --git a/config/crd/bases/config.k8ssandra.io_clientconfigs.yaml b/config/crd/bases/config.k8ssandra.io_clientconfigs.yaml index e57ca23aa..ab9d1efa5 100644 --- a/config/crd/bases/config.k8ssandra.io_clientconfigs.yaml +++ b/config/crd/bases/config.k8ssandra.io_clientconfigs.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: clientconfigs.config.k8ssandra.io spec: group: config.k8ssandra.io diff --git a/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml b/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml index c0ab9295e..f934b7866 100644 --- a/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml +++ b/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: k8ssandratasks.control.k8ssandra.io spec: group: control.k8ssandra.io diff --git a/config/crd/bases/k8ssandra.io_k8ssandraclusters.yaml b/config/crd/bases/k8ssandra.io_k8ssandraclusters.yaml index b6e7305b1..a75d4bcbe 100644 --- a/config/crd/bases/k8ssandra.io_k8ssandraclusters.yaml +++ b/config/crd/bases/k8ssandra.io_k8ssandraclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: k8ssandraclusters.k8ssandra.io spec: group: k8ssandra.io diff --git a/config/crd/bases/medusa.k8ssandra.io_medusabackupjobs.yaml b/config/crd/bases/medusa.k8ssandra.io_medusabackupjobs.yaml index 927ff6c7b..33eaa97f5 100644 --- a/config/crd/bases/medusa.k8ssandra.io_medusabackupjobs.yaml +++ b/config/crd/bases/medusa.k8ssandra.io_medusabackupjobs.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: medusabackupjobs.medusa.k8ssandra.io spec: group: medusa.k8ssandra.io diff --git a/config/crd/bases/medusa.k8ssandra.io_medusabackups.yaml b/config/crd/bases/medusa.k8ssandra.io_medusabackups.yaml index 392dfe754..889024845 100644 --- a/config/crd/bases/medusa.k8ssandra.io_medusabackups.yaml +++ b/config/crd/bases/medusa.k8ssandra.io_medusabackups.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: medusabackups.medusa.k8ssandra.io spec: group: medusa.k8ssandra.io diff --git a/config/crd/bases/medusa.k8ssandra.io_medusabackupschedules.yaml b/config/crd/bases/medusa.k8ssandra.io_medusabackupschedules.yaml index bc1646f3a..840c29823 100644 --- a/config/crd/bases/medusa.k8ssandra.io_medusabackupschedules.yaml +++ b/config/crd/bases/medusa.k8ssandra.io_medusabackupschedules.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: medusabackupschedules.medusa.k8ssandra.io spec: group: medusa.k8ssandra.io diff --git a/config/crd/bases/medusa.k8ssandra.io_medusarestorejobs.yaml b/config/crd/bases/medusa.k8ssandra.io_medusarestorejobs.yaml index dfb48f722..cc4aec7f8 100644 --- a/config/crd/bases/medusa.k8ssandra.io_medusarestorejobs.yaml +++ b/config/crd/bases/medusa.k8ssandra.io_medusarestorejobs.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: medusarestorejobs.medusa.k8ssandra.io spec: group: medusa.k8ssandra.io diff --git a/config/crd/bases/medusa.k8ssandra.io_medusatasks.yaml b/config/crd/bases/medusa.k8ssandra.io_medusatasks.yaml index 3a72dfd37..9a603a5bb 100644 --- a/config/crd/bases/medusa.k8ssandra.io_medusatasks.yaml +++ b/config/crd/bases/medusa.k8ssandra.io_medusatasks.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: medusatasks.medusa.k8ssandra.io spec: group: medusa.k8ssandra.io diff --git a/config/crd/bases/reaper.k8ssandra.io_reapers.yaml b/config/crd/bases/reaper.k8ssandra.io_reapers.yaml index 910012e2d..9602344bd 100644 --- a/config/crd/bases/reaper.k8ssandra.io_reapers.yaml +++ b/config/crd/bases/reaper.k8ssandra.io_reapers.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: reapers.reaper.k8ssandra.io spec: group: reaper.k8ssandra.io diff --git a/config/crd/bases/replication.k8ssandra.io_replicatedsecrets.yaml b/config/crd/bases/replication.k8ssandra.io_replicatedsecrets.yaml index c17acc202..7db1d9388 100644 --- a/config/crd/bases/replication.k8ssandra.io_replicatedsecrets.yaml +++ b/config/crd/bases/replication.k8ssandra.io_replicatedsecrets.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: replicatedsecrets.replication.k8ssandra.io spec: group: replication.k8ssandra.io diff --git a/config/crd/bases/stargate.k8ssandra.io_stargates.yaml b/config/crd/bases/stargate.k8ssandra.io_stargates.yaml index 758767d10..118d7db5f 100644 --- a/config/crd/bases/stargate.k8ssandra.io_stargates.yaml +++ b/config/crd/bases/stargate.k8ssandra.io_stargates.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.0 name: stargates.stargate.k8ssandra.io spec: group: stargate.k8ssandra.io diff --git a/controllers/k8ssandra/add_dc_test.go b/controllers/k8ssandra/add_dc_test.go index 37889de03..77cedad40 100644 --- a/controllers/k8ssandra/add_dc_test.go +++ b/controllers/k8ssandra/add_dc_test.go @@ -818,12 +818,6 @@ func verifyReplicationOfKeyspaceUpdated(t *testing.T, mockMgmtApi *testutils.Fak }, timeout, interval, fmt.Sprintf("failed to verify replication for keyspace %s updated", keyspace)) } -func verifyKeyspaceReplicationAltered(t *testing.T, mockMgmtApi *testutils.FakeManagementApiFacade, keyspace string, replication map[string]int) { - require.Eventually(t, func() bool { - return mockMgmtApi.GetFirstCall(testutils.AlterKeyspace, keyspace, replication) > -1 - }, timeout, interval, fmt.Sprintf("failed to verify replication for keyspace %s updated", keyspace)) -} - func verifyRebuildTaskCreated(ctx context.Context, t *testing.T, f *framework.Framework, targetDcKey, srcDcKey framework.ClusterKey) { t.Log("check that rebuild task was created") require := require.New(t) diff --git a/controllers/k8ssandra/auth_test.go b/controllers/k8ssandra/auth_test.go index 578827b08..e225a3431 100644 --- a/controllers/k8ssandra/auth_test.go +++ b/controllers/k8ssandra/auth_test.go @@ -31,7 +31,7 @@ func createSingleDcClusterNoAuth(t *testing.T, ctx context.Context, f *framework Name: "cluster1", }, Spec: api.K8ssandraClusterSpec{ - Auth: pointer.BoolPtr(false), + Auth: pointer.Bool(false), Cassandra: &api.CassandraClusterTemplate{ Datacenters: []api.CassandraDatacenterTemplate{{ Meta: api.EmbeddedObjectMeta{Name: "dc1"}, @@ -141,7 +141,7 @@ func createSingleDcClusterAuth(t *testing.T, ctx context.Context, f *framework.F Name: "cluster1", }, Spec: api.K8ssandraClusterSpec{ - Auth: pointer.BoolPtr(true), + Auth: pointer.Bool(true), Cassandra: &api.CassandraClusterTemplate{ Datacenters: []api.CassandraDatacenterTemplate{{ Meta: api.EmbeddedObjectMeta{Name: "dc1"}, @@ -255,7 +255,7 @@ func createSingleDcClusterAuthExternalSecrets(t *testing.T, ctx context.Context, Name: "cluster1", }, Spec: api.K8ssandraClusterSpec{ - Auth: pointer.BoolPtr(true), + Auth: pointer.Bool(true), Cassandra: &api.CassandraClusterTemplate{ Datacenters: []api.CassandraDatacenterTemplate{{ Meta: api.EmbeddedObjectMeta{Name: "dc1"}, @@ -383,7 +383,7 @@ func createSingleDcClusterExternalInternode(t *testing.T, ctx context.Context, f Name: "cluster1", }, Spec: api.K8ssandraClusterSpec{ - Auth: pointer.BoolPtr(true), + Auth: pointer.Bool(true), Cassandra: &api.CassandraClusterTemplate{ Datacenters: []api.CassandraDatacenterTemplate{{ Meta: api.EmbeddedObjectMeta{Name: "dc1"}, diff --git a/controllers/k8ssandra/cassandra_metrics_agent_test.go b/controllers/k8ssandra/cassandra_metrics_agent_test.go index 16e9aec26..ddb1fbf48 100644 --- a/controllers/k8ssandra/cassandra_metrics_agent_test.go +++ b/controllers/k8ssandra/cassandra_metrics_agent_test.go @@ -80,7 +80,6 @@ func createSingleDcClusterWithMetricsAgent(t *testing.T, ctx context.Context, f require.Eventually(f.DatacenterExists(ctx, dcKey), timeout, interval) // Check that we have the right volumes and volume mounts. dc := &cassdcapi.CassandraDatacenter{} - f.Get(ctx, dcKey, dc) if err := f.Get(ctx, dcKey, dc); err != nil { require.Fail("could not find dc") } diff --git a/controllers/k8ssandra/cleanup_test.go b/controllers/k8ssandra/cleanup_test.go index ce20f9d4a..790e63de2 100644 --- a/controllers/k8ssandra/cleanup_test.go +++ b/controllers/k8ssandra/cleanup_test.go @@ -7,6 +7,7 @@ import ( testlogr "github.com/go-logr/logr/testing" k8ssandraapi "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" k8ssandralabels "github.com/k8ssandra/k8ssandra-operator/pkg/labels" + "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -17,7 +18,7 @@ import ( ) func TestK8ssandraClusterReconciler_DeleteServices(t *testing.T) { - k8sMock := fake.NewFakeClient() + k8sMock := fake.NewClientBuilder().WithScheme(scheme.Scheme).Build() ctx := context.Background() logger := testlogr.NewTestLogger(t) @@ -38,7 +39,7 @@ func TestK8ssandraClusterReconciler_DeleteServices(t *testing.T) { }, } - k8sMock.Create(ctx, service) + require.NoError(t, k8sMock.Create(ctx, service)) res := K8ssandraClusterReconciler{ Client: k8sMock, @@ -46,20 +47,15 @@ func TestK8ssandraClusterReconciler_DeleteServices(t *testing.T) { } hasError := res.deleteServices(ctx, kc, k8ssandraapi.CassandraDatacenterTemplate{}, namespace, k8sMock, logger) - - if hasError != false { - t.Errorf("Error while deleting services") - } + require.False(t, hasError, "Error while deleting services") err := k8sMock.Get(ctx, client.ObjectKeyFromObject(service), service) - if err == nil || !errors.IsNotFound(err) { - t.Errorf("Service was not deleted: %v", err) - } - + require.Error(t, err) + require.True(t, errors.IsNotFound(err)) } func TestK8ssandraClusterReconciler_DeleteDeployments(t *testing.T) { - k8sMock := fake.NewFakeClient() + k8sMock := fake.NewClientBuilder().WithScheme(scheme.Scheme).Build() ctx := context.Background() logger := testlogr.NewTestLogger(t) @@ -80,7 +76,7 @@ func TestK8ssandraClusterReconciler_DeleteDeployments(t *testing.T) { }, } - k8sMock.Create(ctx, deployment) + require.NoError(t, k8sMock.Create(ctx, deployment)) res := K8ssandraClusterReconciler{ Client: k8sMock, diff --git a/controllers/k8ssandra/k8ssandracluster_controller_test.go b/controllers/k8ssandra/k8ssandracluster_controller_test.go index 73d44a76b..629fd43f1 100644 --- a/controllers/k8ssandra/k8ssandracluster_controller_test.go +++ b/controllers/k8ssandra/k8ssandracluster_controller_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "math/rand" "reflect" "testing" "time" @@ -13,6 +14,7 @@ import ( "github.com/k8ssandra/k8ssandra-operator/pkg/encryption" "github.com/k8ssandra/k8ssandra-operator/pkg/images" "github.com/k8ssandra/k8ssandra-operator/pkg/labels" + medusa "github.com/k8ssandra/k8ssandra-operator/pkg/medusa" "github.com/k8ssandra/k8ssandra-operator/pkg/utils" promapi "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" @@ -105,7 +107,6 @@ func TestK8ssandraCluster(t *testing.T) { t.Run("CreateSingleDcClusterExternalInternode", testEnv.ControllerTest(ctx, createSingleDcClusterExternalInternode)) // If webhooks are installed, this testcase is handled by the webhook test - // t.Run("ChangeNumTokensValue", testEnv.ControllerTest(ctx, changeNumTokensValue)) t.Run("ApplyClusterWithEncryptionOptions", testEnv.ControllerTest(ctx, applyClusterWithEncryptionOptions)) t.Run("ApplyClusterWithEncryptionOptionsFail", testEnv.ControllerTest(ctx, applyClusterWithEncryptionOptionsFail)) t.Run("ApplyClusterWithEncryptionOptionsExternalSecrets", testEnv.ControllerTest(ctx, applyClusterWithEncryptionOptionsExternalSecrets)) @@ -1427,120 +1428,6 @@ func createMultiDcClusterWithStargate(t *testing.T, ctx context.Context, f *fram f.AssertObjectDoesNotExist(ctx, t, sg2Key, &stargateapi.Stargate{}, timeout, interval) } -// changeNumTokensValue creates a Datacenter and then changes the numTokens value -// Such change is prohibited and should fail -func changeNumTokensValue(t *testing.T, ctx context.Context, f *framework.Framework, namespace string) { - require := require.New(t) - - kc := &api.K8ssandraCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: "test", - }, - Spec: api.K8ssandraClusterSpec{ - Cassandra: &api.CassandraClusterTemplate{ - DatacenterOptions: api.DatacenterOptions{ - CassandraConfig: &api.CassandraConfig{ - CassandraYaml: unstructured.Unstructured{ - "num_tokens": 16, - }, - }, - }, - Datacenters: []api.CassandraDatacenterTemplate{ - { - Meta: api.EmbeddedObjectMeta{ - Name: "dc1", - }, - K8sContext: f.DataPlaneContexts[0], - Size: 1, - DatacenterOptions: api.DatacenterOptions{ - ServerVersion: "3.11.14", - StorageConfig: &cassdcapi.StorageConfig{ - CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ - StorageClassName: &defaultStorageClass, - }, - }, - }, - }, - }, - }, - }, - } - - err := f.Client.Create(ctx, kc) - require.NoError(err, "failed to create K8ssandraCluster") - - verifyFinalizerAdded(ctx, t, f, client.ObjectKey{Namespace: kc.Namespace, Name: kc.Name}) - - verifySuperuserSecretCreated(ctx, t, f, kc) - - verifyReplicatedSecretReconciled(ctx, t, f, kc) - - verifySystemReplicationAnnotationSet(ctx, t, f, kc) - - t.Log("check that the datacenter was created") - - dcKey := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}, K8sContext: f.DataPlaneContexts[0]} - require.Eventually(f.DatacenterExists(ctx, dcKey), timeout, interval) - verifySecretAnnotationAdded(t, f, ctx, dcKey, secret.DefaultSuperuserSecretName(kc.SanitizedName())) - - lastTransitionTime := metav1.Now() - - t.Log("update datacenter status to scaling up") - err = f.PatchDatacenterStatus(ctx, dcKey, func(dc *cassdcapi.CassandraDatacenter) { - dc.SetCondition(cassdcapi.DatacenterCondition{ - Type: cassdcapi.DatacenterScalingUp, - Status: corev1.ConditionTrue, - LastTransitionTime: lastTransitionTime, - }) - }) - require.NoError(err, "failed to patch datacenter status") - - t.Log("update datacenter status to ready") - err = f.PatchDatacenterStatus(ctx, dcKey, func(dc *cassdcapi.CassandraDatacenter) { - lastTransitionTime = metav1.Now() - dc.SetCondition(cassdcapi.DatacenterCondition{ - Type: cassdcapi.DatacenterReady, - Status: corev1.ConditionTrue, - LastTransitionTime: lastTransitionTime, - }) - dc.SetCondition(cassdcapi.DatacenterCondition{ - Type: cassdcapi.DatacenterScalingUp, - Status: corev1.ConditionFalse, - LastTransitionTime: lastTransitionTime, - }) - }) - require.NoError(err, "failed to patch datacenter status") - - // Update the datacenter with a different num_tokens value and check that it failed - initialNumTokens := kc.Spec.Cassandra.DatacenterOptions.CassandraConfig.CassandraYaml["num_tokens"] - kcKey := framework.ClusterKey{NamespacedName: utils.GetKey(kc), K8sContext: f.ControlPlaneContext} - kcPatch := client.MergeFrom(kc.DeepCopy()) - kc.Spec.Cassandra.DatacenterOptions.CassandraConfig.CassandraYaml["num_tokens"] = 256 - err = f.Patch(ctx, kc, kcPatch, kcKey) - require.NoError(err, "got error patching num_tokens") - - err = f.Client.Get(ctx, kcKey.NamespacedName, kc) - require.NoError(err, "failed to get K8ssandraCluster") - dc := cassdcapi.CassandraDatacenter{} - err = f.Client.Get(ctx, dcKey.NamespacedName, &dc) - require.NoError(err, "failed to get CassandraDatacenter") - dcConfig, err := utils.UnmarshalToMap(dc.Spec.Config) - require.NoError(err, "failed to unmarshall CassandraDatacenter config") - dcConfigYaml, _ := dcConfig["cassandra-yaml"].(map[string]interface{}) - t.Logf("Initial num_tokens value: %d", initialNumTokens) - t.Logf("Spec num_tokens value: %d", kc.Spec.Cassandra.DatacenterOptions.CassandraConfig.CassandraYaml["num_tokens"]) - t.Logf("dcConfigYaml num tokens: %v", dcConfigYaml["num_tokens"].(float64)) - require.NotEqual(fmt.Sprintf("%v", dcConfigYaml["num_tokens"]), fmt.Sprintf("%d", kc.Spec.Cassandra.DatacenterOptions.CassandraConfig.CassandraYaml["num_tokens"]), "num_tokens should not be updated") - require.Equal(fmt.Sprintf("%v", dcConfigYaml["num_tokens"]), fmt.Sprintf("%d", initialNumTokens), "num_tokens should not be updated") - - // Test cluster deletion - t.Log("deleting K8ssandraCluster") - err = f.DeleteK8ssandraCluster(ctx, client.ObjectKey{Namespace: namespace, Name: kc.Name}, timeout, interval) - require.NoError(err, "failed to delete K8ssandraCluster") - f.AssertObjectDoesNotExist(ctx, t, dcKey, &cassdcapi.CassandraDatacenter{}, timeout, interval) -} - // Create a cluster with encryption options and Stargate. // Verify that volumes, mounts and config maps are correctly created. func applyClusterWithEncryptionOptions(t *testing.T, ctx context.Context, f *framework.Framework, namespace string) { @@ -1614,7 +1501,7 @@ func applyClusterWithEncryptionOptions(t *testing.T, ctx context.Context, f *fra for _, secret := range []*corev1.Secret{clientKeystore, clientTruststore, serverKeystore, serverTruststore, clientCertificates} { secretKey := utils.GetKey(secret) secretClusterKey0 := framework.ClusterKey{NamespacedName: secretKey, K8sContext: f.DataPlaneContexts[0]} - f.Create(ctx, secretClusterKey0, secret) + require.NoError(f.Create(ctx, secretClusterKey0, secret)) } // Create the cluster template with encryption enabled @@ -1706,7 +1593,8 @@ func applyClusterWithEncryptionOptions(t *testing.T, ctx context.Context, f *fra verifySystemReplicationAnnotationSet(ctx, t, f, kc) - reconcileMedusaStandaloneDeployment(ctx, t, f, kc, "dc1", f.DataPlaneContexts[0]) + medusaKey := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: medusa.MedusaStandaloneDeploymentName(kc.SanitizedName(), "dc1")}, K8sContext: f.DataPlaneContexts[0]} + require.NoError(f.SetMedusaDeplAvailable(ctx, medusaKey)) 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) @@ -1812,10 +1700,12 @@ func applyClusterWithEncryptionOptionsFail(t *testing.T, ctx context.Context, f dc1Size := int32(3) dc2Size := int32(3) + randNr := rand.Int31() + // Create the client keystore and truststore secrets clientKeystore := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: "client-keystore-secret", + Name: fmt.Sprintf("client-keystore-secret%d", randNr), Namespace: namespace, }, Data: map[string][]byte{ @@ -1825,7 +1715,7 @@ func applyClusterWithEncryptionOptionsFail(t *testing.T, ctx context.Context, f clientTruststore := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: "client-truststore-secret", + Name: fmt.Sprintf("client-truststore-secret%d", randNr), Namespace: namespace, }, Data: map[string][]byte{ @@ -1836,7 +1726,7 @@ func applyClusterWithEncryptionOptionsFail(t *testing.T, ctx context.Context, f // Create the client keystore and truststore secrets clientKeystoreSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: "client-keystore-password-secret", + Name: fmt.Sprintf("client-keystore-password-secret%d", randNr), Namespace: namespace, }, Data: map[string][]byte{ @@ -1846,7 +1736,7 @@ func applyClusterWithEncryptionOptionsFail(t *testing.T, ctx context.Context, f clientTruststoreSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: "client-truststore-password-secret", + Name: fmt.Sprintf("client-truststore-password-secret%d", randNr), Namespace: namespace, }, Data: map[string][]byte{ @@ -1856,11 +1746,14 @@ func applyClusterWithEncryptionOptionsFail(t *testing.T, ctx context.Context, f // Loop over the created configmaps and create them for _, secret := range []*corev1.Secret{clientKeystore, clientTruststore, clientKeystoreSecret, clientTruststoreSecret} { + secret2 := *secret + secretKey := utils.GetKey(secret) secretClusterKey0 := framework.ClusterKey{NamespacedName: secretKey, K8sContext: f.DataPlaneContexts[0]} secretClusterKey1 := framework.ClusterKey{NamespacedName: secretKey, K8sContext: f.DataPlaneContexts[1]} - f.Create(ctx, secretClusterKey0, secret) - f.Create(ctx, secretClusterKey1, secret) + + require.NoError(f.Create(ctx, secretClusterKey0, secret)) + require.NoError(f.Create(ctx, secretClusterKey1, &secret2)) } // Create the cluster template with encryption enabled for both server and client, but missing client encryption stores @@ -1907,10 +1800,10 @@ func applyClusterWithEncryptionOptionsFail(t *testing.T, ctx context.Context, f }, ServerEncryptionStores: &encryption.Stores{ KeystoreSecretRef: &encryption.SecretKeySelector{LocalObjectReference: corev1.LocalObjectReference{ - Name: "server-keystore-secret", + Name: fmt.Sprintf("server-keystore-secret%d", randNr), }}, TruststoreSecretRef: &encryption.SecretKeySelector{LocalObjectReference: corev1.LocalObjectReference{ - Name: "server-truststore-secret", + Name: fmt.Sprintf("server-truststore-secret%d", randNr), }}, }, }, @@ -2011,7 +1904,7 @@ func applyClusterWithEncryptionOptionsExternalSecrets(t *testing.T, ctx context. for _, secret := range []*corev1.Secret{clientKeystore, clientTruststore, serverKeystore, serverTruststore, clientCertificates} { secretKey := utils.GetKey(secret) secretClusterKey0 := framework.ClusterKey{NamespacedName: secretKey, K8sContext: f.DataPlaneContexts[0]} - f.Create(ctx, secretClusterKey0, secret) + require.NoError(f.Create(ctx, secretClusterKey0, secret)) } // Create the cluster template with encryption enabled @@ -2075,7 +1968,8 @@ func applyClusterWithEncryptionOptionsExternalSecrets(t *testing.T, ctx context. require.NoError(err, "failed to create K8ssandraCluster") verifyFinalizerAdded(ctx, t, f, client.ObjectKey{Namespace: kc.Namespace, Name: kc.Name}) - reconcileMedusaStandaloneDeployment(ctx, t, f, kc, "dc1", f.DataPlaneContexts[0]) + medusaKey := framework.ClusterKey{NamespacedName: types.NamespacedName{Namespace: namespace, Name: medusa.MedusaStandaloneDeploymentName(kc.SanitizedName(), "dc1")}, K8sContext: f.DataPlaneContexts[0]} + require.NoError(f.SetMedusaDeplAvailable(ctx, medusaKey)) 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) diff --git a/controllers/k8ssandra/medusa_reconciler.go b/controllers/k8ssandra/medusa_reconciler.go index e45faf56a..a4837c146 100644 --- a/controllers/k8ssandra/medusa_reconciler.go +++ b/controllers/k8ssandra/medusa_reconciler.go @@ -75,7 +75,9 @@ func (r *K8ssandraClusterReconciler) reconcileMedusa( if dcConfig.Meta.Pods.Annotations == nil { dcConfig.Meta.Pods.Annotations = map[string]string{} } - secret.AddInjectionAnnotationMedusaContainers(&dcConfig.Meta.Pods, cassandraUserSecretName) + if err := secret.AddInjectionAnnotationMedusaContainers(&dcConfig.Meta.Pods, cassandraUserSecretName); err != nil { + return result.Error(err) + } } // Reconcile the Medusa standalone deployment diff --git a/controllers/k8ssandra/medusa_reconciler_test.go b/controllers/k8ssandra/medusa_reconciler_test.go index 2b998aade..ac25c1511 100644 --- a/controllers/k8ssandra/medusa_reconciler_test.go +++ b/controllers/k8ssandra/medusa_reconciler_test.go @@ -375,7 +375,7 @@ func reconcileMedusaStandaloneDeployment(ctx context.Context, t *testing.T, f *f }, } medusaKey := framework.ClusterKey{NamespacedName: utils.GetKey(medusaDepl), K8sContext: k8sContext} - f.Create(ctx, medusaKey, medusaDepl) + require.NoError(t, f.Create(ctx, medusaKey, medusaDepl)) actualMedusaDepl := &appsv1.Deployment{} assert.Eventually(t, func() bool { diff --git a/controllers/medusa/medusabackupjob_controller.go b/controllers/medusa/medusabackupjob_controller.go index 0d9da5452..cd6c32eab 100644 --- a/controllers/medusa/medusabackupjob_controller.go +++ b/controllers/medusa/medusabackupjob_controller.go @@ -297,7 +297,7 @@ func (r *MedusaBackupJobReconciler) createMedusaBackup(ctx context.Context, back func doMedusaBackup(ctx context.Context, name string, backupType shared.BackupType, pod *corev1.Pod, clientFactory medusa.ClientFactory, logger logr.Logger) (string, error) { addr := net.JoinHostPort(pod.Status.PodIP, fmt.Sprint(shared.BackupSidecarPort)) logger.Info("connecting to backup sidecar", "Pod", pod.Name, "Address", addr) - if medusaClient, err := clientFactory.NewClient(addr); err != nil { + if medusaClient, err := clientFactory.NewClient(ctx, addr); err != nil { return "", err } else { logger.Info("successfully connected to backup sidecar", "Pod", pod.Name, "Address", addr) @@ -314,7 +314,7 @@ func doMedusaBackup(ctx context.Context, name string, backupType shared.BackupTy func backupStatus(ctx context.Context, name string, pod *corev1.Pod, clientFactory medusa.ClientFactory, logger logr.Logger) (medusa.StatusType, error) { addr := net.JoinHostPort(pod.Status.PodIP, fmt.Sprint(shared.BackupSidecarPort)) logger.Info("connecting to backup sidecar", "Pod", pod.Name, "Address", addr) - if medusaClient, err := clientFactory.NewClient(addr); err != nil { + if medusaClient, err := clientFactory.NewClient(ctx, addr); err != nil { return medusa.StatusType_UNKNOWN, err } else { resp, err := medusaClient.BackupStatus(ctx, name) diff --git a/controllers/medusa/medusabackupjob_controller_test.go b/controllers/medusa/medusabackupjob_controller_test.go index 5f2ba7e95..472b09903 100644 --- a/controllers/medusa/medusabackupjob_controller_test.go +++ b/controllers/medusa/medusabackupjob_controller_test.go @@ -299,7 +299,7 @@ func NewMedusaClientFactory() *fakeMedusaClientFactory { return &fakeMedusaClientFactory{clients: make(map[string]*fakeMedusaClient, 0)} } -func (f *fakeMedusaClientFactory) NewClient(address string) (medusa.Client, error) { +func (f *fakeMedusaClientFactory) NewClient(ctx context.Context, address string) (medusa.Client, error) { f.clientsMutex.Lock() defer f.clientsMutex.Unlock() _, ok := f.clients[address] @@ -490,7 +490,7 @@ func reconcileMedusaStandaloneDeployment(ctx context.Context, t *testing.T, f *f }, } medusaKey := framework.ClusterKey{NamespacedName: utils.GetKey(medusaDepl), K8sContext: k8sContext} - f.Create(ctx, medusaKey, medusaDepl) + require.NoError(t, f.Create(ctx, medusaKey, medusaDepl)) actualMedusaDepl := &appsv1.Deployment{} assert.Eventually(t, func() bool { diff --git a/controllers/medusa/medusabackupschedule_controller_test.go b/controllers/medusa/medusabackupschedule_controller_test.go index b5d3c8697..36067bc01 100644 --- a/controllers/medusa/medusabackupschedule_controller_test.go +++ b/controllers/medusa/medusabackupschedule_controller_test.go @@ -41,7 +41,8 @@ func TestScheduler(t *testing.T) { }, }, } - medusav1alpha1.AddToScheme(scheme.Scheme) + err := medusav1alpha1.AddToScheme(scheme.Scheme) + require.NoError(err) fakeClient := fake.NewClientBuilder(). WithRuntimeObjects(backupSchedule). @@ -163,7 +164,8 @@ func TestSchedulerParseError(t *testing.T) { }, }, } - medusav1alpha1.AddToScheme(scheme.Scheme) + err := medusav1alpha1.AddToScheme(scheme.Scheme) + require.NoError(err) fakeClient := fake.NewClientBuilder(). WithRuntimeObjects(backupSchedule). @@ -183,6 +185,6 @@ func TestSchedulerParseError(t *testing.T) { Namespace: backupSchedule.Namespace, } - _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: nsName}) + _, err = r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: nsName}) require.Error(err) } diff --git a/controllers/medusa/medusarestorejob_controller.go b/controllers/medusa/medusarestorejob_controller.go index c110a576e..3308acc96 100644 --- a/controllers/medusa/medusarestorejob_controller.go +++ b/controllers/medusa/medusarestorejob_controller.go @@ -254,7 +254,7 @@ func (r *MedusaRestoreJobReconciler) podTemplateSpecUpdateComplete(ctx context.C // prepareRestore prepares the MedusaRestoreMapping for the restore operation. // It uses the Medusa client to get the host map for the restore operation, using the Medusa standalone service to get the backup topology. func (r *MedusaRestoreJobReconciler) prepareRestore(ctx context.Context, request *medusa.RestoreRequest) (*medusav1alpha1.MedusaRestoreMapping, error) { - medusaClient, err := r.ClientFactory.NewClient(medusaServiceUrl( + medusaClient, err := r.ClientFactory.NewClient(ctx, medusaServiceUrl( cassdcapi.CleanupForKubernetes(request.Datacenter.Spec.ClusterName), request.Datacenter.SanitizedName(), request.Datacenter.Namespace)) diff --git a/controllers/medusa/medusarestorejob_controller_test.go b/controllers/medusa/medusarestorejob_controller_test.go index 33239addb..87ec12e37 100644 --- a/controllers/medusa/medusarestorejob_controller_test.go +++ b/controllers/medusa/medusarestorejob_controller_test.go @@ -27,7 +27,8 @@ const ( func testMedusaRestoreDatacenter(t *testing.T, ctx context.Context, f *framework.Framework, namespace string) { require := require.New(t) - f.Client.DeleteAllOf(ctx, &corev1.Pod{}, client.InNamespace(namespace)) + err := f.Client.DeleteAllOf(ctx, &corev1.Pod{}, client.InNamespace(namespace)) + require.NoError(err) k8sCtx0 := f.DataPlaneContexts[0] kc := &k8ss.K8ssandraCluster{ @@ -73,8 +74,7 @@ func testMedusaRestoreDatacenter(t *testing.T, ctx context.Context, f *framework } t.Log("Creating k8ssandracluster with Medusa") - err := f.Client.Create(ctx, kc) - require.NoError(err, "failed to create K8ssandraCluster") + require.NoError(f.Client.Create(ctx, kc), "failed to create K8ssandraCluster") reconcileReplicatedSecret(ctx, t, f, kc) reconcileMedusaStandaloneDeployment(ctx, t, f, kc, "real-dc1", f.DataPlaneContexts[0]) @@ -298,7 +298,7 @@ func testMedusaRestoreDatacenter(t *testing.T, ctx context.Context, f *framework func testValidationErrorStopsRestore(t *testing.T, ctx context.Context, f *framework.Framework, namespace string) { require := require.New(t) - f.Client.DeleteAllOf(ctx, &corev1.Pod{}, client.InNamespace(namespace)) + require.NoError(f.Client.DeleteAllOf(ctx, &corev1.Pod{}, client.InNamespace(namespace))) k8sCtx0 := f.DataPlaneContexts[0] kc := &k8ss.K8ssandraCluster{ @@ -572,7 +572,7 @@ func NewMedusaClientRestoreFactory() *fakeMedusaRestoreClientFactory { return &fakeMedusaRestoreClientFactory{clients: make(map[string]*fakeMedusaRestoreClient, 0)} } -func (f *fakeMedusaRestoreClientFactory) NewClient(address string) (medusa.Client, error) { +func (f *fakeMedusaRestoreClientFactory) NewClient(ctx context.Context, address string) (medusa.Client, error) { f.clientsMutex.Lock() defer f.clientsMutex.Unlock() _, ok := f.clients[address] diff --git a/controllers/medusa/medusatask_controller.go b/controllers/medusa/medusatask_controller.go index 24279da41..6f265a0f8 100644 --- a/controllers/medusa/medusatask_controller.go +++ b/controllers/medusa/medusatask_controller.go @@ -395,7 +395,7 @@ func (r *MedusaTaskReconciler) scheduleSyncForPurge(task *medusav1alpha1.MedusaT func doPurge(ctx context.Context, task *medusav1alpha1.MedusaTask, pod *corev1.Pod, clientFactory medusa.ClientFactory) (*medusa.PurgeBackupsResponse, error) { addr := net.JoinHostPort(pod.Status.PodIP, fmt.Sprint(shared.BackupSidecarPort)) - if medusaClient, err := clientFactory.NewClient(addr); err != nil { + if medusaClient, err := clientFactory.NewClient(ctx, addr); err != nil { return nil, err } else { defer medusaClient.Close() @@ -405,7 +405,7 @@ func doPurge(ctx context.Context, task *medusav1alpha1.MedusaTask, pod *corev1.P func prepareRestore(ctx context.Context, task *medusav1alpha1.MedusaTask, pod *corev1.Pod, clientFactory medusa.ClientFactory) (*medusa.PurgeBackupsResponse, error) { addr := net.JoinHostPort(pod.Status.PodIP, fmt.Sprint(shared.BackupSidecarPort)) - if medusaClient, err := clientFactory.NewClient(addr); err != nil { + if medusaClient, err := clientFactory.NewClient(ctx, addr); err != nil { return nil, err } else { defer medusaClient.Close() @@ -416,7 +416,7 @@ func prepareRestore(ctx context.Context, task *medusav1alpha1.MedusaTask, pod *c func GetBackups(ctx context.Context, pod *corev1.Pod, clientFactory medusa.ClientFactory) ([]*medusa.BackupSummary, error) { addr := net.JoinHostPort(pod.Status.PodIP, fmt.Sprint(shared.BackupSidecarPort)) - if medusaClient, err := clientFactory.NewClient(addr); err != nil { + if medusaClient, err := clientFactory.NewClient(ctx, addr); err != nil { return nil, err } else { defer medusaClient.Close() diff --git a/controllers/reaper/reaper_controller_test.go b/controllers/reaper/reaper_controller_test.go index ad1c24d7d..49c85939b 100644 --- a/controllers/reaper/reaper_controller_test.go +++ b/controllers/reaper/reaper_controller_test.go @@ -473,7 +473,10 @@ func testCreateReaperWithAuthEnabledExternalSecret(t *testing.T, ctx context.Con // these shouldn't be set when SecretsProvider=='external', but verifying // the env vars aren't created even if they are set rpr.Spec.CassandraUserSecretRef.Name = "top-secret-cass" - rpr.Spec.JmxUserSecretRef.Name = "top-secret-jmx" + + //lint:ignore SA1019 Verify deprecated method is ineffective + rpr.Spec.JmxUserSecretRef.Name = "top-secret-jmx" //nolint:staticcheck + rpr.Spec.UiUserSecretRef.Name = "top-secret-ui" err = k8sClient.Create(ctx, rpr) require.NoError(t, err) diff --git a/controllers/secrets-webhook/secretswebhook.go b/controllers/secrets-webhook/secretswebhook.go index fd2b5ef42..dcbce076a 100644 --- a/controllers/secrets-webhook/secretswebhook.go +++ b/controllers/secrets-webhook/secretswebhook.go @@ -158,7 +158,7 @@ func injectVolume(pod *corev1.Pod, volume corev1.Volume) { func injectVolumeMount(pod *corev1.Pod, volumeMount corev1.VolumeMount, containers []string) { var all bool s := make(map[string]bool) - if containers == nil || len(containers) == 0 { + if len(containers) == 0 { all = true } else { for _, c := range containers { diff --git a/controllers/secrets-webhook/secretswebhook_test.go b/controllers/secrets-webhook/secretswebhook_test.go index 67f9d159f..29ede1a65 100644 --- a/controllers/secrets-webhook/secretswebhook_test.go +++ b/controllers/secrets-webhook/secretswebhook_test.go @@ -3,14 +3,13 @@ package secrets_webhook import ( "context" "encoding/json" - "fmt" + "sort" "testing" "github.com/stretchr/testify/assert" admissionv1 "k8s.io/api/admission/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" log "sigs.k8s.io/controller-runtime/pkg/log" @@ -20,9 +19,10 @@ import ( func TestHandleInjectSecretSuccess(t *testing.T) { p := setupSecretsInjector(t) + assert := assert.New(t) pod := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "k8ssandra.io/inject-secret": `[{"name": "mySecret", "path": "/my/secret/path"}]`, @@ -37,21 +37,24 @@ func TestHandleInjectSecretSuccess(t *testing.T) { req := createRequest(t, pod) resp := p.Handle(context.Background(), req) - fmt.Println(fmt.Sprintf("%v", resp)) - assert.Equal(t, true, resp.AdmissionResponse.Allowed) + assert.True(resp.AdmissionResponse.Allowed) // 2 patches for addition of volume and volumeMount, but the order of the patches may vary - assert.Equal(t, len(resp.Patches), 2) - testPasses := (resp.Patches[0].Path == "/spec/volumes" && resp.Patches[1].Path == "/spec/containers/0/volumeMounts") || (resp.Patches[1].Path == "/spec/volumes" && resp.Patches[0].Path == "/spec/containers/0/volumeMounts") - assert.True(t, testPasses) - assert.Equal(t, resp.Patches[0].Operation, "add") - assert.Equal(t, resp.Patches[1].Operation, "add") + assert.Equal(len(resp.Patches), 2) + + sort.Slice(resp.Patches, func(i, j int) bool { + return resp.Patches[i].Path > resp.Patches[j].Path + }) + assert.Equal(resp.Patches[0].Path, "/spec/volumes") + assert.Equal(resp.Patches[1].Path, "/spec/containers/0/volumeMounts") + assert.Equal(resp.Patches[0].Operation, "add") + assert.Equal(resp.Patches[1].Operation, "add") } func TestHandleInjectSecretNoPatch(t *testing.T) { p := setupSecretsInjector(t) pod := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "fake-annotation": `fake-val`, @@ -73,7 +76,7 @@ func TestHandleInjectSecretNoPatch(t *testing.T) { func TestMutatePodsSingleSecret(t *testing.T) { want := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "k8ssandra.io/inject-secret": `[{"name": "mySecret", "path": "/my/secret/path"}]`, @@ -99,7 +102,7 @@ func TestMutatePodsSingleSecret(t *testing.T) { } pod := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "k8ssandra.io/inject-secret": `[{"name": "mySecret", "path": "/my/secret/path"}]`, @@ -128,7 +131,7 @@ func TestMutatePodsMutliSecret(t *testing.T) { {"name": "myOtherSecret", "path": "/my/other/secret/path"}]` want := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "k8ssandra.io/inject-secret": injectionAnnotation, @@ -170,7 +173,7 @@ func TestMutatePodsMutliSecret(t *testing.T) { } pod := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "k8ssandra.io/inject-secret": injectionAnnotation, @@ -200,7 +203,9 @@ func setupSecretsInjector(t *testing.T) *podSecretsInjector { if err != nil { t.Fatal(err) } - p.InjectDecoder(d) + if err := p.InjectDecoder(d); err != nil { + t.Fatal(err) + } return p } @@ -225,7 +230,7 @@ func createRequest(t *testing.T, pod *corev1.Pod) webhook.AdmissionRequest { func TestMutatePodsExpandKey(t *testing.T) { want := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "cluster2-dc2-r1-sts-0", Namespace: "test-ns", Annotations: map[string]string{ @@ -252,7 +257,7 @@ func TestMutatePodsExpandKey(t *testing.T) { } pod := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "cluster2-dc2-r1-sts-0", Namespace: "test-ns", Annotations: map[string]string{ @@ -281,7 +286,7 @@ func TestMutatePodsSpecifyContainer(t *testing.T) { injectionAnnotation := `[{"name": "mySecret", "path": "/my/secret/path", "containers": ["test"]}]` want := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "k8ssandra.io/inject-secret": injectionAnnotation, @@ -316,7 +321,7 @@ func TestMutatePodsSpecifyContainer(t *testing.T) { } pod := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "test", Annotations: map[string]string{ "k8ssandra.io/inject-secret": injectionAnnotation, diff --git a/controllers/stargate/stargate_controller_test.go b/controllers/stargate/stargate_controller_test.go index 752ff6932..b0db1f134 100644 --- a/controllers/stargate/stargate_controller_test.go +++ b/controllers/stargate/stargate_controller_test.go @@ -12,6 +12,7 @@ import ( "github.com/k8ssandra/k8ssandra-operator/pkg/encryption" "github.com/k8ssandra/k8ssandra-operator/pkg/stargate" promapi "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + "k8s.io/apimachinery/pkg/api/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors" cassdcapi "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" @@ -517,7 +518,7 @@ func testCreateStargateEncryption(t *testing.T, ctx context.Context, testClient // Loop over the secrets and create them for _, secret := range []*corev1.Secret{clientKeystore, clientTruststore, serverKeystore, serverTruststore} { - testClient.Create(ctx, secret) + require.NoError(t, testClient.Create(ctx, secret)) } serverEncryption := map[string]interface{}{ @@ -793,7 +794,11 @@ func testCreateStargateEncryptionExternalSecrets(t *testing.T, ctx context.Conte // Loop over the secrets and create them for _, secret := range []*corev1.Secret{clientKeystore, clientTruststore, serverKeystore, serverTruststore} { - testClient.Create(ctx, secret) + // This test and other encryption tests in this file are badly designed, they write the same secret names to the + // same namespace and conflict. + if err := testClient.Create(ctx, secret); err != nil && !errors.IsAlreadyExists(err) { + require.NoError(t, err) + } } serverEncryption := map[string]interface{}{ diff --git a/pkg/cassandra/datacenter.go b/pkg/cassandra/datacenter.go index bb196a978..7f375d38c 100644 --- a/pkg/cassandra/datacenter.go +++ b/pkg/cassandra/datacenter.go @@ -346,7 +346,6 @@ func Coalesce(clusterName string, clusterTemplate *api.CassandraClusterTemplate, dcConfig.ServerVersion = semver.MustParse(mergedOptions.ServerVersion) } dcConfig.ServerImage = mergedOptions.ServerImage - dcConfig.JmxInitContainerImage = mergedOptions.JmxInitContainerImage dcConfig.Racks = mergedOptions.Racks dcConfig.Resources = mergedOptions.Resources dcConfig.StorageConfig = mergedOptions.StorageConfig diff --git a/pkg/cassandra/datacenter_test.go b/pkg/cassandra/datacenter_test.go index 4473759b5..99f4b7fdb 100644 --- a/pkg/cassandra/datacenter_test.go +++ b/pkg/cassandra/datacenter_test.go @@ -5,7 +5,6 @@ import ( "github.com/k8ssandra/cass-operator/pkg/reconciliation" - "github.com/k8ssandra/k8ssandra-operator/pkg/images" "github.com/k8ssandra/k8ssandra-operator/pkg/meta" "github.com/k8ssandra/k8ssandra-operator/pkg/unstructured" "k8s.io/utils/pointer" @@ -421,28 +420,6 @@ func TestCoalesce(t *testing.T) { }, }, }, - { - name: "Override JMX init container", - clusterTemplate: &api.CassandraClusterTemplate{ - DatacenterOptions: api.DatacenterOptions{ - JmxInitContainerImage: &images.Image{Name: "cluster-image"}, - }, - }, - dcTemplate: &api.CassandraDatacenterTemplate{ - DatacenterOptions: api.DatacenterOptions{ - JmxInitContainerImage: &images.Image{Name: "dc-image"}, - }, - }, - want: &DatacenterConfig{ - JmxInitContainerImage: &images.Image{Name: "dc-image"}, - McacEnabled: true, - PodTemplateSpec: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{{Name: "cassandra"}}, - }, - }, - }, - }, { name: "Stopped flag", clusterTemplate: &api.CassandraClusterTemplate{}, diff --git a/pkg/clientcache/cache.go b/pkg/clientcache/cache.go index 3d5a3461e..a9242934b 100644 --- a/pkg/clientcache/cache.go +++ b/pkg/clientcache/cache.go @@ -105,7 +105,7 @@ func (c *ClientCache) CreateRemoteClientsFromSecret(secretKey types.NamespacedNa return err } - for ctx, _ := range apiConfig.Contexts { + for ctx := range apiConfig.Contexts { clientCmdCfg := clientcmd.NewNonInteractiveClientConfig(*apiConfig, ctx, &clientcmd.ConfigOverrides{}, nil) restConfig, err := clientCmdCfg.ClientConfig() if err != nil { diff --git a/pkg/medusa/grpc.go b/pkg/medusa/grpc.go index 317b6d020..3e301a3b1 100644 --- a/pkg/medusa/grpc.go +++ b/pkg/medusa/grpc.go @@ -6,6 +6,7 @@ import ( "time" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) type defaultClient struct { @@ -14,16 +15,20 @@ type defaultClient struct { } type ClientFactory interface { - NewClient(address string) (Client, error) + NewClient(ctx context.Context, address string) (Client, error) } type DefaultFactory struct { + cancelFunc context.CancelFunc } -func (f *DefaultFactory) NewClient(address string) (Client, error) { - conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithDefaultCallOptions(grpc.WaitForReady(false)), grpc.WithTimeout(5*time.Second)) +func (f *DefaultFactory) NewClient(ctx context.Context, address string) (Client, error) { + callCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + conn, err := grpc.DialContext(callCtx, address, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock(), grpc.WithDefaultCallOptions(grpc.WaitForReady(false))) + f.cancelFunc = cancel if err != nil { + defer cancel() return nil, fmt.Errorf("failed to create gRPC connection to %s: %s", address, err) } diff --git a/pkg/medusa/hostmap.go b/pkg/medusa/hostmap.go index 57278fa70..23b04af32 100644 --- a/pkg/medusa/hostmap.go +++ b/pkg/medusa/hostmap.go @@ -18,11 +18,6 @@ type HostMapping struct { } type HostMappingSlice []HostMapping -type mappable interface { - ToSourceTargetMap() map[string]string - ToTargetSourceMap() map[string]string -} - // Transform HostMappingSlice into a map with source IPs as keys and Target IPs as values. func (m HostMappingSlice) ToSourceTargetMap() map[string]string { out := make(map[string]string) @@ -189,7 +184,7 @@ func GetHostMap(cassDC *cassdcapi.CassandraDatacenter, k8sbackup medusaapi.Medus sortedSource := sortLocations(sourceRacks) sortedDests := sortLocations(destRacks) if len(sortedDests) != len(sortedSource) { - return nil, errors.New(fmt.Sprintf("number of racks in source != racks in destination. Source: %v, Dest: %v", sortedSource, sortedDests)) + return nil, fmt.Errorf("number of racks in source != racks in destination. Source: %v, Dest: %v", sortedSource, sortedDests) } out := HostMappingSlice{} for i, sourceRack := range sortedSource { diff --git a/pkg/medusa/hostmap_test.go b/pkg/medusa/hostmap_test.go index f27320ff3..f1576335c 100644 --- a/pkg/medusa/hostmap_test.go +++ b/pkg/medusa/hostmap_test.go @@ -231,6 +231,6 @@ func Test_HostMappingSlice_IsInPlace(t *testing.T) { s = HostMappingSlice{ {Source: "1", Target: ""}, } - res, err = s.IsInPlace() + _, err = s.IsInPlace() assert.Error(t, err, err) } diff --git a/pkg/medusa/reconcile.go b/pkg/medusa/reconcile.go index df7a94706..65ff37920 100644 --- a/pkg/medusa/reconcile.go +++ b/pkg/medusa/reconcile.go @@ -7,7 +7,6 @@ import ( "text/template" "github.com/adutra/goalesce" - "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" k8ss "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" api "github.com/k8ssandra/k8ssandra-operator/apis/medusa/v1alpha1" "github.com/k8ssandra/k8ssandra-operator/pkg/images" @@ -350,12 +349,6 @@ type medusaVolume struct { Exists bool } -type medusaAdditionalVolume struct { - Volume *v1beta1.AdditionalVolumes - VolumeIndex int - Exists bool -} - // Create or update volumes for medusa func GenerateMedusaVolumes(dcConfig *cassandra.DatacenterConfig, medusaSpec *api.MedusaClusterTemplate, k8cName string) []medusaVolume { var newVolumes []medusaVolume diff --git a/pkg/stargate/affinity.go b/pkg/stargate/affinity.go index 5cfa28f1e..bb454920e 100644 --- a/pkg/stargate/affinity.go +++ b/pkg/stargate/affinity.go @@ -9,10 +9,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// Deprecated label name used in cass-operator. -// See pkg/reconciliation/construct_statefulset.go -const zoneLabel = "failure-domain.beta.kubernetes.io/zone" - // computeNodeAffinityLabels computes a set of labels to select worker nodes for the Stargate pods. // We use the same labels that were used to select worker nodes for the data pods. This means that Stargate pods will // be scheduled on the same category of nodes that can host data pods. diff --git a/pkg/telemetry/cassandra_agent/cassandra_agent_config.go b/pkg/telemetry/cassandra_agent/cassandra_agent_config.go index b582895a3..963b88190 100644 --- a/pkg/telemetry/cassandra_agent/cassandra_agent_config.go +++ b/pkg/telemetry/cassandra_agent/cassandra_agent_config.go @@ -162,7 +162,9 @@ func (c Configurator) ReconcileTelemetryAgentConfig(dc *cassdcapi.CassandraDatac return recRes } - c.AddVolumeSource(dc) + if err := c.AddVolumeSource(dc); err != nil { + return result.Error(err) + } return result.Done() } diff --git a/pkg/test/mgmtapi.go b/pkg/test/mgmtapi.go index 3cbfdde71..01e03dbe6 100644 --- a/pkg/test/mgmtapi.go +++ b/pkg/test/mgmtapi.go @@ -3,6 +3,8 @@ package test import ( "context" "fmt" + "testing" + "github.com/go-logr/logr" cassdcapi "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" "github.com/k8ssandra/cass-operator/pkg/httphelper" @@ -11,7 +13,6 @@ import ( "github.com/k8ssandra/k8ssandra-operator/pkg/stargate" "github.com/stretchr/testify/mock" "sigs.k8s.io/controller-runtime/pkg/client" - "testing" ) type ManagementApiFactoryAdapter func( @@ -145,13 +146,3 @@ func (f *FakeManagementApiFacade) GetFirstCall(method ManagementApiMethod, args return -1 } - -func (f *FakeManagementApiFacade) getCallsForMethod(method ManagementApiMethod) []mock.Call { - calls := make([]mock.Call, 0) - for _, call := range f.Calls { - if call.Method == string(method) { - calls = append(calls, call) - } - } - return calls -} diff --git a/pkg/test/testenv.go b/pkg/test/testenv.go index ce0dbfb5e..8722b20d7 100644 --- a/pkg/test/testenv.go +++ b/pkg/test/testenv.go @@ -99,6 +99,9 @@ func (e *TestEnv) Start(ctx context.Context, t *testing.T, initReconcilers func( } e.TestClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + if err != nil { + return err + } clientCache := clientcache.New(e.TestClient, e.TestClient, scheme.Scheme) err = (&api.K8ssandraCluster{}).SetupWebhookWithManager(k8sManager, clientCache) @@ -294,9 +297,9 @@ func (e *MultiClusterTestEnv) GetDataPlaneEnvTests() []*envtest.Environment { type ControllerTest func(*testing.T, context.Context, *framework.Framework, string) func (e *MultiClusterTestEnv) ControllerTest(ctx context.Context, test ControllerTest) func(*testing.T) { - namespace := "ns-" + framework.CleanupForKubernetes(rand.String(9)) - return func(t *testing.T) { + namespace := "ns-" + framework.CleanupForKubernetes(rand.String(9)) + f := framework.NewFramework(e.Clients[e.controlPlane], e.controlPlane, e.dataPlanes, e.Clients) if err := f.CreateNamespace(namespace); err != nil { diff --git a/pkg/unstructured/unstructured_test.go b/pkg/unstructured/unstructured_test.go index 39ae38df1..2a7367c6c 100644 --- a/pkg/unstructured/unstructured_test.go +++ b/pkg/unstructured/unstructured_test.go @@ -2,8 +2,9 @@ package unstructured import ( "encoding/json" - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func TestUnstructured_MarshalJSON(t *testing.T) { @@ -200,9 +201,7 @@ func TestUnstructured_DeepCopyInto(t *testing.T) { out := new(Unstructured) // out not allowed to be nil tt.in.DeepCopyInto(out) assert.Equal(t, tt.in, out) - if out != nil { - assert.NotSame(t, tt.in, out) - } + assert.NotSame(t, tt.in, out) }) } } diff --git a/pkg/utils/map.go b/pkg/utils/map.go index 7200d2113..da2f99c58 100644 --- a/pkg/utils/map.go +++ b/pkg/utils/map.go @@ -7,10 +7,8 @@ import "fmt" func MergeMap(sources ...map[string]string) map[string]string { destination := make(map[string]string, 0) for _, source := range sources { - if source != nil { - for k, v := range source { - destination[k] = v - } + for k, v := range source { + destination[k] = v } } return destination @@ -24,26 +22,24 @@ func MergeMap(sources ...map[string]string) map[string]string { func MergeMapNested(allowOverwrite bool, sources ...map[string]interface{}) (map[string]interface{}, error) { destination := make(map[string]interface{}, 0) for _, source := range sources { - if source != nil { - for k, sourceVal := range source { - destVal, destValFound := destination[k] - if destValFound { - sourceMap, sourceValIsMap := sourceVal.(map[string]interface{}) - destMap, destValIsMap := destVal.(map[string]interface{}) - if sourceValIsMap && destValIsMap { - if merged, err := MergeMapNested(allowOverwrite, destMap, sourceMap); err != nil { - return nil, err - } else { - destination[k] = merged - } - } else if allowOverwrite || destVal == nil { - destination[k] = sourceVal + for k, sourceVal := range source { + destVal, destValFound := destination[k] + if destValFound { + sourceMap, sourceValIsMap := sourceVal.(map[string]interface{}) + destMap, destValIsMap := destVal.(map[string]interface{}) + if sourceValIsMap && destValIsMap { + if merged, err := MergeMapNested(allowOverwrite, destMap, sourceMap); err != nil { + return nil, err } else { - return nil, fmt.Errorf("key %v already exists", k) + destination[k] = merged } - } else { + } else if allowOverwrite || destVal == nil { destination[k] = sourceVal + } else { + return nil, fmt.Errorf("key %v already exists", k) } + } else { + destination[k] = sourceVal } } } diff --git a/test/e2e/dse_test.go b/test/e2e/dse_test.go index e1d083722..beade52ac 100644 --- a/test/e2e/dse_test.go +++ b/test/e2e/dse_test.go @@ -64,7 +64,7 @@ func createSingleDseDatacenterCluster(t *testing.T, ctx context.Context, namespa require.NoError(t, err, "failed to execute CQL query against DSE") assert.Contains(t, output, "modified", "expected server_id to be modified") - output, err = f.ExecuteCqlNoAuth(f.DataPlaneContexts[0], namespace, DcPrefix(t, f, dcKey)+"-default-sts-0", + _, err = f.ExecuteCqlNoAuth(f.DataPlaneContexts[0], namespace, DcPrefix(t, f, dcKey)+"-default-sts-0", "SELECT server_id FROM system.local") require.Error(t, err, "expected CQL query without auth to fail") } diff --git a/test/e2e/gc_test.go b/test/e2e/gc_test.go index 67cb37a30..85edf18c9 100644 --- a/test/e2e/gc_test.go +++ b/test/e2e/gc_test.go @@ -24,6 +24,7 @@ func gcTest(gcName string) e2eTestFunc { checkDatacenterReady(t, ctx, dc1Key, f) logs, err := f.GetContainerLogs(f.DataPlaneContexts[0], namespace, DcPrefix(t, f, dc1Key)+"-default-sts-0", "server-system-logger") + require.NoError(t, err) require.Containsf(t, logs, gcName, "Could not find %s in logs", gcName) switch gcName { diff --git a/test/e2e/stop_dc_test.go b/test/e2e/stop_dc_test.go index 484ff4167..dbbcdf9d8 100644 --- a/test/e2e/stop_dc_test.go +++ b/test/e2e/stop_dc_test.go @@ -52,6 +52,7 @@ func stopAndRestartDc(t *testing.T, ctx context.Context, namespace string, f *fr checkReaperReady(t, f, ctx, reaper2Key) username, password, err := f.RetrieveDatabaseCredentials(ctx, f.DataPlaneContexts[0], kcKey.Namespace, "cluster1") + require.NoError(t, err) t.Log("deploying Stargate and Reaper ingress routes in", f.DataPlaneContexts[1]) stargateRestHostAndPort := ingressConfigs[f.DataPlaneContexts[1]].StargateRest diff --git a/test/e2e/suite_test.go b/test/e2e/suite_test.go index 7101a548c..fd2f3a483 100644 --- a/test/e2e/suite_test.go +++ b/test/e2e/suite_test.go @@ -1009,32 +1009,6 @@ func createSingleDatacenterClusterWithEncryption(t *testing.T, ctx context.Conte testStargateApis(t, f, ctx, f.DataPlaneContexts[0], namespace, dcPrefix, username, password, true, replication) } -// createSingleDatacenterCluster creates a K8ssandraCluster with one CassandraDatacenter -// and one Reaper instance that are deployed in the local cluster with encryption on. -func createSingleDatacenterClusterReaperEncryption(t *testing.T, ctx context.Context, namespace string, f *framework.E2eFramework) { - require := require.New(t) - require.NoError(f.CreateCassandraEncryptionStoresSecret(namespace), "Failed to create the encryption secrets") - - t.Log("check that the K8ssandraCluster was created") - k8ssandra := &api.K8ssandraCluster{} - kcKey := types.NamespacedName{Namespace: namespace, Name: "test"} - err := f.Client.Get(ctx, kcKey, k8ssandra) - require.NoError(err, "failed to get K8ssandraCluster in namespace %s", namespace) - - dcKey := framework.ClusterKey{K8sContext: f.DataPlaneContexts[0], NamespacedName: types.NamespacedName{Namespace: namespace, Name: "dc1"}} - checkDatacenterReady(t, ctx, dcKey, f) - assertCassandraDatacenterK8cStatusReady(ctx, t, f, kcKey, dcKey.Name) - dcPrefix := DcPrefix(t, f, dcKey) - - reaperKey := framework.ClusterKey{K8sContext: f.DataPlaneContexts[0], NamespacedName: types.NamespacedName{Namespace: namespace, Name: dcPrefix + "-reaper"}} - checkReaperReady(t, f, ctx, reaperKey) - - checkReaperK8cStatusReady(t, f, ctx, kcKey, dcKey) - - t.Log("check Reaper keyspace created") - checkKeyspaceExists(t, f, ctx, f.DataPlaneContexts[0], namespace, k8ssandra.SanitizedName(), dcPrefix+"-default-sts-0", "reaper_db") -} - // createStargateAndDatacenter creates a CassandraDatacenter with 3 nodes, one per rack. It also creates 1 or 3 Stargate // nodes, one per rack, all deployed in the local cluster. Note that no K8ssandraCluster object is created. func createStargateAndDatacenter(t *testing.T, ctx context.Context, namespace string, f *framework.E2eFramework) { @@ -2174,22 +2148,6 @@ func checkInjectedVolumePresence(t *testing.T, ctx context.Context, f *framework return nil } -func checkVectorAgentPresence(t *testing.T, ctx context.Context, f *framework.E2eFramework, dcKey framework.ClusterKey) { - t.Logf("check that vector agent is present in %s cass pods in cluster %s", dcKey.Name, dcKey.K8sContext) - cassdc := &cassdcapi.CassandraDatacenter{} - err := f.Get(ctx, dcKey, cassdc) - require.NoError(t, err, "failed to get cassandra datacenter") - - vectorContainerIdx, containerFound := cassandra.FindContainer(cassdc.Spec.PodTemplateSpec, "vector-agent") - require.True(t, containerFound, "cannot find vector agent container in pod template spec") - clusterNameEnvVar := utils.FindEnvVarInContainer(&cassdc.Spec.PodTemplateSpec.Spec.Containers[vectorContainerIdx], "CLUSTER_NAME") - require.NotNil(t, clusterNameEnvVar, "cannot find CLUSTER_NAME env var in vector agent container") - dcNameEnvVar := utils.FindEnvVarInContainer(&cassdc.Spec.PodTemplateSpec.Spec.Containers[vectorContainerIdx], "DATACENTER_NAME") - require.NotNil(t, dcNameEnvVar, "cannot find DATACENTER_NAME env var in vector agent container") - rackNameEnvVar := utils.FindEnvVarInContainer(&cassdc.Spec.PodTemplateSpec.Spec.Containers[vectorContainerIdx], "RACK_NAME") - require.NotNil(t, rackNameEnvVar, "cannot find RACK_NAME env var in vector agent container") -} - func findContainerInPod(t *testing.T, pod corev1.Pod, containerName string) (index int, found bool) { for i, container := range pod.Spec.Containers { t.Logf("checking container %s in pod %s", container.Name, pod.Name) @@ -2231,13 +2189,6 @@ func checkVectorConfigMapDeleted(t *testing.T, ctx context.Context, f *framework } -func getPodTemplateSpecForCassandra(t *testing.T, ctx context.Context, f *framework.E2eFramework, dcKey framework.ClusterKey) *corev1.PodTemplateSpec { - cassdc := &cassdcapi.CassandraDatacenter{} - require.NoError(t, f.Get(ctx, dcKey, cassdc), "failed to get Cassandra Datacenter") - - return cassdc.Spec.PodTemplateSpec -} - func getPodTemplateSpecForDeployment(t *testing.T, ctx context.Context, f *framework.E2eFramework, deploymentKey framework.ClusterKey) *corev1.PodTemplateSpec { sg := &appsv1.Deployment{} require.NoError(t, f.Get(ctx, deploymentKey, sg), "failed to get Deployment") @@ -2272,10 +2223,7 @@ func checkVectorAgentConfigMapPresence(t *testing.T, ctx context.Context, f *fra require.Eventually(t, func() bool { cm := &corev1.ConfigMap{} err := f.Get(ctx, configMapKey, cm) - if err != nil { - return false - } - return true + return err == nil }, polling.k8ssandraClusterStatus.timeout, polling.k8ssandraClusterStatus.interval, "Vector configmap was not found") } diff --git a/test/framework/cqlsh.go b/test/framework/cqlsh.go index 81d2670c5..88f95d7db 100644 --- a/test/framework/cqlsh.go +++ b/test/framework/cqlsh.go @@ -10,8 +10,7 @@ import ( ) func (f *E2eFramework) RetrieveSuperuserSecret(ctx context.Context, k8sContext, namespace, clusterName string) (*corev1.Secret, error) { - var superUserSecret *corev1.Secret - superUserSecret = &corev1.Secret{} + superUserSecret := &corev1.Secret{} superUserSecretKey := ClusterKey{ NamespacedName: types.NamespacedName{ Namespace: namespace, diff --git a/test/framework/e2e_framework.go b/test/framework/e2e_framework.go index cd0310d7c..f1a8bba3e 100644 --- a/test/framework/e2e_framework.go +++ b/test/framework/e2e_framework.go @@ -52,8 +52,8 @@ type E2eFramework struct { } var ( - nodeToolStatusUN = regexp.MustCompile("UN\\s\\s") - nodeToolStatusDN = regexp.MustCompile("DN\\s\\s") + nodeToolStatusUN = regexp.MustCompile(`UN\s\s`) + nodeToolStatusDN = regexp.MustCompile(`DN\s\s`) ) func NewE2eFramework(t *testing.T, kubeconfigFile string, useDse bool, controlPlane string, dataPlanes ...string) (*E2eFramework, error) { @@ -589,7 +589,9 @@ func (f *E2eFramework) DumpClusterInfo(test string, namespaces ...string) error f.logger.Info("dump failed", "output", output, "error", err) errs = append(errs, fmt.Errorf("failed to dump %s for cluster %s: %w", "pods", ctx, err)) } - f.storeOutput(outputDir, namespace, "pods", "out", output) + if err := f.storeOutput(outputDir, namespace, "pods", "out", output); err != nil { + errs = append(errs, err) + } // Dump all objects that we need to investigate failures as a flat list and as yaml manifests for _, objectType := range []string{"K8ssandraCluster", "CassandraDatacenter", "Stargate", "Reaper", "StatefulSet", "Secrets", @@ -604,7 +606,9 @@ func (f *E2eFramework) DumpClusterInfo(test string, namespaces ...string) error f.logger.Info("dump failed", "output", output, "error", err) errs = append(errs, fmt.Errorf("failed to dump %s for cluster %s: %w", objectType, ctx, err)) } - f.storeOutput(outputDir, fmt.Sprintf("%s/objects/%s", namespace, objectType), objectType, "out", output) + if err := f.storeOutput(outputDir, fmt.Sprintf("%s/objects/%s", namespace, objectType), objectType, "out", output); err != nil { + errs = append(errs, err) + } // Get the yamls for each object outputYaml, err := kubectl.Get(kubectl.Options{Context: ctx, Namespace: namespace}, objectType, "-o", "yaml") @@ -612,7 +616,9 @@ func (f *E2eFramework) DumpClusterInfo(test string, namespaces ...string) error f.logger.Info("dump failed", "output", output, "error", err) errs = append(errs, fmt.Errorf("failed to dump %s for cluster %s: %w", objectType, ctx, err)) } - f.storeOutput(outputDir, fmt.Sprintf("%s/objects/%s", namespace, objectType), objectType, "yaml", outputYaml) + if err := f.storeOutput(outputDir, fmt.Sprintf("%s/objects/%s", namespace, objectType), objectType, "yaml", outputYaml); err != nil { + errs = append(errs, err) + } } } } @@ -631,8 +637,12 @@ func (f *E2eFramework) storeOutput(outputDir, subdirectory, objectType, ext, out return err } defer outputFile.Close() - outputFile.WriteString(output) - outputFile.Sync() + if _, err := outputFile.WriteString(output); err != nil { + return err + } + if err := outputFile.Sync(); err != nil { + return err + } return nil } diff --git a/test/framework/framework.go b/test/framework/framework.go index 3f5ade99a..a795727d3 100644 --- a/test/framework/framework.go +++ b/test/framework/framework.go @@ -132,8 +132,7 @@ func NewClusterKey(context, namespace, name string) ClusterKey { } func NewFramework(client client.Client, controlPlaneContext string, dataPlaneContexts []string, remoteClients map[string]client.Client) *Framework { - var log logr.Logger - log = logrusr.New(logrus.New()) + log := logrusr.New(logrus.New()) terratestlogger.Default = terratestlogger.New(&terratestLoggerBridge{logger: log}) return &Framework{ Client: client, @@ -462,7 +461,7 @@ func (f *Framework) PatchCassandraTaskStatus(ctx context.Context, key ClusterKey // remote clusters. func (f *Framework) WaitForDeploymentToBeReady(key ClusterKey, timeout, interval time.Duration) error { if len(key.K8sContext) == 0 { - for k8sContext, _ := range f.remoteClients { + for k8sContext := range f.remoteClients { opts := kubectl.Options{Namespace: key.Namespace, Context: k8sContext} err := wait.PollWithContext(context.Background(), interval, timeout, func(ctx context.Context) (bool, error) { if err := kubectl.RolloutStatus(ctx, opts, "Deployment", key.Name); err != nil { diff --git a/test/yq/yq_test.go b/test/yq/yq_test.go index 97ee95c90..9e6cbb0f6 100644 --- a/test/yq/yq_test.go +++ b/test/yq/yq_test.go @@ -1,11 +1,12 @@ package yq import ( - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "os" "strings" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestEval(t *testing.T) { @@ -51,7 +52,7 @@ func TestEval(t *testing.T) { "../testdata/fixtures/single-dc/k8ssandra.yaml", }, }, - want: "3", + want: "3\n3", }, { name: "empty line",