diff --git a/pkg/controller/autoops/reconcile.go b/pkg/controller/autoops/reconcile.go index 5991704c515..93403fb4003 100644 --- a/pkg/controller/autoops/reconcile.go +++ b/pkg/controller/autoops/reconcile.go @@ -23,6 +23,7 @@ import ( "github.com/elastic/cloud-on-k8s/v3/pkg/controller/association" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/deployment" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/version" "github.com/elastic/cloud-on-k8s/v3/pkg/utils/k8s" ulog "github.com/elastic/cloud-on-k8s/v3/pkg/utils/log" ) @@ -134,8 +135,23 @@ func (r *AgentPolicyReconciler) internalReconcile( for _, es := range accessibleClusters { log := log.WithValues("es_namespace", es.Namespace, "es_name", es.Name) + esVersion, err := version.Parse(es.Spec.Version) + if err != nil { + log.Error(err, "while parsing ES version") + state.UpdateWithPhase(autoopsv1alpha1.ErrorPhase) + return results.WithError(err) + } + + // No error means the version is within the deprecated range, so we skip the cluster. + // We do not adjust the status to indicate this issue at this time, as the status object + // does not currently support a status per-cluster. + if version.DeprecatedVersions.WithinRange(esVersion) == nil { + log.Info("Skipping ES cluster because of deprecated version", "version", es.Spec.Version) + continue + } + if es.Status.Phase != esv1.ElasticsearchReadyPhase { - log.V(1).Info("Skipping ES cluster that is not ready", "es_namespace", es.Namespace, "es_name", es.Name) + log.V(1).Info("Skipping ES cluster that is not ready") state.UpdateWithPhase(autoopsv1alpha1.ResourcesNotReadyPhase) results = results.WithRequeue(reconciler.DefaultRequeue) continue @@ -143,7 +159,7 @@ func (r *AgentPolicyReconciler) internalReconcile( if es.Spec.HTTP.TLS.Enabled() { if err := r.reconcileAutoOpsESCASecret(ctx, policy, es); err != nil { - log.Error(err, "while reconciling AutoOps ES CA secret", "es_namespace", es.Namespace, "es_name", es.Name) + log.Error(err, "while reconciling AutoOps ES CA secret") errorCount++ state.UpdateWithPhase(autoopsv1alpha1.ErrorPhase) results.WithError(err) @@ -153,7 +169,7 @@ func (r *AgentPolicyReconciler) internalReconcile( apiKeySecret, err := r.reconcileAutoOpsESAPIKey(ctx, policy, es) if err != nil { - log.Error(err, "while reconciling AutoOps ES API key", "es_namespace", es.Namespace, "es_name", es.Name) + log.Error(err, "while reconciling AutoOps ES API key") errorCount++ state.UpdateWithPhase(autoopsv1alpha1.ErrorPhase) results.WithError(err) @@ -162,7 +178,7 @@ func (r *AgentPolicyReconciler) internalReconcile( configMap, err := ReconcileAutoOpsESConfigMap(ctx, r.Client, policy, es) if err != nil { - log.Error(err, "while reconciling AutoOps ES config map", "es_namespace", es.Namespace, "es_name", es.Name) + log.Error(err, "while reconciling AutoOps ES config map") errorCount++ state.UpdateWithPhase(autoopsv1alpha1.ErrorPhase) results.WithError(err) @@ -171,7 +187,7 @@ func (r *AgentPolicyReconciler) internalReconcile( configHash, err := buildConfigHash(ctx, *configMap, *apiKeySecret, r.Client, policy) if err != nil { - log.Error(err, "while building config hash", "es_namespace", es.Namespace, "es_name", es.Name) + log.Error(err, "while building config hash") errorCount++ state.UpdateWithPhase(autoopsv1alpha1.ErrorPhase) results.WithError(err) @@ -180,7 +196,7 @@ func (r *AgentPolicyReconciler) internalReconcile( deploymentParams, err := r.buildDeployment(configHash, policy, es) if err != nil { - log.Error(err, "while getting deployment params", "es_namespace", es.Namespace, "es_name", es.Name) + log.Error(err, "while getting deployment params") errorCount++ state.UpdateWithPhase(autoopsv1alpha1.ErrorPhase) results.WithError(err) @@ -189,7 +205,7 @@ func (r *AgentPolicyReconciler) internalReconcile( reconciledDeployment, err := deployment.Reconcile(ctx, r.Client, deploymentParams, &policy) if err != nil { - log.Error(err, "while reconciling deployment", "es_namespace", es.Namespace, "es_name", es.Name) + log.Error(err, "while reconciling deployment") errorCount++ state.UpdateWithPhase(autoopsv1alpha1.ErrorPhase) results.WithError(err) diff --git a/pkg/controller/autoops/reconcile_test.go b/pkg/controller/autoops/reconcile_test.go index b5d1ce486b6..626a935a087 100644 --- a/pkg/controller/autoops/reconcile_test.go +++ b/pkg/controller/autoops/reconcile_test.go @@ -214,6 +214,9 @@ func TestAutoOpsAgentPolicyReconciler_internalReconcile(t *testing.T) { Status: esv1.ElasticsearchStatus{ Phase: esv1.ElasticsearchApplyingChangesPhase, }, + Spec: esv1.ElasticsearchSpec{ + Version: "9.1.0", + }, }, }, wantStatus: autoopsv1alpha1.AutoOpsAgentPolicyStatus{ @@ -335,6 +338,9 @@ func TestAutoOpsAgentPolicyReconciler_internalReconcile(t *testing.T) { Namespace: "ns-1", Labels: map[string]string{"app": "elasticsearch"}, }, + Spec: esv1.ElasticsearchSpec{ + Version: "9.1.0", + }, Status: esv1.ElasticsearchStatus{ Phase: esv1.ElasticsearchApplyingChangesPhase, }, @@ -548,6 +554,64 @@ func TestAutoOpsAgentPolicyReconciler_internalReconcile(t *testing.T) { }, wantResults: reconcile.Result{}, }, + { + name: "deprecated ES version is ignored", + policy: autoopsv1alpha1.AutoOpsAgentPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "policy-1", + Namespace: "ns-1", + }, + Spec: autoopsv1alpha1.AutoOpsAgentPolicySpec{ + Version: "9.2.1", + AutoOpsRef: autoopsv1alpha1.AutoOpsRef{ + SecretName: "config-secret", + }, + ResourceSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "elasticsearch"}, + }, + }, + }, + initialObjects: []client.Object{ + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "config-secret", + Namespace: "ns-1", + }, + Data: map[string][]byte{ + "cloud-connected-mode-api-key": []byte("test-key"), + "autoops-otel-url": []byte("https://test-url"), + "autoops-token": []byte("test-token"), + }, + }, + &esv1.Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Name: "es-deprecated", + Namespace: "ns-1", + Labels: map[string]string{"app": "elasticsearch"}, + }, + Spec: esv1.ElasticsearchSpec{ + Version: "7.15.0", + HTTP: commonv1.HTTPConfig{ + TLS: commonv1.TLSOptions{ + SelfSignedCertificate: &commonv1.SelfSignedCertificate{ + Disabled: true, + }, + }, + }, + }, + Status: esv1.ElasticsearchStatus{ + Phase: esv1.ElasticsearchReadyPhase, + }, + }, + }, + wantStatus: autoopsv1alpha1.AutoOpsAgentPolicyStatus{ + Resources: 1, + Ready: 0, + Errors: 0, + Phase: "", + }, + wantResults: reconcile.Result{}, + }, } for _, tt := range tests { @@ -577,7 +641,7 @@ func TestAutoOpsAgentPolicyReconciler_internalReconcile(t *testing.T) { gotResult, gotErr := gotResults.Aggregate() expectError := tt.wantStatus.Phase == autoopsv1alpha1.ErrorPhase || tt.wantStatus.Phase == autoopsv1alpha1.InvalidPhase - require.Equal(t, expectError, gotErr != nil) + require.Equal(t, expectError, gotErr != nil, "expected error: %v, got error: %v", expectError, gotErr) if !cmp.Equal(tt.wantStatus, state.status, cmpopts.IgnoreFields(autoopsv1alpha1.AutoOpsAgentPolicyStatus{}, "ObservedGeneration")) { t.Errorf("status mismatch:\n%s", cmp.Diff(tt.wantStatus, state.status, cmpopts.IgnoreFields(autoopsv1alpha1.AutoOpsAgentPolicyStatus{}, "ObservedGeneration")))