diff --git a/castai/resource_gke_cluster_id.go b/castai/resource_gke_cluster_id.go index 6e0f8d57d..4703746fe 100644 --- a/castai/resource_gke_cluster_id.go +++ b/castai/resource_gke_cluster_id.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/castai/terraform-provider-castai/castai/sdk" + "github.com/hashicorp/terraform-plugin-log/tflog" ) const ( @@ -117,25 +118,13 @@ func resourceCastaiGKEClusterIdCreate(ctx context.Context, data *schema.Resource return diag.FromErr(err) } if err := data.Set(FieldClusterToken, tkn); err != nil { - return diag.FromErr(fmt.Errorf("setting cluster token: %w", err)) + return diag.FromErr(fmt.Errorf("setting cluster token: %v", err)) } data.SetId(clusterID) // If client service account is set, create service account on cast side. if len(data.Get(FieldGKEClientSA).(string)) > 0 { - resp, err := client.ExternalClusterAPIGKECreateSAWithResponse(ctx, data.Id(), sdk.ExternalClusterAPIGKECreateSARequest{ - Gke: &sdk.ExternalclusterV1UpdateGKEClusterParams{ - GkeSaImpersonate: toPtr(data.Get(FieldGKEClientSA).(string)), - ProjectId: toPtr(data.Get(FieldGKEClusterProjectId).(string)), - }, - }) - if err != nil { - return diag.FromErr(err) - } - if resp.JSON200 == nil || resp.JSON200.ServiceAccount == nil { - return diag.FromErr(fmt.Errorf("service account not returned")) - } - if err := data.Set(FieldGKECastSA, toString(resp.JSON200.ServiceAccount)); err != nil { - return diag.FromErr(fmt.Errorf("service account id: %w", err)) + if err := createCastServiceAccount(ctx, client, data); err != nil { + return diag.FromErr(fmt.Errorf("[ERROR] Creating Cast service account %v", err)) } } return nil @@ -145,7 +134,7 @@ func resourceCastaiGKEClusterIdRead(ctx context.Context, data *schema.ResourceDa client := meta.(*ProviderConfig).api if data.Id() == "" { - log.Printf("[INFO] id is null not fetching anything.") + tflog.Info(ctx, "id is null, not fetching anything.") return nil } @@ -177,9 +166,37 @@ func resourceCastaiGKEClusterIdRead(ctx context.Context, data *schema.ResourceDa } func resourceCastaiGKEClusterIdUpdate(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Re-read the resource to ensure the state is up-to-date return resourceCastaiGKEClusterIdRead(ctx, data, meta) } func resourceCastaiGKEClusterIdDelete(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { - return resourceCastaiClusterDelete(ctx, data, meta) + // Disable service account used for impersonation. + client := meta.(*ProviderConfig).api + tflog.Info(ctx, "Disabling service account.") + _, err := client.ExternalClusterAPIDisableGKESA(ctx, data.Id()) + if err != nil { + return diag.FromErr(fmt.Errorf("disabling service account: %w", err)) + } + return nil +} + +func createCastServiceAccount(ctx context.Context, client sdk.ClientWithResponsesInterface, data *schema.ResourceData) diag.Diagnostics { + resp, err := client.ExternalClusterAPIGKECreateSAWithResponse(ctx, data.Id(), sdk.ExternalClusterAPIGKECreateSARequest{ + Gke: &sdk.ExternalclusterV1UpdateGKEClusterParams{ + GkeSaImpersonate: toPtr(data.Get(FieldGKEClientSA).(string)), + ProjectId: toPtr(data.Get(FieldGKEClusterProjectId).(string)), + }, + }) + if err != nil { + return diag.FromErr(err) + } + if resp.JSON200 == nil || resp.JSON200.ServiceAccount == nil { + return diag.FromErr(fmt.Errorf("service account not returned")) + } + if err := data.Set(FieldGKECastSA, toString(resp.JSON200.ServiceAccount)); err != nil { + return diag.FromErr(fmt.Errorf("service account id: %w", err)) + } + + return nil } diff --git a/castai/sdk/api.gen.go b/castai/sdk/api.gen.go index 105caf704..87590677e 100644 --- a/castai/sdk/api.gen.go +++ b/castai/sdk/api.gen.go @@ -313,10 +313,11 @@ const ( // Defines values for PoliciesV1EvictorStatus. const ( - PoliciesV1EvictorStatusCompatible PoliciesV1EvictorStatus = "Compatible" - PoliciesV1EvictorStatusIncompatible PoliciesV1EvictorStatus = "Incompatible" - PoliciesV1EvictorStatusMissing PoliciesV1EvictorStatus = "Missing" - PoliciesV1EvictorStatusUnknown PoliciesV1EvictorStatus = "Unknown" + PoliciesV1EvictorStatusCompatible PoliciesV1EvictorStatus = "Compatible" + PoliciesV1EvictorStatusIncompatible PoliciesV1EvictorStatus = "Incompatible" + PoliciesV1EvictorStatusInvalidConfig PoliciesV1EvictorStatus = "InvalidConfig" + PoliciesV1EvictorStatusMissing PoliciesV1EvictorStatus = "Missing" + PoliciesV1EvictorStatusUnknown PoliciesV1EvictorStatus = "Unknown" ) // Defines values for PoliciesV1PodPinnerStatus. @@ -434,6 +435,12 @@ const ( QUANTILE WorkloadoptimizationV1ResourcePoliciesFunction = "QUANTILE" ) +// Defines values for WorkloadoptimizationV1RolloutBehaviorType. +const ( + NODISRUPTION WorkloadoptimizationV1RolloutBehaviorType = "NO_DISRUPTION" + UNSPECIFIED WorkloadoptimizationV1RolloutBehaviorType = "UNSPECIFIED" +) + // Defines values for CommitmentsAPIGetCommitmentUsageHistoryParamsAggregationInterval. const ( AGGREGATIONINTERVALUNSPECIFIED CommitmentsAPIGetCommitmentUsageHistoryParamsAggregationInterval = "AGGREGATION_INTERVAL_UNSPECIFIED" @@ -4884,10 +4891,11 @@ type WorkloadoptimizationV1RecommendationPolicies struct { // ManagementOption Defines possible options for workload management. // READ_ONLY - workload watched (metrics collected), but no actions may be performed by CAST AI. // MANAGED - workload watched (metrics collected), CAST AI may perform actions on the workload. - ManagementOption WorkloadoptimizationV1ManagementOption `json:"managementOption"` - Memory WorkloadoptimizationV1ResourcePolicies `json:"memory"` - MemoryEvent *WorkloadoptimizationV1MemoryEventSettings `json:"memoryEvent,omitempty"` - Startup *WorkloadoptimizationV1StartupSettings `json:"startup,omitempty"` + ManagementOption WorkloadoptimizationV1ManagementOption `json:"managementOption"` + Memory WorkloadoptimizationV1ResourcePolicies `json:"memory"` + MemoryEvent *WorkloadoptimizationV1MemoryEventSettings `json:"memoryEvent,omitempty"` + RolloutBehavior *WorkloadoptimizationV1RolloutBehaviorSettings `json:"rolloutBehavior,omitempty"` + Startup *WorkloadoptimizationV1StartupSettings `json:"startup,omitempty"` } // WorkloadoptimizationV1RecommendedPodCountChangedEvent defines model for workloadoptimization.v1.RecommendedPodCountChangedEvent. @@ -5104,6 +5112,17 @@ type WorkloadoptimizationV1Resources struct { Requests *WorkloadoptimizationV1ResourceQuantity `json:"requests,omitempty"` } +// WorkloadoptimizationV1RolloutBehaviorSettings defines model for workloadoptimization.v1.RolloutBehaviorSettings. +type WorkloadoptimizationV1RolloutBehaviorSettings struct { + // Type Defines workload recommendation rollout types. + // NO_DISRUPTION - rollout shouldn't cause service disruption. + Type *WorkloadoptimizationV1RolloutBehaviorType `json:"type,omitempty"` +} + +// WorkloadoptimizationV1RolloutBehaviorType Defines workload recommendation rollout types. +// NO_DISRUPTION - rollout shouldn't cause service disruption. +type WorkloadoptimizationV1RolloutBehaviorType string + // WorkloadoptimizationV1ScalingBehaviour defines model for workloadoptimization.v1.ScalingBehaviour. type WorkloadoptimizationV1ScalingBehaviour struct { // StabilizationWindowSeconds Defines the minimum time to make a scaling decision after decision has been made. @@ -5318,8 +5337,9 @@ type WorkloadoptimizationV1WorkloadConfigUpdateV2 struct { // WorkloadoptimizationV1WorkloadConfigV2 defines model for workloadoptimization.v1.WorkloadConfigV2. type WorkloadoptimizationV1WorkloadConfigV2 struct { - HpaConfig WorkloadoptimizationV1HPAConfig `json:"hpaConfig"` - VpaConfig WorkloadoptimizationV1VPAConfig `json:"vpaConfig"` + HpaConfig WorkloadoptimizationV1HPAConfig `json:"hpaConfig"` + RolloutBehavior *WorkloadoptimizationV1RolloutBehaviorSettings `json:"rolloutBehavior,omitempty"` + VpaConfig WorkloadoptimizationV1VPAConfig `json:"vpaConfig"` } // WorkloadoptimizationV1WorkloadEvent defines model for workloadoptimization.v1.WorkloadEvent. @@ -5362,8 +5382,9 @@ type WorkloadoptimizationV1WorkloadMetrics struct { // WorkloadoptimizationV1WorkloadOverrides defines model for workloadoptimization.v1.WorkloadOverrides. type WorkloadoptimizationV1WorkloadOverrides struct { - Horizontal *WorkloadoptimizationV1HorizontalOverrides `json:"horizontal,omitempty"` - Vertical *WorkloadoptimizationV1VerticalOverrides `json:"vertical,omitempty"` + Horizontal *WorkloadoptimizationV1HorizontalOverrides `json:"horizontal,omitempty"` + RolloutBehavior *WorkloadoptimizationV1RolloutBehaviorSettings `json:"rolloutBehavior,omitempty"` + Vertical *WorkloadoptimizationV1VerticalOverrides `json:"vertical,omitempty"` } // WorkloadoptimizationV1WorkloadRecommendation defines model for workloadoptimization.v1.WorkloadRecommendation.