diff --git a/client/configuration_variable.go b/client/configuration_variable.go index 77d6e462..67074798 100644 --- a/client/configuration_variable.go +++ b/client/configuration_variable.go @@ -41,7 +41,7 @@ func (c *ConfigurationVariableSchema) ResourceDataSliceStructValueWrite(values m type ConfigurationVariable struct { ScopeId string `json:"scopeId,omitempty"` - Value string `json:"value"` + Value string `json:"value" tfschema:"-"` OrganizationId string `json:"organizationId,omitempty"` UserId string `json:"userId,omitempty"` IsSensitive *bool `json:"isSensitive,omitempty"` diff --git a/env0/data_configuration_variable.go b/env0/data_configuration_variable.go index b3383104..d1f7d0ad 100644 --- a/env0/data_configuration_variable.go +++ b/env0/data_configuration_variable.go @@ -136,6 +136,10 @@ func dataConfigurationVariableRead(ctx context.Context, d *schema.ResourceData, return diag.Errorf("schema resource data serialization failed: %v", err) } + if variable.IsSensitive == nil || !*variable.IsSensitive { + d.Set("value", variable.Value) + } + d.Set("enum", variable.Schema.Enum) if variable.Schema.Format != client.Text { diff --git a/env0/data_source_code_variables.go b/env0/data_source_code_variables.go index f180b7b3..c265302b 100644 --- a/env0/data_source_code_variables.go +++ b/env0/data_source_code_variables.go @@ -76,10 +76,20 @@ func dataSourceCodeVariablesRead(ctx context.Context, d *schema.ResourceData, me return diag.Errorf("failed to extract variables from repository: %v", err) } - if err := writeResourceDataSlice(variables, "variables", d); err != nil { + ivalues, err := writeResourceDataGetSliceValues(variables, "variables", d) + if err != nil { return diag.Errorf("schema slice resource data serialization failed: %v", err) } + for i, ivalue := range ivalues { + if variables[i].IsSensitive == nil || !*variables[i].IsSensitive { + ivariable := ivalue.(map[string]interface{}) + ivariable["value"] = variables[i].Value + } + } + + d.Set("variables", ivalues) + d.SetId(templateId) return nil diff --git a/env0/resource_configuration_variable.go b/env0/resource_configuration_variable.go index f3c05b67..6122c9f1 100644 --- a/env0/resource_configuration_variable.go +++ b/env0/resource_configuration_variable.go @@ -170,7 +170,7 @@ func getConfigurationVariableCreateParams(d *schema.ResourceData) (*client.Confi func resourceConfigurationVariableCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { params, err := getConfigurationVariableCreateParams(d) if err != nil { - return diag.Errorf(err.Error()) + return diag.FromErr(err) } apiClient := meta.(client.ApiClientInterface) @@ -195,7 +195,9 @@ func getEnum(d *schema.ResourceData, selectedValue string) ([]string, error) { if enumValue == nil { return nil, fmt.Errorf("an empty enum value is not allowed (at index %d)", i) } + actualEnumValues = append(actualEnumValues, enumValue.(string)) + if enumValue == selectedValue { valueExists = true } @@ -223,13 +225,17 @@ func resourceConfigurationVariableRead(ctx context.Context, d *schema.ResourceDa return diag.Errorf("schema resource data serialization failed: %v", err) } + if variable.IsSensitive == nil || !*variable.IsSensitive { + d.Set("value", variable.Value) + } + return nil } func resourceConfigurationVariableUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { params, err := getConfigurationVariableCreateParams(d) if err != nil { - return diag.Errorf(err.Error()) + return diag.FromErr(err) } apiClient := meta.(client.ApiClientInterface) @@ -280,7 +286,7 @@ func resourceConfigurationVariableImport(ctx context.Context, d *schema.Resource var scopeName string if variable.Scope == client.ScopeTemplate { - scopeName = strings.ToLower(fmt.Sprintf("%s_id", templateScope)) + scopeName = strings.ToLower(templateScope + "_id") } else { scopeName = strings.ToLower(fmt.Sprintf("%s_id", variable.Scope)) } diff --git a/env0/resource_configuration_variable_test.go b/env0/resource_configuration_variable_test.go index 26613e2e..063d7512 100644 --- a/env0/resource_configuration_variable_test.go +++ b/env0/resource_configuration_variable_test.go @@ -11,6 +11,7 @@ import ( "github.com/env0/terraform-provider-env0/client" "github.com/env0/terraform-provider-env0/client/http" + "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "go.uber.org/mock/gomock" ) @@ -50,6 +51,7 @@ func TestUnitConfigurationVariableResource(t *testing.T) { IsRequired: *configVar.IsRequired, IsReadOnly: *configVar.IsReadOnly, } + t.Run("Create", func(t *testing.T) { createTestCase := resource.TestCase{ Steps: []resource.TestStep{ @@ -74,6 +76,47 @@ func TestUnitConfigurationVariableResource(t *testing.T) { }) }) + t.Run("Create sensitive", func(t *testing.T) { + createSenstiveConfig := client.ConfigurationVariableCreateParams{ + Name: "name", + Value: "value", + IsSensitive: true, + Scope: client.ScopeGlobal, + } + + sensitiveConfig := client.ConfigurationVariable{ + Id: uuid.NewString(), + Name: createSenstiveConfig.Name, + Value: "*", + IsSensitive: boolPtr(true), + Scope: client.ScopeGlobal, + } + + createTestCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "name": createSenstiveConfig.Name, + "value": createSenstiveConfig.Value, + "is_sensitive": true, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(accessor, "id", sensitiveConfig.Id), + resource.TestCheckResourceAttr(accessor, "name", createSenstiveConfig.Name), + resource.TestCheckResourceAttr(accessor, "value", createSenstiveConfig.Value), + resource.TestCheckResourceAttr(accessor, "is_sensitive", strconv.FormatBool(true)), + ), + }, + }, + } + + runUnitTest(t, createTestCase, func(mock *client.MockApiClientInterface) { + mock.EXPECT().ConfigurationVariableCreate(createSenstiveConfig).Times(1).Return(sensitiveConfig, nil) + mock.EXPECT().ConfigurationVariablesById(sensitiveConfig.Id).Times(1).Return(sensitiveConfig, nil) + mock.EXPECT().ConfigurationVariableDelete(sensitiveConfig.Id).Times(1).Return(nil) + }) + }) + t.Run("Create Two with readonly", func(t *testing.T) { // https://github.com/env0/terraform-provider-env0/issues/215 // we want to create two variables, one org level with read only and another in lower level and see we can still manage both - double apply and destroy @@ -286,7 +329,6 @@ resource "{{.resourceType}}" "{{.projResourceName}}" { for _, format := range []client.Format{client.HCL, client.JSON} { t.Run("Create "+string(format)+" Variable", func(t *testing.T) { - expectedVariable := `{ A = "A" B = "B" @@ -627,8 +669,8 @@ resource "%s" "test" { IsRequired: *configVarImport.IsRequired, IsReadOnly: *configVarImport.IsReadOnly, } - t.Run("import by name", func(t *testing.T) { + t.Run("import by name", func(t *testing.T) { createTestCaseForImport := resource.TestCase{ Steps: []resource.TestStep{ { @@ -653,7 +695,6 @@ resource "%s" "test" { }) t.Run("import by id", func(t *testing.T) { - createTestCaseForImport := resource.TestCase{ Steps: []resource.TestStep{ { diff --git a/env0/utils_test.go b/env0/utils_test.go index ab8f3967..21f93d05 100644 --- a/env0/utils_test.go +++ b/env0/utils_test.go @@ -177,7 +177,6 @@ func TestWriteCustomResourceData(t *testing.T) { Name: "name0", Description: "desc0", ScopeId: "scope0", - Value: "value0", OrganizationId: "organization0", UserId: "user0", IsSensitive: boolPtr(true), @@ -196,7 +195,6 @@ func TestWriteCustomResourceData(t *testing.T) { assert.Equal(t, configurationVariable.Name, d.Get("name")) assert.Equal(t, configurationVariable.Description, d.Get("description")) assert.Equal(t, "terraform", d.Get("type")) - assert.Equal(t, configurationVariable.Value, d.Get("value")) assert.Equal(t, string(configurationVariable.Scope), d.Get("scope")) assert.Equal(t, *configurationVariable.IsReadOnly, d.Get("is_read_only")) assert.Equal(t, *configurationVariable.IsRequired, d.Get("is_required")) @@ -287,7 +285,6 @@ func TestWriteResourceDataSliceVariablesConfigurationVariable(t *testing.T) { Id: "id0", Name: "name0", Description: "desc0", - Value: "v1", Schema: &schema1, } @@ -295,7 +292,6 @@ func TestWriteResourceDataSliceVariablesConfigurationVariable(t *testing.T) { Id: "id1", Name: "name1", Description: "desc1", - Value: "v2", Schema: &schema2, } @@ -305,8 +301,6 @@ func TestWriteResourceDataSliceVariablesConfigurationVariable(t *testing.T) { assert.Equal(t, var1.Name, d.Get("variables.0.name")) assert.Equal(t, var2.Name, d.Get("variables.1.name")) - assert.Equal(t, var1.Value, d.Get("variables.0.value")) - assert.Equal(t, var2.Value, d.Get("variables.1.value")) assert.Equal(t, string(var1.Schema.Format), d.Get("variables.0.format")) assert.Equal(t, string(var2.Schema.Format), d.Get("variables.1.format")) } diff --git a/tests/harness.go b/tests/harness.go index 677077df..7d8c6eda 100644 --- a/tests/harness.go +++ b/tests/harness.go @@ -39,7 +39,7 @@ func main() { } else { success, err := runTest(testName, destroyMode != "NO_DESTROY") if !success { - log.Fatalf("Halting due to test '%s' failure: %s\n", testName, err.Error()) + log.Fatalf("Halting due to test '%s' failure: %s\n", testName, err) } }