From 7703749223765b29acf2ef73d153d2cd757b0477 Mon Sep 17 00:00:00 2001 From: Michael Burman Date: Mon, 23 Oct 2023 14:50:30 +0300 Subject: [PATCH 1/2] Update to newer cass-operator version, modify the tasks APIs to include new operations as well as new Status spec --- Makefile | 2 +- apis/control/v1alpha1/k8ssandratask_types.go | 34 ++--- .../v1alpha1/k8ssandratask_types_test.go | 33 ++-- .../cluster-scoped/kustomization.yaml | 2 +- .../ns-scoped/kustomization.yaml | 2 +- .../control.k8ssandra.io_k8ssandratasks.yaml | 144 +++++++++++++++--- .../control/k8ssandratask_controller.go | 9 +- .../control/k8ssandratask_controller_test.go | 48 +++--- go.mod | 2 +- go.sum | 4 +- 10 files changed, 190 insertions(+), 90 deletions(-) diff --git a/Makefile b/Makefile index 1f2bb4a90..54550b5d4 100644 --- a/Makefile +++ b/Makefile @@ -325,7 +325,7 @@ GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint # TODO Add linting to the GHA also CERT_MANAGER_VERSION ?= v1.12.2 KUSTOMIZE_VERSION ?= v5.0.3 CONTROLLER_TOOLS_VERSION ?= v0.12.0 -GOLINT_VERSION ?= 1.54.2 +GOLINT_VERSION ?= 1.55.0 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 diff --git a/apis/control/v1alpha1/k8ssandratask_types.go b/apis/control/v1alpha1/k8ssandratask_types.go index fd35770b9..3a5cc2b04 100644 --- a/apis/control/v1alpha1/k8ssandratask_types.go +++ b/apis/control/v1alpha1/k8ssandratask_types.go @@ -118,13 +118,13 @@ func (t *K8ssandraTask) RefreshGlobalStatus(expectedDcCount int) { totalActive += dcStatus.Active totalSucceeded += dcStatus.Succeeded totalFailed += dcStatus.Failed - if getConditionStatus(dcStatus, cassapi.JobRunning) == corev1.ConditionTrue { + if getConditionStatus(dcStatus, cassapi.JobRunning) == metav1.ConditionTrue { anyRunning = true } - if getConditionStatus(dcStatus, cassapi.JobFailed) == corev1.ConditionTrue { + if getConditionStatus(dcStatus, cassapi.JobFailed) == metav1.ConditionTrue { anyFailed = true } - if getConditionStatus(dcStatus, cassapi.JobComplete) != corev1.ConditionTrue { + if getConditionStatus(dcStatus, cassapi.JobComplete) != metav1.ConditionTrue { allComplete = false } } @@ -137,15 +137,15 @@ func (t *K8ssandraTask) RefreshGlobalStatus(expectedDcCount int) { t.SetCondition(cassapi.JobFailed, toConditionStatus(anyFailed)) if allComplete && len(t.Status.Datacenters) == expectedDcCount { t.Status.CompletionTime = lastCompletionTime - t.SetCondition(cassapi.JobComplete, corev1.ConditionTrue) + t.SetCondition(cassapi.JobComplete, metav1.ConditionTrue) } } -func (t *K8ssandraTask) SetCondition(condition cassapi.JobConditionType, status corev1.ConditionStatus) bool { +func (t *K8ssandraTask) SetCondition(condition cassapi.JobConditionType, status metav1.ConditionStatus) bool { existing := false for i := 0; i < len(t.Status.Conditions); i++ { cond := t.Status.Conditions[i] - if cond.Type == condition { + if cond.Type == string(condition) { if cond.Status == status { // Already correct status return false @@ -159,8 +159,8 @@ func (t *K8ssandraTask) SetCondition(condition cassapi.JobConditionType, status } if !existing { - cond := cassapi.JobCondition{ - Type: condition, + cond := metav1.Condition{ + Type: string(condition), Status: status, LastTransitionTime: metav1.Now(), } @@ -170,22 +170,22 @@ func (t *K8ssandraTask) SetCondition(condition cassapi.JobConditionType, status return true } -func (t *K8ssandraTask) GetConditionStatus(conditionType cassapi.JobConditionType) corev1.ConditionStatus { +func (t *K8ssandraTask) GetConditionStatus(conditionType cassapi.JobConditionType) metav1.ConditionStatus { for _, condition := range t.Status.Conditions { - if condition.Type == conditionType { + if condition.Type == string(conditionType) { return condition.Status } } - return corev1.ConditionUnknown + return metav1.ConditionUnknown } -func getConditionStatus(s cassapi.CassandraTaskStatus, conditionType cassapi.JobConditionType) corev1.ConditionStatus { +func getConditionStatus(s cassapi.CassandraTaskStatus, conditionType cassapi.JobConditionType) metav1.ConditionStatus { for _, condition := range s.Conditions { - if condition.Type == conditionType { + if condition.Type == string(conditionType) { return condition.Status } } - return corev1.ConditionUnknown + return metav1.ConditionUnknown } func init() { @@ -193,9 +193,9 @@ func init() { } // toConditionStatus converts a primitive boolean into a k8s ConditionStatus -func toConditionStatus(condition bool) corev1.ConditionStatus { +func toConditionStatus(condition bool) metav1.ConditionStatus { if condition { - return corev1.ConditionTrue + return metav1.ConditionTrue } - return corev1.ConditionFalse + return metav1.ConditionFalse } diff --git a/apis/control/v1alpha1/k8ssandratask_types_test.go b/apis/control/v1alpha1/k8ssandratask_types_test.go index c12877d2e..38077a9b1 100644 --- a/apis/control/v1alpha1/k8ssandratask_types_test.go +++ b/apis/control/v1alpha1/k8ssandratask_types_test.go @@ -4,9 +4,8 @@ import ( "testing" "time" - "github.com/k8ssandra/cass-operator/apis/control/v1alpha1" + controlapi "github.com/k8ssandra/cass-operator/apis/control/v1alpha1" "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -15,7 +14,7 @@ func TestRefreshGlobalStatus(t *testing.T) { dcMap := generateDatacenters() kts := K8ssandraTaskStatus{ - CassandraTaskStatus: v1alpha1.CassandraTaskStatus{}, + CassandraTaskStatus: controlapi.CassandraTaskStatus{}, Datacenters: dcMap, } kt := K8ssandraTask{ @@ -26,14 +25,14 @@ func TestRefreshGlobalStatus(t *testing.T) { assert.Equal(t, 1, kt.Status.Failed) assert.Equal(t, 1, kt.Status.Succeeded) assert.Equal(t, 0, kt.Status.StartTime.Compare(time.Date(2023, 6, 10, 10, 10, 10, 10, time.UTC))) - assert.Equal(t, v1.ConditionTrue, kt.GetConditionStatus(v1alpha1.JobRunning)) - assert.Equal(t, v1.ConditionTrue, kt.GetConditionStatus(v1alpha1.JobFailed)) + assert.Equal(t, metav1.ConditionTrue, kt.GetConditionStatus(controlapi.JobRunning)) + assert.Equal(t, metav1.ConditionTrue, kt.GetConditionStatus(controlapi.JobFailed)) // the test data does not have a completion time, so it should be Unknown - assert.Equal(t, v1.ConditionUnknown, kt.GetConditionStatus(v1alpha1.JobComplete)) + assert.Equal(t, metav1.ConditionUnknown, kt.GetConditionStatus(controlapi.JobComplete)) } -func generateDatacenters() map[string]v1alpha1.CassandraTaskStatus { - return map[string]v1alpha1.CassandraTaskStatus{ +func generateDatacenters() map[string]controlapi.CassandraTaskStatus { + return map[string]controlapi.CassandraTaskStatus{ "dc1": { StartTime: &metav1.Time{ Time: time.Date(2023, 6, 13, 13, 13, 13, 13, time.UTC), @@ -44,10 +43,10 @@ func generateDatacenters() map[string]v1alpha1.CassandraTaskStatus { Active: 1, Succeeded: 1, Failed: 0, - Conditions: []v1alpha1.JobCondition{ + Conditions: []metav1.Condition{ { - Type: v1alpha1.JobComplete, - Status: v1.ConditionTrue, + Type: string(controlapi.JobComplete), + Status: metav1.ConditionTrue, }, }, }, @@ -61,10 +60,10 @@ func generateDatacenters() map[string]v1alpha1.CassandraTaskStatus { Active: 0, Succeeded: 0, Failed: 1, - Conditions: []v1alpha1.JobCondition{ + Conditions: []metav1.Condition{ { - Type: v1alpha1.JobFailed, - Status: v1.ConditionTrue, + Type: string(controlapi.JobFailed), + Status: metav1.ConditionTrue, }, }, }, @@ -76,10 +75,10 @@ func generateDatacenters() map[string]v1alpha1.CassandraTaskStatus { Active: 1, Succeeded: 0, Failed: 0, - Conditions: []v1alpha1.JobCondition{ + Conditions: []metav1.Condition{ { - Type: v1alpha1.JobRunning, - Status: v1.ConditionTrue, + Type: string(controlapi.JobRunning), + Status: metav1.ConditionTrue, }, }, }, diff --git a/config/cass-operator/cluster-scoped/kustomization.yaml b/config/cass-operator/cluster-scoped/kustomization.yaml index e1be4ca2d..d7512140f 100644 --- a/config/cass-operator/cluster-scoped/kustomization.yaml +++ b/config/cass-operator/cluster-scoped/kustomization.yaml @@ -11,4 +11,4 @@ components: # This is required when a new feature of cass-operator is needed that is not yet released. images: - name: k8ssandra/cass-operator - newTag: v1.18.0-dev.34e2ae6-20231002 \ No newline at end of file + newTag: v1.18.0-dev.5189beb-20231020 \ No newline at end of file diff --git a/config/cass-operator/ns-scoped/kustomization.yaml b/config/cass-operator/ns-scoped/kustomization.yaml index 137baddbc..98ee42f82 100644 --- a/config/cass-operator/ns-scoped/kustomization.yaml +++ b/config/cass-operator/ns-scoped/kustomization.yaml @@ -11,4 +11,4 @@ components: # This is required when a new feature of cass-operator is needed that is not yet released. images: - name: k8ssandra/cass-operator - newTag: v1.18.0-dev.34e2ae6-20231002 \ No newline at end of file + newTag: v1.18.0-dev.5189beb-20231020 \ No newline at end of file diff --git a/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml b/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml index f934b7866..7068d092c 100644 --- a/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml +++ b/config/crd/bases/control.k8ssandra.io_k8ssandratasks.yaml @@ -126,6 +126,10 @@ spec: description: Arguments are additional parameters for the command properties: + end_token: + type: string + jobs: + type: integer keyspace_name: type: string new_tokens: @@ -137,12 +141,28 @@ spec: exist; any existing pod not referenced in this map will not be moved. type: object + no_snapshot: + type: boolean + no_validate: + description: Scrub arguments + type: boolean pod_name: type: string rack: type: string + skip_corrupted: + type: boolean source_datacenter: type: string + split_output: + description: Compaction arguments + type: boolean + start_token: + type: string + tables: + items: + type: string + type: array type: object command: description: Command defines what is run against Cassandra @@ -197,30 +217,68 @@ spec: one of the conditions will have type "Complete" and status true. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/' items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" properties: - lastProbeTime: - description: Last time the condition was checked. - format: date-time - type: string lastTransitionTime: - description: Last time the condition transit from one status - to another. + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. format: date-time type: string message: - description: Human readable message indicating details about - last transition. + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer reason: - description: (brief) reason for the condition's last transition. + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: Status of the condition, one of True, False, Unknown. + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown type: string type: - description: Type of job condition, Complete or Failed. + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: + - lastTransitionTime + - message + - reason - status - type type: object @@ -250,31 +308,73 @@ spec: will become false. When a Job is completed, one of the conditions will have type "Complete" and status true. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/' items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" properties: - lastProbeTime: - description: Last time the condition was checked. - format: date-time - type: string lastTransitionTime: - description: Last time the condition transit from one - status to another. + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. format: date-time type: string message: - description: Human readable message indicating details - about last transition. + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer reason: - description: (brief) reason for the condition's last transition. + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: - description: Status of the condition, one of True, False, + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown type: string type: - description: Type of job condition, Complete or Failed. + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: + - lastTransitionTime + - message + - reason - status - type type: object diff --git a/controllers/control/k8ssandratask_controller.go b/controllers/control/k8ssandratask_controller.go index e04553a2b..9edd0449b 100644 --- a/controllers/control/k8ssandratask_controller.go +++ b/controllers/control/k8ssandratask_controller.go @@ -19,6 +19,9 @@ package control import ( "context" "fmt" + "strings" + "time" + "github.com/go-logr/logr" cassapi "github.com/k8ssandra/cass-operator/apis/control/v1alpha1" k8capi "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" @@ -40,8 +43,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" - "strings" - "time" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" @@ -218,7 +219,7 @@ func (r *K8ssandraTaskReconciler) deleteCassandraTasks( // If the K8ssandraCluster was deleted, the CassandraDatacenters and CassandraTasks will be deleted automatically. // If the spec was invalid, we didn't create the CassandraTasks in the first place. if !kcExists || - kTask.GetConditionStatus(api.JobInvalid) == corev1.ConditionTrue { + kTask.GetConditionStatus(api.JobInvalid) == metav1.ConditionTrue { return nil } @@ -344,7 +345,7 @@ func (r *K8ssandraTaskReconciler) reportInvalidSpec( r.Recorder.Event(kTask, "Warning", "InvalidSpec", fmt.Sprintf(format, arguments...)) patch := client.MergeFrom(kTask.DeepCopy()) - kTask.SetCondition(api.JobInvalid, corev1.ConditionTrue) + kTask.SetCondition(api.JobInvalid, metav1.ConditionTrue) err := r.Status().Patch(ctx, kTask, patch) return ctrl.Result{}, err } diff --git a/controllers/control/k8ssandratask_controller_test.go b/controllers/control/k8ssandratask_controller_test.go index cccd46aec..6c35e812d 100644 --- a/controllers/control/k8ssandratask_controller_test.go +++ b/controllers/control/k8ssandratask_controller_test.go @@ -119,14 +119,14 @@ func executeParallelK8ssandraTask(t *testing.T, ctx context.Context, f *framewor require.NoError(f.PatchCassandraTaskStatus(ctx, cassTask1Key, func(cassTask1 *cassapi.CassandraTask) { cassTask1.Status.Active = 1 cassTask1.Status.StartTime = &startTime1 - SetCondition(cassTask1, cassapi.JobRunning, corev1.ConditionTrue) + SetCondition(cassTask1, cassapi.JobRunning, metav1.ConditionTrue) })) cassTask2Key := newClusterKey(f.DataPlaneContexts[1], namespace, "upgradesstables-dc2") require.NoError(f.PatchCassandraTaskStatus(ctx, cassTask2Key, func(cassTask2 *cassapi.CassandraTask) { cassTask2.Status.Active = 1 cassTask2.Status.StartTime = &startTime2 - SetCondition(cassTask2, cassapi.JobRunning, corev1.ConditionTrue) + SetCondition(cassTask2, cassapi.JobRunning, metav1.ConditionTrue) })) t.Log("Check that the K8ssandraTask is marked as Running") @@ -135,7 +135,7 @@ func executeParallelK8ssandraTask(t *testing.T, ctx context.Context, f *framewor require.NoError(f.Get(ctx, newClusterKey(f.ControlPlaneContext, namespace, "upgradesstables"), k8Task)) return k8Task.Status.Active == 2 && k8Task.Status.StartTime.Equal(&startTime1) && - k8Task.GetConditionStatus(cassapi.JobRunning) == corev1.ConditionTrue + k8Task.GetConditionStatus(cassapi.JobRunning) == metav1.ConditionTrue }, timeout, interval) t.Log("Mark the CassandraTasks as Complete") @@ -145,15 +145,15 @@ func executeParallelK8ssandraTask(t *testing.T, ctx context.Context, f *framewor cassTask1.Status.Active = 0 cassTask1.Status.Succeeded = 1 cassTask1.Status.CompletionTime = &completionTime1 - SetCondition(cassTask1, cassapi.JobRunning, corev1.ConditionFalse) - SetCondition(cassTask1, cassapi.JobComplete, corev1.ConditionTrue) + SetCondition(cassTask1, cassapi.JobRunning, metav1.ConditionFalse) + SetCondition(cassTask1, cassapi.JobComplete, metav1.ConditionTrue) })) require.NoError(f.PatchCassandraTaskStatus(ctx, cassTask2Key, func(cassTask2 *cassapi.CassandraTask) { cassTask2.Status.Active = 0 cassTask2.Status.Succeeded = 1 cassTask2.Status.CompletionTime = &completionTime2 - SetCondition(cassTask2, cassapi.JobRunning, corev1.ConditionFalse) - SetCondition(cassTask2, cassapi.JobComplete, corev1.ConditionTrue) + SetCondition(cassTask2, cassapi.JobRunning, metav1.ConditionFalse) + SetCondition(cassTask2, cassapi.JobComplete, metav1.ConditionTrue) })) t.Log("Check that the K8ssandraTask is marked as Complete") @@ -163,8 +163,8 @@ func executeParallelK8ssandraTask(t *testing.T, ctx context.Context, f *framewor return k8Task.Status.Active == 0 && k8Task.Status.Succeeded == 2 && k8Task.Status.CompletionTime.Equal(&completionTime2) && - k8Task.GetConditionStatus(cassapi.JobRunning) == corev1.ConditionFalse && - k8Task.GetConditionStatus(cassapi.JobComplete) == corev1.ConditionTrue + k8Task.GetConditionStatus(cassapi.JobRunning) == metav1.ConditionFalse && + k8Task.GetConditionStatus(cassapi.JobComplete) == metav1.ConditionTrue }, timeout, interval) } @@ -214,7 +214,7 @@ func executeSequentialK8ssandraTask(t *testing.T, ctx context.Context, f *framew require.NoError(f.PatchCassandraTaskStatus(ctx, cassTask1Key, func(cassTask1 *cassapi.CassandraTask) { cassTask1.Status.Active = 1 cassTask1.Status.StartTime = &startTime1 - SetCondition(cassTask1, cassapi.JobRunning, corev1.ConditionTrue) + SetCondition(cassTask1, cassapi.JobRunning, metav1.ConditionTrue) })) t.Log("Check that the K8ssandraTask is marked as Running") @@ -223,7 +223,7 @@ func executeSequentialK8ssandraTask(t *testing.T, ctx context.Context, f *framew require.NoError(f.Get(ctx, newClusterKey(f.ControlPlaneContext, namespace, "upgradesstables"), k8Task)) return k8Task.Status.Active == 1 && k8Task.Status.StartTime.Equal(&startTime1) && - k8Task.GetConditionStatus(cassapi.JobRunning) == corev1.ConditionTrue + k8Task.GetConditionStatus(cassapi.JobRunning) == metav1.ConditionTrue }, timeout, interval) t.Log("Check that CassandraTask 2 still hasn't been created") @@ -235,8 +235,8 @@ func executeSequentialK8ssandraTask(t *testing.T, ctx context.Context, f *framew cassTask1.Status.Active = 0 cassTask1.Status.Succeeded = 1 cassTask1.Status.CompletionTime = &completionTime1 - SetCondition(cassTask1, cassapi.JobRunning, corev1.ConditionFalse) - SetCondition(cassTask1, cassapi.JobComplete, corev1.ConditionTrue) + SetCondition(cassTask1, cassapi.JobRunning, metav1.ConditionFalse) + SetCondition(cassTask1, cassapi.JobComplete, metav1.ConditionTrue) })) t.Log("Check that CassandraTask 2 has been created") @@ -249,7 +249,7 @@ func executeSequentialK8ssandraTask(t *testing.T, ctx context.Context, f *framew require.NoError(f.PatchCassandraTaskStatus(ctx, cassTask2Key, func(cassTask2 *cassapi.CassandraTask) { cassTask2.Status.Active = 1 cassTask2.Status.StartTime = &startTime2 - SetCondition(cassTask2, cassapi.JobRunning, corev1.ConditionTrue) + SetCondition(cassTask2, cassapi.JobRunning, metav1.ConditionTrue) })) t.Log("Mark CassandraTask 2 as Complete") @@ -258,8 +258,8 @@ func executeSequentialK8ssandraTask(t *testing.T, ctx context.Context, f *framew cassTask2.Status.Active = 0 cassTask2.Status.Succeeded = 1 cassTask2.Status.CompletionTime = &completionTime2 - SetCondition(cassTask2, cassapi.JobRunning, corev1.ConditionFalse) - SetCondition(cassTask2, cassapi.JobComplete, corev1.ConditionTrue) + SetCondition(cassTask2, cassapi.JobRunning, metav1.ConditionFalse) + SetCondition(cassTask2, cassapi.JobComplete, metav1.ConditionTrue) })) t.Log("Check that the K8ssandraTask is marked as Complete") @@ -269,8 +269,8 @@ func executeSequentialK8ssandraTask(t *testing.T, ctx context.Context, f *framew return k8Task.Status.Active == 0 && k8Task.Status.Succeeded == 2 && k8Task.Status.CompletionTime.Equal(&completionTime2) && - k8Task.GetConditionStatus(cassapi.JobRunning) == corev1.ConditionFalse && - k8Task.GetConditionStatus(cassapi.JobComplete) == corev1.ConditionTrue + k8Task.GetConditionStatus(cassapi.JobRunning) == metav1.ConditionFalse && + k8Task.GetConditionStatus(cassapi.JobComplete) == metav1.ConditionTrue }, timeout, interval) } @@ -363,12 +363,12 @@ func expireK8ssandraTask(t *testing.T, ctx context.Context, f *framework.Framewo require.NoError(f.PatchCassandraTaskStatus(ctx, cassTask1Key, func(cassTask1 *cassapi.CassandraTask) { cassTask1.Status.Succeeded = 1 cassTask1.Status.CompletionTime = &completionTime1 - SetCondition(cassTask1, cassapi.JobComplete, corev1.ConditionTrue) + SetCondition(cassTask1, cassapi.JobComplete, metav1.ConditionTrue) })) require.NoError(f.PatchCassandraTaskStatus(ctx, cassTask2Key, func(cassTask2 *cassapi.CassandraTask) { cassTask2.Status.Succeeded = 1 cassTask2.Status.CompletionTime = &completionTime2 - SetCondition(cassTask2, cassapi.JobComplete, corev1.ConditionTrue) + SetCondition(cassTask2, cassapi.JobComplete, metav1.ConditionTrue) })) t.Log("Check that everything gets deleted") @@ -425,11 +425,11 @@ func loadCassandraTask(k8sContext, namespace, cassTaskName string, ctx context.C return cassTask } -func SetCondition(task *cassapi.CassandraTask, condition cassapi.JobConditionType, status corev1.ConditionStatus) bool { +func SetCondition(task *cassapi.CassandraTask, condition cassapi.JobConditionType, status metav1.ConditionStatus) bool { existing := false for i := 0; i < len(task.Status.Conditions); i++ { cond := task.Status.Conditions[i] - if cond.Type == condition { + if cond.Type == string(condition) { if cond.Status == status { // Already correct status return false @@ -443,8 +443,8 @@ func SetCondition(task *cassapi.CassandraTask, condition cassapi.JobConditionTyp } if !existing { - cond := cassapi.JobCondition{ - Type: condition, + cond := metav1.Condition{ + Type: string(condition), Status: status, LastTransitionTime: metav1.Now(), } diff --git a/go.mod b/go.mod index c73c9ed3c..d2b4cbc2b 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/go-logr/zapr v1.2.3 github.com/google/uuid v1.3.0 github.com/gruntwork-io/terratest v0.37.7 - github.com/k8ssandra/cass-operator v1.17.2 + github.com/k8ssandra/cass-operator v1.17.3-0.20231020160518-5189bebc9531 github.com/k8ssandra/reaper-client-go v0.3.1-0.20220114183114-6923e077c4f5 github.com/pkg/errors v0.9.1 github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.52.1 diff --git a/go.sum b/go.sum index 91fa41c93..89d83009e 100644 --- a/go.sum +++ b/go.sum @@ -653,8 +653,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k8ssandra/cass-operator v1.17.2 h1:e9cmvgpSW2R3wFd525SjIznp9kuJwkeMpYIwAD+eR+Y= -github.com/k8ssandra/cass-operator v1.17.2/go.mod h1:8gYoASfrQYiDmvfMAeYSe31dO1qVe8uIISJeVXGFSiI= +github.com/k8ssandra/cass-operator v1.17.3-0.20231020160518-5189bebc9531 h1:plGB8EBK8jEpbphiCkmNJNktjZwrTRlA2WzBTxEY9pU= +github.com/k8ssandra/cass-operator v1.17.3-0.20231020160518-5189bebc9531/go.mod h1:8gYoASfrQYiDmvfMAeYSe31dO1qVe8uIISJeVXGFSiI= github.com/k8ssandra/reaper-client-go v0.3.1-0.20220114183114-6923e077c4f5 h1:Dq0VdM960G3AbhYwFuaebmsE08IzOYHYhngUfDmWaAc= github.com/k8ssandra/reaper-client-go v0.3.1-0.20220114183114-6923e077c4f5/go.mod h1:WsQymIaVT39xbcstZhdqynUS13AGzP2p6U9Hsk1oy5M= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= From 930dc74552ef9c1da98e5e762712045844c9c14a Mon Sep 17 00:00:00 2001 From: Michael Burman Date: Tue, 24 Oct 2023 13:22:07 +0300 Subject: [PATCH 2/2] Fix K8ssandraTask Status part to conform with CassandraTask one --- apis/control/v1alpha1/k8ssandratask_types.go | 1 + controllers/control/k8ssandratask_controller_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/apis/control/v1alpha1/k8ssandratask_types.go b/apis/control/v1alpha1/k8ssandratask_types.go index 3a5cc2b04..ded8eff98 100644 --- a/apis/control/v1alpha1/k8ssandratask_types.go +++ b/apis/control/v1alpha1/k8ssandratask_types.go @@ -161,6 +161,7 @@ func (t *K8ssandraTask) SetCondition(condition cassapi.JobConditionType, status if !existing { cond := metav1.Condition{ Type: string(condition), + Reason: string(condition), Status: status, LastTransitionTime: metav1.Now(), } diff --git a/controllers/control/k8ssandratask_controller_test.go b/controllers/control/k8ssandratask_controller_test.go index 6c35e812d..d0b4f0d5c 100644 --- a/controllers/control/k8ssandratask_controller_test.go +++ b/controllers/control/k8ssandratask_controller_test.go @@ -445,6 +445,7 @@ func SetCondition(task *cassapi.CassandraTask, condition cassapi.JobConditionTyp if !existing { cond := metav1.Condition{ Type: string(condition), + Reason: string(condition), Status: status, LastTransitionTime: metav1.Now(), }