From 6a7a794ad00eabca046691710f952cf5c5baf15b Mon Sep 17 00:00:00 2001 From: Ramon Snir Date: Mon, 13 May 2024 17:32:20 -0400 Subject: [PATCH] unify netlify_environment_variable and netlify_secret_environment_variable --- docs/resources/environment_variable.md | 16 +++- docs/resources/secret_environment_variable.md | 43 --------- examples/env_vars/main.tf | 4 +- .../provider/environment_variable_resource.go | 92 +++++++++++++------ internal/provider/provider.go | 3 +- 5 files changed, 84 insertions(+), 74 deletions(-) delete mode 100644 docs/resources/secret_environment_variable.md diff --git a/docs/resources/environment_variable.md b/docs/resources/environment_variable.md index 6cec63e..a8f09f7 100644 --- a/docs/resources/environment_variable.md +++ b/docs/resources/environment_variable.md @@ -19,17 +19,31 @@ description: |- - `account_id` (String) - `key` (String) -- `value` (Attributes Set) (see [below for nested schema](#nestedatt--value)) ### Optional - `scopes` (Set of String) +- `secret_value` (Attributes Set) (see [below for nested schema](#nestedatt--secret_value)) - `site_id` (String) +- `value` (Attributes Set) (see [below for nested schema](#nestedatt--value)) ### Read-Only - `last_updated` (String) + +### Nested Schema for `secret_value` + +Required: + +- `context` (String) +- `value` (String, Sensitive) + +Optional: + +- `context_parameter` (String) + + ### Nested Schema for `value` diff --git a/docs/resources/secret_environment_variable.md b/docs/resources/secret_environment_variable.md deleted file mode 100644 index 6ee3e9d..0000000 --- a/docs/resources/secret_environment_variable.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "netlify_secret_environment_variable Resource - netlify" -subcategory: "" -description: |- - ---- - -# netlify_secret_environment_variable (Resource) - - - - - - -## Schema - -### Required - -- `account_id` (String) -- `key` (String) -- `value` (Attributes Set) (see [below for nested schema](#nestedatt--value)) - -### Optional - -- `scopes` (Set of String) -- `site_id` (String) - -### Read-Only - -- `last_updated` (String) - - -### Nested Schema for `value` - -Required: - -- `context` (String) -- `value` (String, Sensitive) - -Optional: - -- `context_parameter` (String) diff --git a/examples/env_vars/main.tf b/examples/env_vars/main.tf index 7bd3460..d4a7e09 100644 --- a/examples/env_vars/main.tf +++ b/examples/env_vars/main.tf @@ -43,11 +43,11 @@ resource "netlify_environment_variable" "meow" { ] } -resource "netlify_secret_environment_variable" "meow" { +resource "netlify_environment_variable" "secret_meow" { account_id = data.netlify_account.current.id site_id = data.netlify_site.platform_test.id key = "SECRET_TEST_MEOW" - value = [ + secret_value = [ { value = "secret roflmaocopter", context = "production", diff --git a/internal/provider/environment_variable_resource.go b/internal/provider/environment_variable_resource.go index 725ae6b..7516360 100644 --- a/internal/provider/environment_variable_resource.go +++ b/internal/provider/environment_variable_resource.go @@ -29,17 +29,12 @@ var ( _ resource.ResourceWithImportState = &environmentVariableResource{} ) -var NewEnvironmentVariableResource = func(isSecret bool) func() resource.Resource { - return func() resource.Resource { - return &environmentVariableResource{ - isSecret: isSecret, - } - } +func NewEnvironmentVariableResource() resource.Resource { + return &environmentVariableResource{} } type environmentVariableResource struct { - data NetlifyProviderData - isSecret bool + data NetlifyProviderData } type environmentVariableResourceModel struct { @@ -49,6 +44,7 @@ type environmentVariableResourceModel struct { Key types.String `tfsdk:"key"` Scopes []types.String `tfsdk:"scopes"` Value []environmentVariableValueModel `tfsdk:"value"` + SecretValue []environmentVariableValueModel `tfsdk:"secret_value"` } type environmentVariableValueModel struct { @@ -58,11 +54,7 @@ type environmentVariableValueModel struct { } func (r *environmentVariableResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { - if r.isSecret { - resp.TypeName = req.ProviderTypeName + "_secret_environment_variable" - } else { - resp.TypeName = req.ProviderTypeName + "_environment_variable" - } + resp.TypeName = req.ProviderTypeName + "_environment_variable" } func (r *environmentVariableResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { @@ -124,13 +116,44 @@ func (r *environmentVariableResource) Schema(_ context.Context, _ resource.Schem })), }, "value": schema.SetNestedAttribute{ - Required: true, + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + // TODO: confirm it's OK that we aren't tracking the ID of value items + "value": schema.StringAttribute{ + Required: true, + }, + "context": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("all", "dev", "branch-deploy", "deploy-preview", "production", "branch"), + }, + }, + "context_parameter": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(""), + Validators: []validator.String{ + netlify_validators.EnvironmentVariableContextParameterValidator{ + ContextPathExpression: path.MatchRelative().AtParent().AtName("context"), + }, + }, + }, + }, + }, + // TODO: validate that values don't overlap + }, + "secret_value": schema.SetNestedAttribute{ + Optional: true, + Validators: []validator.Set{ + setvalidator.ExactlyOneOf(path.MatchRoot("value")), + }, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ // TODO: confirm it's OK that we aren't tracking the ID of value items "value": schema.StringAttribute{ Required: true, - Sensitive: r.isSecret, + Sensitive: true, }, "context": schema.StringAttribute{ Required: true, @@ -167,6 +190,15 @@ func (r *environmentVariableResource) Create(ctx context.Context, req resource.C for i, scope := range plan.Scopes { scopes[i] = scope.ValueString() } + var values []*models.EnvVarValue + var isSecret bool + if plan.SecretValue != nil && len(plan.SecretValue) > 0 { + values = serializeValues(plan.SecretValue) + isSecret = true + } else { + values = serializeValues(plan.Value) + isSecret = false + } createEnvVarsParams := operations. NewCreateEnvVarsParams(). WithAccountID(plan.AccountID.ValueString()). @@ -174,8 +206,8 @@ func (r *environmentVariableResource) Create(ctx context.Context, req resource.C { Key: plan.Key.ValueString(), Scopes: scopes, - Values: serializeValues(plan.Value), - IsSecret: r.isSecret, + Values: values, + IsSecret: isSecret, }, }) if plan.SiteID.ValueString() != "" { @@ -190,7 +222,7 @@ func (r *environmentVariableResource) Create(ctx context.Context, req resource.C plan.Key.ValueString(), plan.AccountID.ValueString(), plan.SiteID.ValueString(), - r.isSecret, + isSecret, err.Error(), ), ) @@ -219,7 +251,7 @@ func (r *environmentVariableResource) Read(ctx context.Context, req resource.Rea getEnvVarParams.SetSiteID(state.SiteID.ValueStringPointer()) } envVar, err := r.data.client.Operations.GetEnvVar(getEnvVarParams, r.data.authInfo) - if err != nil || envVar.Payload.IsSecret != r.isSecret { + if err != nil { resp.Diagnostics.AddError( "Error reading Netlify environment variable", fmt.Sprintf( @@ -227,7 +259,7 @@ func (r *environmentVariableResource) Read(ctx context.Context, req resource.Rea state.Key.ValueString(), state.AccountID.ValueString(), state.SiteID.ValueString(), - r.isSecret, + envVar.Payload.IsSecret, err.Error(), ), ) @@ -238,7 +270,7 @@ func (r *environmentVariableResource) Read(ctx context.Context, req resource.Rea for i, scope := range envVar.Payload.Scopes { state.Scopes[i] = types.StringValue(strings.ReplaceAll(strings.ReplaceAll(scope, " ", "-"), "_", "-")) } - if !r.isSecret { + if !envVar.Payload.IsSecret { state.Value = parseValues(envVar.Payload.Values) } @@ -259,6 +291,15 @@ func (r *environmentVariableResource) Update(ctx context.Context, req resource.U for i, scope := range plan.Scopes { scopes[i] = scope.ValueString() } + var values []*models.EnvVarValue + var isSecret bool + if plan.SecretValue != nil && len(plan.SecretValue) > 0 { + values = serializeValues(plan.SecretValue) + isSecret = true + } else { + values = serializeValues(plan.Value) + isSecret = false + } updateEnvVarParams := operations. NewUpdateEnvVarParams(). WithAccountID(plan.AccountID.ValueString()). @@ -266,8 +307,8 @@ func (r *environmentVariableResource) Update(ctx context.Context, req resource.U WithEnvVar(&models.UpdateEnvVarParamsBody{ Key: plan.Key.ValueString(), Scopes: scopes, - Values: serializeValues(plan.Value), - IsSecret: r.isSecret, + Values: values, + IsSecret: isSecret, }) if plan.SiteID.ValueString() != "" { updateEnvVarParams.SetSiteID(plan.SiteID.ValueStringPointer()) @@ -281,7 +322,7 @@ func (r *environmentVariableResource) Update(ctx context.Context, req resource.U plan.Key.ValueString(), plan.AccountID.ValueString(), plan.SiteID.ValueString(), - r.isSecret, + isSecret, err.Error(), ), ) @@ -314,11 +355,10 @@ func (r *environmentVariableResource) Delete(ctx context.Context, req resource.D resp.Diagnostics.AddError( "Error deleting Netlify environment variable", fmt.Sprintf( - "Could not delete Netlify environment variable order ID %q (account ID: %q, site ID: %q, secret: %v): %q", + "Could not delete Netlify environment variable order ID %q (account ID: %q, site ID: %q): %q", state.Key.ValueString(), state.AccountID.ValueString(), state.SiteID.ValueString(), - r.isSecret, err.Error(), ), ) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 56b8ace..9f891e0 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -166,8 +166,7 @@ func (p *NetlifyProvider) Resources(ctx context.Context) []func() resource.Resou NewDnsRecordResource("SPF"), NewDnsRecordResource("TXT"), NewDnsZoneResource, - NewEnvironmentVariableResource(false), - NewEnvironmentVariableResource(true), + NewEnvironmentVariableResource, } }