diff --git a/pkg/recipes/terraform/execute.go b/pkg/recipes/terraform/execute.go index 18cf5c1f90..232b548bda 100644 --- a/pkg/recipes/terraform/execute.go +++ b/pkg/recipes/terraform/execute.go @@ -20,11 +20,14 @@ import ( "context" "errors" "fmt" + "os" + "strings" "time" install "github.com/hashicorp/hc-install" "github.com/hashicorp/terraform-exec/tfexec" tfjson "github.com/hashicorp/terraform-json" + "github.com/radius-project/radius/pkg/corerp/datamodel" "github.com/radius-project/radius/pkg/metrics" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/recipecontext" @@ -88,10 +91,12 @@ func (e *executor) Deploy(ctx context.Context, options Options) (*tfjson.State, return nil, err } - // Set environment variables for the Terraform process. - err = e.setEnvironmentVariables(ctx, tf, options.EnvConfig) - if err != nil { - return nil, err + if options.EnvConfig != nil { + // Set environment variables for the Terraform process. + err = e.setEnvironmentVariables(ctx, tf, &options.EnvConfig.RecipeConfig) + if err != nil { + return nil, err + } } // Run TF Init and Apply in the working directory @@ -200,13 +205,14 @@ func (e *executor) GetRecipeMetadata(ctx context.Context, options Options) (map[ }, nil } -// setEnvironmentVariables sets environment variables for the Terraform process by reading values from the environment configuration. +// setEnvironmentVariables sets environment variables for the Terraform process by reading values from the recipe configuration. // Terraform process will use environment variables as input for the recipe deployment. -func (e executor) setEnvironmentVariables(ctx context.Context, tf *tfexec.Terraform, envConfig *recipes.Configuration) error { - if envConfig != nil && envConfig.RecipeConfig.Env.AdditionalProperties != nil { - envVars := map[string]string{} +func (e executor) setEnvironmentVariables(ctx context.Context, tf *tfexec.Terraform, recipeConfig *datamodel.RecipeConfigProperties) error { + if recipeConfig != nil && recipeConfig.Env.AdditionalProperties != nil && len(recipeConfig.Env.AdditionalProperties) > 0 { + // populate envVars with the environment variables from current process + envVars := splitEnvVar(os.Environ()) - for key, value := range envConfig.RecipeConfig.Env.AdditionalProperties { + for key, value := range recipeConfig.Env.AdditionalProperties { envVars[key] = value } @@ -218,6 +224,19 @@ func (e executor) setEnvironmentVariables(ctx context.Context, tf *tfexec.Terraf return nil } +// splitEnvVar splits a slice of environment variables into a map of keys and values. +func splitEnvVar(envVars []string) map[string]string { + parsedEnvVars := make(map[string]string) + for _, item := range envVars { + splits := strings.SplitN(item, "=", 2) // Split on the first "=" + if len(splits) == 2 { + parsedEnvVars[splits[0]] = splits[1] + } + } + + return parsedEnvVars +} + // generateConfig generates Terraform configuration with required inputs for the module, providers and backend to be initialized and applied. func (e *executor) generateConfig(ctx context.Context, tf *tfexec.Terraform, options Options) (string, error) { logger := ucplog.FromContextOrDiscard(ctx) diff --git a/pkg/recipes/terraform/execute_test.go b/pkg/recipes/terraform/execute_test.go index 431cbf3679..2baa02243d 100644 --- a/pkg/recipes/terraform/execute_test.go +++ b/pkg/recipes/terraform/execute_test.go @@ -18,6 +18,7 @@ package terraform import ( "path/filepath" + reflect "reflect" "testing" "github.com/hashicorp/terraform-exec/tfexec" @@ -168,8 +169,56 @@ func TestSetEnvironmentVariables(t *testing.T) { e := executor{} - err = e.setEnvironmentVariables(ctx, tf, tc.opts.EnvConfig) + err = e.setEnvironmentVariables(ctx, tf, &tc.opts.EnvConfig.RecipeConfig) + require.NoError(t, err) }) } } + +func TestSplitEnvVar(t *testing.T) { + tests := []struct { + name string + envVars []string + want map[string]string + }{ + { + name: "nil input", + envVars: nil, + want: map[string]string{}, + }, + { + name: "empty input", + envVars: []string{}, + want: map[string]string{}, + }, + { + name: "single variable", + envVars: []string{"VAR1=value1"}, + want: map[string]string{"VAR1": "value1"}, + }, + { + name: "multiple variables", + envVars: []string{"VAR1=value1", "VAR2=value2"}, + want: map[string]string{"VAR1": "value1", "VAR2": "value2"}, + }, + { + name: "variable with no value", + envVars: []string{"VAR1="}, + want: map[string]string{"VAR1": ""}, + }, + { + name: "variable with equals sign in value", + envVars: []string{"VAR1=value1=value2"}, + want: map[string]string{"VAR1": "value1=value2"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := splitEnvVar(tt.envVars); !reflect.DeepEqual(got, tt.want) { + t.Errorf("splitEnvVar() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/test/functional/shared/resources/testdata/corerp-resources-terraform-redis.bicep b/test/functional/shared/resources/testdata/corerp-resources-terraform-redis.bicep index e810ade66d..a5619fd0af 100644 --- a/test/functional/shared/resources/testdata/corerp-resources-terraform-redis.bicep +++ b/test/functional/shared/resources/testdata/corerp-resources-terraform-redis.bicep @@ -17,6 +17,12 @@ resource env 'Applications.Core/environments@2023-10-01-preview' = { resourceId: 'self' namespace: 'corerp-resources-terraform-redis-env' } + recipeConfig: { + env: { + MY_ENV_VAR_1: 'env-var-value-1' + MY_ENV_VAR_2: 'env-var-value-2' + } + } recipes: { 'Applications.Core/extenders': { default: {