From 1157c5539122a9fdb09f66570ff5d190695ccfba Mon Sep 17 00:00:00 2001 From: Douglas Harcourt Parsons Date: Tue, 27 Feb 2024 12:05:33 +0000 Subject: [PATCH] Add a Data Source for Shared Environment Variables --- .../shared_environment_variable.md | 50 ++++ .../data-source.tf | 12 + vercel/data_source_project.go | 2 +- ...data_source_shared_environment_variable.go | 245 ++++++++++++++++++ ...source_shared_environment_variable_test.go | 82 ++++++ vercel/provider.go | 1 + .../resource_shared_environment_variable.go | 29 ++- ...ource_shared_environment_variable_model.go | 70 +++-- 8 files changed, 451 insertions(+), 40 deletions(-) create mode 100644 docs/data-sources/shared_environment_variable.md create mode 100644 examples/data-sources/vercel_shared_environment_variable/data-source.tf create mode 100644 vercel/data_source_shared_environment_variable.go create mode 100644 vercel/data_source_shared_environment_variable_test.go diff --git a/docs/data-sources/shared_environment_variable.md b/docs/data-sources/shared_environment_variable.md new file mode 100644 index 00000000..ebb402a7 --- /dev/null +++ b/docs/data-sources/shared_environment_variable.md @@ -0,0 +1,50 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "vercel_shared_environment_variable Data Source - terraform-provider-vercel" +subcategory: "" +description: |- + Provides information about an existing Shared Environment Variable within Vercel. + A Shared Environment Variable resource defines an Environment Variable that can be shared between multiple Vercel Projects. + For more detailed information, please see the Vercel documentation https://vercel.com/docs/concepts/projects/environment-variables/shared-environment-variables. +--- + +# vercel_shared_environment_variable (Data Source) + +Provides information about an existing Shared Environment Variable within Vercel. + +A Shared Environment Variable resource defines an Environment Variable that can be shared between multiple Vercel Projects. + +For more detailed information, please see the [Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables/shared-environment-variables). + +## Example Usage + +```terraform +# Environment variables can be identified by their ID, or by their key and target. +# The ID is hard to find, but can be taken from the network tab, inside developer tools, on the shared environment variable page. +data "vercel_shared_environment_variable" "example" { + id = "xxxxxxxxxxxxxxx" +} + +# Alternatively, you can use the key and target to identify the environment variable. +# Note that all `target`s must be specified for a match to be found. +data "vercel_shared_environment_variable" "example_by_key_and_target" { + key = "MY_ENV_VAR" + target = ["production", "preview"] +} +``` + + +## Schema + +### Optional + +- `id` (String) The ID of the Environment Variable. +- `key` (String) The name of the Environment Variable. +- `target` (Set of String) The environments that the Environment Variable should be present on. Valid targets are either `production`, `preview`, or `development`. +- `team_id` (String) The ID of the Vercel team. Shared environment variables require a team. + +### Read-Only + +- `project_ids` (Set of String) The ID of the Vercel project. +- `sensitive` (Boolean) Whether the Environment Variable is sensitive or not. +- `value` (String, Sensitive) The value of the Environment Variable. diff --git a/examples/data-sources/vercel_shared_environment_variable/data-source.tf b/examples/data-sources/vercel_shared_environment_variable/data-source.tf new file mode 100644 index 00000000..017143e7 --- /dev/null +++ b/examples/data-sources/vercel_shared_environment_variable/data-source.tf @@ -0,0 +1,12 @@ +# Environment variables can be identified by their ID, or by their key and target. +# The ID is hard to find, but can be taken from the network tab, inside developer tools, on the shared environment variable page. +data "vercel_shared_environment_variable" "example" { + id = "xxxxxxxxxxxxxxx" +} + +# Alternatively, you can use the key and target to identify the environment variable. +# Note that all `target`s must be specified for a match to be found. +data "vercel_shared_environment_variable" "example_by_key_and_target" { + key = "MY_ENV_VAR" + target = ["production", "preview"] +} diff --git a/vercel/data_source_project.go b/vercel/data_source_project.go index 9aa12213..f06d5ba5 100644 --- a/vercel/data_source_project.go +++ b/vercel/data_source_project.go @@ -245,7 +245,7 @@ func (d *projectDataSource) Read(ctx context.Context, req datasource.ReadRequest if err != nil { resp.Diagnostics.AddError( "Error converting project response to model", - "Could not create project, unexpected error: "+err.Error(), + "Could not read project, unexpected error: "+err.Error(), ) return } diff --git a/vercel/data_source_shared_environment_variable.go b/vercel/data_source_shared_environment_variable.go new file mode 100644 index 00000000..ff7ffdc1 --- /dev/null +++ b/vercel/data_source_shared_environment_variable.go @@ -0,0 +1,245 @@ +package vercel + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/vercel/terraform-provider-vercel/client" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ datasource.DataSourceWithValidateConfig = &sharedEnvironmentVariableDataSource{} +) + +func newSharedEnvironmentVariableDataSource() datasource.DataSource { + return &sharedEnvironmentVariableDataSource{} +} + +type sharedEnvironmentVariableDataSource struct { + client *client.Client +} + +func (d *sharedEnvironmentVariableDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_shared_environment_variable" +} + +func (d *sharedEnvironmentVariableDataSource) ValidateConfig(ctx context.Context, req datasource.ValidateConfigRequest, resp *datasource.ValidateConfigResponse) { + var config SharedEnvironmentVariable + diags := req.Config.Get(ctx, &config) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + if config.ID.IsNull() && config.Key.IsNull() { + resp.Diagnostics.AddError( + "Shared Environment Variable invalid", + "Shared Environment Variable must have either a key and target, or an ID", + ) + return + } + + if !config.ID.IsNull() && (!config.Key.IsNull() || len(config.Target.Elements()) > 0) { + resp.Diagnostics.AddError( + "Shared Environment Variable invalid", + "Shared Environment Variable can only specify either an ID or a key and target, not both", + ) + return + } + + if !config.Key.IsNull() && !config.Target.IsUnknown() && len(config.Target.Elements()) == 0 { + resp.Diagnostics.AddError( + "Shared Environment Variable invalid", + "Shared Environment Variable must specify at least one `target` when specifying a key", + ) + return + } +} + +func (d *sharedEnvironmentVariableDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*client.Client) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + d.client = client +} + +// Schema returns the schema information for a shared environment variable data source +func (d *sharedEnvironmentVariableDataSource) Schema(_ context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: ` +Provides information about an existing Shared Environment Variable within Vercel. + +A Shared Environment Variable resource defines an Environment Variable that can be shared between multiple Vercel Projects. + +For more detailed information, please see the [Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables/shared-environment-variables). +`, + Attributes: map[string]schema.Attribute{ + "team_id": schema.StringAttribute{ + Optional: true, + Computed: true, + Description: "The ID of the Vercel team. Shared environment variables require a team.", + }, + "id": schema.StringAttribute{ + Description: "The ID of the Environment Variable.", + Optional: true, + Computed: true, + }, + "target": schema.SetAttribute{ + Optional: true, + Computed: true, + Description: "The environments that the Environment Variable should be present on. Valid targets are either `production`, `preview`, or `development`.", + ElementType: types.StringType, + Validators: []validator.Set{ + stringSetItemsIn("production", "preview", "development"), + stringSetMinCount(1), + }, + }, + "key": schema.StringAttribute{ + Optional: true, + Computed: true, + Description: "The name of the Environment Variable.", + }, + "value": schema.StringAttribute{ + Computed: true, + Description: "The value of the Environment Variable.", + Sensitive: true, + }, + "project_ids": schema.SetAttribute{ + Computed: true, + Description: "The ID of the Vercel project.", + ElementType: types.StringType, + }, + "sensitive": schema.BoolAttribute{ + Description: "Whether the Environment Variable is sensitive or not.", + Computed: true, + }, + }, + } +} + +func isSameTarget(a []string, b []types.String) bool { + if len(a) != len(b) { + return false + } + for _, v := range b { + if !contains(a, v.ValueString()) { + return false + } + } + return true +} + +// Read will read project information by requesting it from the Vercel API, and will update terraform +// with this information. +// It is called by the provider whenever data source values should be read to update state. +func (d *sharedEnvironmentVariableDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var config SharedEnvironmentVariable + diags := req.Config.Get(ctx, &config) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + id := config.ID.ValueString() + if id == "" { + // Then we need to look up the shared env var by key + target. Bleugh. + envs, err := d.client.ListSharedEnvironmentVariables(ctx, config.TeamID.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Error finding shared environment variable", + fmt.Sprintf("Could not list shared environment variables for team %s, unexpected error: %s", + config.TeamID.ValueString(), + err, + ), + ) + return + } + tflog.Trace(ctx, "list shared environment variable", map[string]interface{}{ + "team_id": config.TeamID.ValueString(), + }) + var configTarget []types.String + diags := config.Target.ElementsAs(ctx, &configTarget, false) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + for _, e := range envs { + if e.Key == config.Key.ValueString() && isSameTarget(e.Target, configTarget) { + // We have found the right env var by Key + Target(s). + id = e.ID + break + } + } + + if id == "" { + // the env var was not found - output an error + targetStrs := []string{} + for _, t := range configTarget { + targetStrs = append(targetStrs, t.ValueString()) + } + resp.Diagnostics.AddError( + "Error reading shared environment variable", + fmt.Sprintf("Could not read shared environment variable %s, unexpected error: %s", + config.Key.ValueString(), + fmt.Errorf( + "the shared environment variable with key %s and target %s was not found. Please ensure the full `targets` are specified and that it exists", + config.Key.ValueString(), + strings.Join(targetStrs, ","), + ), + ), + ) + return + } + } + + // else we can get by ID. + out, err := d.client.GetSharedEnvironmentVariable(ctx, config.TeamID.ValueString(), id) + if err != nil { + resp.Diagnostics.AddError( + "Error reading shared environment variable", + fmt.Sprintf("Could not read shared environment variable %s %s, unexpected error: %s", + config.TeamID.ValueString(), + config.ID.ValueString(), + err, + ), + ) + return + } + + result := convertResponseToSharedEnvironmentVariable(out, types.StringNull()) + if err != nil { + resp.Diagnostics.AddError( + "Error converting shared environment variable response to model", + "Could not read shared environment variable, unexpected error: "+err.Error(), + ) + return + } + tflog.Trace(ctx, "read shared environment variable", map[string]interface{}{ + "team_id": result.TeamID.ValueString(), + "project_id": result.ID.ValueString(), + }) + + diags = resp.State.Set(ctx, result) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} diff --git a/vercel/data_source_shared_environment_variable_test.go b/vercel/data_source_shared_environment_variable_test.go new file mode 100644 index 00000000..fad671b0 --- /dev/null +++ b/vercel/data_source_shared_environment_variable_test.go @@ -0,0 +1,82 @@ +package vercel_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAcc_SharedEnvironmentVariableDataSource(t *testing.T) { + name := acctest.RandString(16) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccSharedEnvironmentVariableDataSource(name, teamIDConfig()), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.test", "key", "test_acc_"+name), + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.test", "value", "foobar"), + resource.TestCheckTypeSetElemAttr("data.vercel_shared_environment_variable.test", "target.*", "production"), + resource.TestCheckTypeSetElemAttr("data.vercel_shared_environment_variable.test", "target.*", "preview"), + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.test", "sensitive", "false"), + + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.by_key_and_target", "key", "test_acc_"+name), + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.by_key_and_target", "value", "foobar"), + resource.TestCheckTypeSetElemAttr("data.vercel_shared_environment_variable.by_key_and_target", "target.*", "production"), + resource.TestCheckTypeSetElemAttr("data.vercel_shared_environment_variable.by_key_and_target", "target.*", "preview"), + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.by_key_and_target", "sensitive", "false"), + + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.sensitive", "key", "test_acc_"+name+"_sensitive"), + resource.TestCheckNoResourceAttr("data.vercel_shared_environment_variable.sensitive", "value"), + resource.TestCheckTypeSetElemAttr("data.vercel_shared_environment_variable.sensitive", "target.*", "production"), + resource.TestCheckResourceAttr("data.vercel_shared_environment_variable.sensitive", "sensitive", "true"), + ), + }, + }, + }) +} + +func testAccSharedEnvironmentVariableDataSource(name, teamID string) string { + return fmt.Sprintf(` +resource "vercel_project" "test" { + name = "test-acc-%[1]s" + %[2]s +} + +resource "vercel_shared_environment_variable" "test" { + key = "test_acc_%[1]s" + value = "foobar" + target = [ "production", "preview" ] + project_ids = [ vercel_project.test.id ] + %[2]s +} + +data "vercel_shared_environment_variable" "test" { + id = vercel_shared_environment_variable.test.id + %[2]s +} + +data "vercel_shared_environment_variable" "by_key_and_target" { + key = vercel_shared_environment_variable.test.key + target = vercel_shared_environment_variable.test.target + %[2]s +} + +resource "vercel_shared_environment_variable" "sensitive" { + key = "test_acc_%[1]s_sensitive" + %[2]s + value = "foobar" + target = [ "production" ] + project_ids = [ vercel_project.test.id ] + sensitive = true +} + +data "vercel_shared_environment_variable" "sensitive" { + id = vercel_shared_environment_variable.sensitive.id + %[2]s +} +`, name, teamID) +} diff --git a/vercel/provider.go b/vercel/provider.go index ebf5c3fe..de2735f1 100644 --- a/vercel/provider.go +++ b/vercel/provider.go @@ -67,6 +67,7 @@ func (p *vercelProvider) DataSources(_ context.Context) []func() datasource.Data newPrebuiltProjectDataSource, newProjectDataSource, newProjectDirectoryDataSource, + newSharedEnvironmentVariableDataSource, } } diff --git a/vercel/resource_shared_environment_variable.go b/vercel/resource_shared_environment_variable.go index 6c045753..e6093498 100644 --- a/vercel/resource_shared_environment_variable.go +++ b/vercel/resource_shared_environment_variable.go @@ -51,7 +51,7 @@ func (r *sharedEnvironmentVariableResource) Configure(ctx context.Context, req r r.client = client } -// Schema returns the schema information for a project environment variable resource. +// Schema returns the schema information for a shared environment variable resource. func (r *sharedEnvironmentVariableResource) Schema(_ context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Description: ` @@ -117,11 +117,15 @@ func (r *sharedEnvironmentVariableResource) Create(ctx context.Context, req reso return } - response, err := r.client.CreateSharedEnvironmentVariable(ctx, plan.toCreateSharedEnvironmentVariableRequest()) + request, ok := plan.toCreateSharedEnvironmentVariableRequest(ctx, resp.Diagnostics) + if !ok { + return + } + response, err := r.client.CreateSharedEnvironmentVariable(ctx, request) if err != nil { resp.Diagnostics.AddError( - "Error creating project environment variable", - "Could not create project environment variable, unexpected error: "+err.Error(), + "Error creating shared environment variable", + "Could not create shared environment variable, unexpected error: "+err.Error(), ) return } @@ -180,7 +184,7 @@ func (r *sharedEnvironmentVariableResource) Read(ctx context.Context, req resour } } -// Update updates the project environment variable of a Vercel project state. +// Update updates the shared environment variable of a Vercel project state. func (r *sharedEnvironmentVariableResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var plan SharedEnvironmentVariable diags := req.Plan.Get(ctx, &plan) @@ -188,8 +192,11 @@ func (r *sharedEnvironmentVariableResource) Update(ctx context.Context, req reso if resp.Diagnostics.HasError() { return } - - response, err := r.client.UpdateSharedEnvironmentVariable(ctx, plan.toUpdateSharedEnvironmentVariableRequest()) + request, ok := plan.toUpdateSharedEnvironmentVariableRequest(ctx, resp.Diagnostics) + if !ok { + return + } + response, err := r.client.UpdateSharedEnvironmentVariable(ctx, request) if err != nil { resp.Diagnostics.AddError( "Error updating shared environment variable", @@ -200,7 +207,7 @@ func (r *sharedEnvironmentVariableResource) Update(ctx context.Context, req reso result := convertResponseToSharedEnvironmentVariable(response, plan.Value) - tflog.Trace(ctx, "updated project environment variable", map[string]interface{}{ + tflog.Trace(ctx, "updated shared environment variable", map[string]interface{}{ "id": result.ID.ValueString(), "team_id": result.TeamID.ValueString(), }) @@ -212,7 +219,7 @@ func (r *sharedEnvironmentVariableResource) Update(ctx context.Context, req reso } } -// Delete deletes a Vercel project environment variable. +// Delete deletes a Vercel shared environment variable. func (r *sharedEnvironmentVariableResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { var state SharedEnvironmentVariable diags := req.State.Get(ctx, &state) @@ -237,7 +244,7 @@ func (r *sharedEnvironmentVariableResource) Delete(ctx context.Context, req reso return } - tflog.Trace(ctx, "deleted project environment variable", map[string]interface{}{ + tflog.Trace(ctx, "deleted shared environment variable", map[string]interface{}{ "id": state.ID.ValueString(), "team_id": state.TeamID.ValueString(), }) @@ -254,7 +261,7 @@ func splitSharedEnvironmentVariableID(id string) (teamID, envID string, ok bool) return "", "", false } -// ImportState takes an identifier and reads all the project environment variable information from the Vercel API. +// ImportState takes an identifier and reads all the shared environment variable information from the Vercel API. // The results are then stored in terraform state. func (r *sharedEnvironmentVariableResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { teamID, envID, ok := splitSharedEnvironmentVariableID(req.ID) diff --git a/vercel/resource_shared_environment_variable_model.go b/vercel/resource_shared_environment_variable_model.go index 83bb83b7..4e429199 100644 --- a/vercel/resource_shared_environment_variable_model.go +++ b/vercel/resource_shared_environment_variable_model.go @@ -1,29 +1,38 @@ package vercel import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/vercel/terraform-provider-vercel/client" ) // SharedEnvironmentVariable reflects the state terraform stores internally for a project environment variable. type SharedEnvironmentVariable struct { - Target []types.String `tfsdk:"target"` - Key types.String `tfsdk:"key"` - Value types.String `tfsdk:"value"` - TeamID types.String `tfsdk:"team_id"` - ProjectIDs []types.String `tfsdk:"project_ids"` - ID types.String `tfsdk:"id"` - Sensitive types.Bool `tfsdk:"sensitive"` + Target types.Set `tfsdk:"target"` + Key types.String `tfsdk:"key"` + Value types.String `tfsdk:"value"` + TeamID types.String `tfsdk:"team_id"` + ProjectIDs types.Set `tfsdk:"project_ids"` + ID types.String `tfsdk:"id"` + Sensitive types.Bool `tfsdk:"sensitive"` } -func (e *SharedEnvironmentVariable) toCreateSharedEnvironmentVariableRequest() client.CreateSharedEnvironmentVariableRequest { - target := []string{} - for _, t := range e.Target { - target = append(target, t.ValueString()) +func (e *SharedEnvironmentVariable) toCreateSharedEnvironmentVariableRequest(ctx context.Context, diags diag.Diagnostics) (req client.CreateSharedEnvironmentVariableRequest, ok bool) { + var target []string + ds := e.Target.ElementsAs(ctx, &target, false) + diags = append(diags, ds...) + if diags.HasError() { + return req, false } - projectIDs := []string{} - for _, t := range e.ProjectIDs { - projectIDs = append(projectIDs, t.ValueString()) + + var projectIDs []string + ds = e.ProjectIDs.ElementsAs(ctx, &projectIDs, false) + diags = append(diags, ds...) + if diags.HasError() { + return req, false } var envVariableType string @@ -47,17 +56,22 @@ func (e *SharedEnvironmentVariable) toCreateSharedEnvironmentVariableRequest() c }, }, TeamID: e.TeamID.ValueString(), - } + }, true } -func (e *SharedEnvironmentVariable) toUpdateSharedEnvironmentVariableRequest() client.UpdateSharedEnvironmentVariableRequest { - target := []string{} - for _, t := range e.Target { - target = append(target, t.ValueString()) +func (e *SharedEnvironmentVariable) toUpdateSharedEnvironmentVariableRequest(ctx context.Context, diags diag.Diagnostics) (req client.UpdateSharedEnvironmentVariableRequest, ok bool) { + var target []string + ds := e.Target.ElementsAs(ctx, &target, false) + diags = append(diags, ds...) + if diags.HasError() { + return req, false } - projectIDs := []string{} - for _, t := range e.ProjectIDs { - projectIDs = append(projectIDs, t.ValueString()) + + var projectIDs []string + ds = e.ProjectIDs.ElementsAs(ctx, &projectIDs, false) + diags = append(diags, ds...) + if diags.HasError() { + return req, false } var envVariableType string @@ -73,21 +87,21 @@ func (e *SharedEnvironmentVariable) toUpdateSharedEnvironmentVariableRequest() c TeamID: e.TeamID.ValueString(), EnvID: e.ID.ValueString(), ProjectIDs: projectIDs, - } + }, true } // convertResponseToSharedEnvironmentVariable is used to populate terraform state based on an API response. // Where possible, values from the API response are used to populate state. If not possible, // values from plan are used. func convertResponseToSharedEnvironmentVariable(response client.SharedEnvironmentVariableResponse, v types.String) SharedEnvironmentVariable { - target := []types.String{} + target := []attr.Value{} for _, t := range response.Target { target = append(target, types.StringValue(t)) } - project_ids := []types.String{} + projectIDs := []attr.Value{} for _, t := range response.ProjectIDs { - project_ids = append(project_ids, types.StringValue(t)) + projectIDs = append(projectIDs, types.StringValue(t)) } value := types.StringValue(response.Value) @@ -96,10 +110,10 @@ func convertResponseToSharedEnvironmentVariable(response client.SharedEnvironmen } return SharedEnvironmentVariable{ - Target: target, + Target: types.SetValueMust(types.StringType, target), Key: types.StringValue(response.Key), Value: value, - ProjectIDs: project_ids, + ProjectIDs: types.SetValueMust(types.StringType, projectIDs), TeamID: toTeamID(response.TeamID), ID: types.StringValue(response.ID), Sensitive: types.BoolValue(response.Type == "sensitive"),