diff --git a/pkg/plan_modifier/cloud_provider.go b/pkg/plan_modifier/cloud_provider.go new file mode 100644 index 00000000..b3bad7fa --- /dev/null +++ b/pkg/plan_modifier/cloud_provider.go @@ -0,0 +1,59 @@ +package plan_modifier + +import ( + "context" + "strings" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-go/tftypes" +) + +func CustomClusterCloudProvider() planmodifier.String { + return customCloudProviderModifier{} +} + +type customCloudProviderModifier struct{} + +func (m customCloudProviderModifier) Description(_ context.Context) string { + return "Once set, the value of this attribute in state will not change." +} + +func (m customCloudProviderModifier) MarkdownDescription(_ context.Context) string { + return "Once set, the value of this attribute in state will not change." +} + +func (m customCloudProviderModifier) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) { + cloudProviderConfig := req.ConfigValue.ValueString() + var configObject map[string]tftypes.Value + + err := req.Config.Raw.As(&configObject) + if err != nil { + resp.Diagnostics.AddError("Mapping config object in custom cloud provider modifier error", err.Error()) + return + } + + if !strings.Contains(cloudProviderConfig, "bah") { + peIds, ok := configObject["pe_allowed_principal_ids"] + if ok && !peIds.IsNull() { + resp.Diagnostics.AddError("your cloud account 'pe_allowed_principal_ids' field not allowed error", + "field 'pe_allowed_principal_ids' should only be set if you are using BigAnimal's cloud account e.g. 'bah:aws', please remove 'pe_allowed_principal_ids'") + return + } + + saIds, ok := configObject["service_account_ids"] + if ok && !saIds.IsNull() { + resp.Diagnostics.AddError("your cloud account 'service_account_ids' field not allowed error", + "field 'service_account_ids' should only be set if you are using BigAnimal's cloud account 'bah:gcp', please remove 'service_account_ids'") + return + } + } + + if strings.Contains(cloudProviderConfig, "bah") && !strings.Contains(cloudProviderConfig, "bah:gcp") { + saIds, ok := configObject["service_account_ids"] + if ok && !saIds.IsNull() { + resp.Diagnostics.AddError("your cloud account 'service_account_ids' field not allowed error", + "you are not using cloud provider 'bah:gcp', field 'service_account_ids' should only be set if you are using cloud provider 'bah:gcp', please remove 'service_account_ids'") + return + } + } +} diff --git a/pkg/plan_modifier/data_group_custom_diff.go b/pkg/plan_modifier/data_group_custom_diff.go index 2facbb45..db207562 100644 --- a/pkg/plan_modifier/data_group_custom_diff.go +++ b/pkg/plan_modifier/data_group_custom_diff.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "reflect" + "strings" "github.com/EnterpriseDB/terraform-provider-biganimal/pkg/models/pgd/terraform" "github.com/hashicorp/terraform-plugin-framework/attr" @@ -32,6 +33,44 @@ func (m CustomDataGroupDiffModifier) MarkdownDescription(_ context.Context) stri // PlanModifyList implements the plan modification logic. func (m CustomDataGroupDiffModifier) PlanModifyList(ctx context.Context, req planmodifier.ListRequest, resp *planmodifier.ListResponse) { + var stateDgsObs []terraform.DataGroup + diag := req.StateValue.ElementsAs(ctx, &stateDgsObs, false) + if diag.ErrorsCount() > 0 { + resp.Diagnostics.Append(diag...) + return + } + + var planDgsObs []terraform.DataGroup + diag = resp.PlanValue.ElementsAs(ctx, &planDgsObs, false) + if diag.ErrorsCount() > 0 { + resp.Diagnostics.Append(diag...) + return + } + + // validations + for _, pDg := range planDgsObs { + // validation to remove principal ids and service account ids if cloud provider is not bah + if !strings.Contains(*pDg.Provider.CloudProviderId, "bah") { + if !pDg.PeAllowedPrincipalIds.IsNull() && len(pDg.PeAllowedPrincipalIds.Elements()) > 0 { + resp.Diagnostics.AddError("your cloud account 'pe_allowed_principal_ids' field not allowed error", + fmt.Sprintf("field 'pe_allowed_principal_ids' for region %v should only be set if you are using BigAnimal's cloud account e.g. 'bah:aws', please remove 'pe_allowed_principal_ids'\n", pDg.Region.RegionId)) + return + } + + if !pDg.ServiceAccountIds.IsNull() && len(pDg.ServiceAccountIds.Elements()) > 0 { + resp.Diagnostics.AddError("your cloud account 'service_account_ids' field not allowed error", + fmt.Sprintf("field 'service_account_ids' for region %v should only be set if you are using BigAnimal's cloud account 'bah:gcp', please remove 'service_account_ids'\n", pDg.Region.RegionId)) + return + } + } else if strings.Contains(*pDg.Provider.CloudProviderId, "bah") && !strings.Contains(*pDg.Provider.CloudProviderId, "bah:gcp") { + if !pDg.ServiceAccountIds.IsNull() && len(pDg.ServiceAccountIds.Elements()) > 0 { + resp.Diagnostics.AddError("your cloud account 'service_account_ids' field not allowed error", + fmt.Sprintf("you are not using BigAnimal's cloud account 'bah:gcp' for region %v, field 'service_account_ids' should only be set if you are using BigAnimal's cloud account 'bah:gcp', please remove 'service_account_ids'", pDg.Region.RegionId)) + return + } + } + } + if req.StateValue.IsNull() { // private networking case when doing create var planDgsObs []terraform.DataGroup @@ -87,20 +126,6 @@ func (m CustomDataGroupDiffModifier) PlanModifyList(ctx context.Context, req pla newDgPlan := []terraform.DataGroup{} - var stateDgsObs []terraform.DataGroup - diag := req.StateValue.ElementsAs(ctx, &stateDgsObs, false) - if diag.ErrorsCount() > 0 { - resp.Diagnostics.Append(diag...) - return - } - - var planDgsObs []terraform.DataGroup - diag = resp.PlanValue.ElementsAs(ctx, &planDgsObs, false) - if diag.ErrorsCount() > 0 { - resp.Diagnostics.Append(diag...) - return - } - // Need to sort the plan according to the state this is so the compare and setting unknowns are correct // https://developer.hashicorp.com/terraform/plugin/framework/resources/plan-modification#caveats // sort the order of the plan the same as the state, state is from the read and plan is from the config diff --git a/pkg/provider/resource_analytics_cluster.go b/pkg/provider/resource_analytics_cluster.go index 51ec7a29..5eabc97a 100644 --- a/pkg/provider/resource_analytics_cluster.go +++ b/pkg/provider/resource_analytics_cluster.go @@ -169,8 +169,9 @@ func (r *analyticsClusterResource) Schema(ctx context.Context, req resource.Sche PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, }, "cloud_provider": schema.StringAttribute{ - Description: "Cloud provider. For example, \"aws\" or \"bah:aws\".", - Required: true, + Description: "Cloud provider. For example, \"aws\" or \"bah:aws\".", + Required: true, + PlanModifiers: []planmodifier.String{plan_modifier.CustomClusterCloudProvider()}, }, "pg_type": schema.StringAttribute{ MarkdownDescription: "Postgres type. For example, \"epas\" or \"pgextended\".", diff --git a/pkg/provider/resource_cluster.go b/pkg/provider/resource_cluster.go index 5855ae53..48b1456e 100644 --- a/pkg/provider/resource_cluster.go +++ b/pkg/provider/resource_cluster.go @@ -326,8 +326,9 @@ func (c *clusterResource) Schema(ctx context.Context, req resource.SchemaRequest PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, }, "cloud_provider": schema.StringAttribute{ - Description: "Cloud provider. For example, \"aws\", \"azure\", \"gcp\" or \"bah:aws\", \"bah:gcp\".", - Required: true, + Description: "Cloud provider. For example, \"aws\", \"azure\", \"gcp\" or \"bah:aws\", \"bah:gcp\".", + Required: true, + PlanModifiers: []planmodifier.String{plan_modifier.CustomClusterCloudProvider()}, }, "pg_type": schema.StringAttribute{ MarkdownDescription: "Postgres type. For example, \"epas\", \"pgextended\", or \"postgres\".",