|
| 1 | +// Copyright (c) HashiCorp, Inc. |
| 2 | +// SPDX-License-Identifier: MPL-2.0 |
| 3 | + |
| 4 | +package controller |
| 5 | + |
| 6 | +import ( |
| 7 | + "context" |
| 8 | + "fmt" |
| 9 | + "time" |
| 10 | + |
| 11 | + tfc "github.com/hashicorp/go-tfe" |
| 12 | + corev1 "k8s.io/api/core/v1" |
| 13 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 14 | + |
| 15 | + appv1alpha2 "github.com/hashicorp/hcp-terraform-operator/api/v1alpha2" |
| 16 | +) |
| 17 | + |
| 18 | +func (r *AgentPoolReconciler) deleteAgentPool(ctx context.Context, ap *agentPoolInstance) error { |
| 19 | + ap.log.Info("Reconcile Agent Pool", "msg", fmt.Sprintf("deletion policy is %s", ap.instance.Spec.DeletionPolicy)) |
| 20 | + |
| 21 | + if ap.instance.Status.AgentPoolID == "" { |
| 22 | + ap.log.Info("Reconcile Agent Pool", "msg", fmt.Sprintf("status.agentPoolID is empty, remove finalizer %s", agentPoolFinalizer)) |
| 23 | + return r.removeFinalizer(ctx, ap) |
| 24 | + } |
| 25 | + |
| 26 | + switch ap.instance.Spec.DeletionPolicy { |
| 27 | + case appv1alpha2.AgentPoolDeletionPolicyRetain: |
| 28 | + ap.log.Info("Reconcile Agent Pool", "msg", fmt.Sprintf("remove finalizer %s", agentPoolFinalizer)) |
| 29 | + return r.removeFinalizer(ctx, ap) |
| 30 | + case appv1alpha2.AgentPoolDeletionPolicy(appv1alpha2.DeletionPolicyDestroy): |
| 31 | + // Attempt to delete the agent pool first. If successful, no other actions are required. |
| 32 | + // Otherwise, scale down the agents to 0 and delete all tokens. |
| 33 | + err := ap.tfClient.Client.AgentPools.Delete(ctx, ap.instance.Status.AgentPoolID) |
| 34 | + if err != nil { |
| 35 | + // If agent pool wasn't found, it means it was deleted from the HCP Terraform bypass the operator. |
| 36 | + // In this case, remove the finalizer and let Kubernetes remove the object permanently |
| 37 | + if err == tfc.ErrResourceNotFound { |
| 38 | + ap.log.Info("Reconcile Agent Pool", "msg", fmt.Sprintf("agent pool ID %s not found, remove finalizer", agentPoolFinalizer)) |
| 39 | + return r.removeFinalizer(ctx, ap) |
| 40 | + } |
| 41 | + ap.log.Error(err, "Reconcile Agent Pool", "msg", fmt.Sprintf("failed to delete Agent Pool ID %s, retry later", agentPoolFinalizer)) |
| 42 | + r.Recorder.Eventf(&ap.instance, corev1.EventTypeWarning, "ReconcileAgentPool", "Failed to delete Agent Pool ID %s, retry later", ap.instance.Status.AgentPoolID) |
| 43 | + // Do not return the error here; proceed further to cale down the agents to 0 and delete all tokens. |
| 44 | + } else { |
| 45 | + ap.log.Info("Reconcile Agent Pool", "msg", fmt.Sprintf("agent pool ID %s has been deleted, remove finalizer", ap.instance.Status.AgentPoolID)) |
| 46 | + return r.removeFinalizer(ctx, ap) |
| 47 | + } |
| 48 | + // Downscale agents |
| 49 | + if ap.instance.Status.AgentDeploymentAutoscalingStatus != nil && ap.instance.Status.AgentDeploymentAutoscalingStatus.DesiredReplicas != nil { |
| 50 | + if *ap.instance.Status.AgentDeploymentAutoscalingStatus.DesiredReplicas > 0 { |
| 51 | + ap.log.Info("Reconcile Agent Pool", "msg", fmt.Sprintf("scale agents from %d to 0", *ap.instance.Status.AgentDeploymentAutoscalingStatus.DesiredReplicas)) |
| 52 | + var n int32 = 0 |
| 53 | + if err := r.scaleAgentDeployment(ctx, ap, &n); err != nil { |
| 54 | + ap.log.Error(err, "Reconcile Agent Pool", "msg", "failed to scale agents") |
| 55 | + return err |
| 56 | + } |
| 57 | + ap.instance.Status.AgentDeploymentAutoscalingStatus = &appv1alpha2.AgentDeploymentAutoscalingStatus{ |
| 58 | + DesiredReplicas: &n, |
| 59 | + LastScalingEvent: &metav1.Time{ |
| 60 | + Time: time.Now(), |
| 61 | + }, |
| 62 | + } |
| 63 | + ap.log.Info("Reconcile Agent Pool", "msg", "successfully scaled agents to 0") |
| 64 | + } |
| 65 | + } |
| 66 | + // Remove tokens |
| 67 | + if len(ap.instance.Status.AgentTokens) > 0 { |
| 68 | + ap.log.Info("Reconcile Agent Pool", "msg", "remove tokens") |
| 69 | + for _, t := range ap.instance.Status.AgentTokens { |
| 70 | + err := ap.tfClient.Client.AgentTokens.Delete(ctx, t.ID) |
| 71 | + if err != nil && err != tfc.ErrResourceNotFound { |
| 72 | + ap.log.Error(err, "Reconcile Agent Pool", "msg", fmt.Sprintf("failed to remove token %s", t.ID)) |
| 73 | + return err |
| 74 | + } |
| 75 | + err = r.removeToken(ctx, ap, t.ID) |
| 76 | + if err != nil { |
| 77 | + return err |
| 78 | + } |
| 79 | + } |
| 80 | + ap.log.Info("Reconcile Agent Pool", "msg", "successfully deleted tokens") |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + return nil |
| 85 | +} |
0 commit comments