From b15c0fe1eb8ce48be2a6ba63bdcf6c585a0cefe0 Mon Sep 17 00:00:00 2001 From: Lakshmi Javadekar <103459615+lakshmimsft@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:26:10 -0800 Subject: [PATCH] Add support to set environment variables to Terraform environment (#7192) # Description Added a function to set environment variables to the Terraform process. This function reads user provided configuration from the RecipeConfig/EnvVariables section of the Radius environment configuration and is invoked during the setup phase for Terraform deployment. [link to PR for design doc](https://github.com/radius-project/design-notes/pull/39) The design document describes a SecretReference type and ability to fetch data from secrets and set environment variables. This will be implemented in subsequent PRs. ## Type of change - This pull request adds or changes features of Radius and has an approved issue #6539 Fixes: Part of #6539 --------- Signed-off-by: Vishwanath Hiremath Co-authored-by: Vishwanath Hiremath <100623239+vishwahiremat@users.noreply.github.com> --- pkg/recipes/terraform/execute.go | 24 +++++++++++ pkg/recipes/terraform/execute_test.go | 59 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/pkg/recipes/terraform/execute.go b/pkg/recipes/terraform/execute.go index 248d4fa1c7..270429b694 100644 --- a/pkg/recipes/terraform/execute.go +++ b/pkg/recipes/terraform/execute.go @@ -88,6 +88,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 + } + // Run TF Init and Apply in the working directory state, err := initAndApply(ctx, tf) if err != nil { @@ -194,6 +200,24 @@ 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. +// 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{} + + for key, value := range envConfig.RecipeConfig.Env.AdditionalProperties { + envVars[key] = value + } + + if err := tf.SetEnv(envVars); err != nil { + return fmt.Errorf("failed to set environment variables: %w", err) + } + } + + return nil +} + // 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 87e54e8e37..431cbf3679 100644 --- a/pkg/recipes/terraform/execute_test.go +++ b/pkg/recipes/terraform/execute_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/hashicorp/terraform-exec/tfexec" + dm "github.com/radius-project/radius/pkg/corerp/datamodel" "github.com/radius-project/radius/pkg/recipes" "github.com/radius-project/radius/pkg/recipes/terraform/config" "github.com/radius-project/radius/test/testcontext" @@ -114,3 +115,61 @@ func Test_GetTerraformConfig_InvalidDirectory(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "error creating file: open invalid-directory/main.tf.json: no such file or directory") } + +func TestSetEnvironmentVariables(t *testing.T) { + testCase := []struct { + name string + opts Options + }{ + { + name: "set environment variables", + opts: Options{ + EnvConfig: &recipes.Configuration{ + RecipeConfig: dm.RecipeConfigProperties{ + Env: dm.EnvironmentVariables{ + AdditionalProperties: map[string]string{ + "TEST_ENV_VAR1": "value1", + "TEST_ENV_VAR2": "value2", + }, + }, + }, + }, + }, + }, + { + name: "AdditionalProperties set to nil", + opts: Options{ + EnvConfig: &recipes.Configuration{ + RecipeConfig: dm.RecipeConfigProperties{ + Env: dm.EnvironmentVariables{ + AdditionalProperties: nil, + }, + }, + }, + }, + }, + { + name: "no environment variables", + opts: Options{ + EnvConfig: &recipes.Configuration{ + RecipeConfig: dm.RecipeConfigProperties{}, + }, + }, + }, + } + + for _, tc := range testCase { + t.Run(tc.name, func(t *testing.T) { + ctx := testcontext.New(t) + workingDir := t.TempDir() + + tf, err := tfexec.NewTerraform(workingDir, filepath.Join(workingDir, "terraform")) + require.NoError(t, err) + + e := executor{} + + err = e.setEnvironmentVariables(ctx, tf, tc.opts.EnvConfig) + require.NoError(t, err) + }) + } +}