From bc202204e7aaa41ce4d1d6313b4108f2d883f7fb Mon Sep 17 00:00:00 2001 From: Vishwanath Hiremath <100623239+vishwahiremat@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:03:02 -0800 Subject: [PATCH] Adding support for terraform private module source for git (#7167) - Added a RecipeConfig property to the environment - Typesspec changes - Conversion and unit tests - Datamodel changes - Adding changes to the config to append the template path with credential informaiton - changes to query list secret to get secret information - creating credential appended template path Design Doc: https://github.com/radius-project/design-notes/pull/37 - This pull request adds or changes features of Radius and has an approved issue (issue link required). - This pull request is a minor refactor, code cleanup, test improvement, or other maintenance task and doesn't change the functionality of Radius (issue link optional). Fixes: https://github.com/radius-project/radius/issues/6911 --------- Signed-off-by: Vishwanath Hiremath --- pkg/recipes/terraform/execute.go | 26 ++++++++++++ pkg/recipes/terraform/execute_test.go | 61 +++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/pkg/recipes/terraform/execute.go b/pkg/recipes/terraform/execute.go index 248d4fa1c79..a905451f740 100644 --- a/pkg/recipes/terraform/execute.go +++ b/pkg/recipes/terraform/execute.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "os" "time" install "github.com/hashicorp/hc-install" @@ -88,6 +89,13 @@ func (e *executor) Deploy(ctx context.Context, options Options) (*tfjson.State, return nil, err } + // Set environment variables for the Terraform process reading input from the environment configuration. + // This is required for the Terraform process to read the environment variables and use them as input for the recipe deployment. + err = e.setEnvironmentVariables(ctx, 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 +202,24 @@ func (e *executor) GetRecipeMetadata(ctx context.Context, options Options) (map[ }, nil } +// setEnvironmentVariables sets environment variables for the Terraform process reading input from the environment configuration. +func (e executor) setEnvironmentVariables(ctx context.Context, envConfig *recipes.Configuration) error { + logger := ucplog.FromContextOrDiscard(ctx) + + // Set environment variables for the Terraform process reading input from the environment configuration. + // This is required for the Terraform process to read the environment variables and use them as input for the recipe deployment. + if envConfig != nil && envConfig.RecipeConfig.EnvVars.AdditionalProperties != nil { + for key, value := range envConfig.RecipeConfig.EnvVars.AdditionalProperties { + if err := os.Setenv(key, value); err != nil { + logger.Info(fmt.Sprintf("Failed to set environment variable %s: %s", key, err.Error())) + return fmt.Errorf("error setting environment variable %s: %w", key, 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 87e54e8e37c..6e492a45020 100644 --- a/pkg/recipes/terraform/execute_test.go +++ b/pkg/recipes/terraform/execute_test.go @@ -17,10 +17,12 @@ limitations under the License. package terraform import ( + "os" "path/filepath" "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 +116,62 @@ 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{ + EnvVars: dm.EnvironmentVariables{ + AdditionalProperties: map[string]string{ + "TEST_ENV_VAR1": "value1", + "TEST_ENV_VAR2": "value2", + }, + }, + }, + }, + }, + }, + { + 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) + + // Get the environment variables to set + envVars := tc.opts.EnvConfig.RecipeConfig.EnvVars.AdditionalProperties + + // Create an executor + e := executor{} + + // Check that the environment variables are not set + for key, expectedValue := range envVars { + err := os.Unsetenv(key) + require.NoError(t, err) + + // Call the function to set environment variables + err = e.setEnvironmentVariables(ctx, tc.opts.EnvConfig) + require.NoError(t, err) + + actualValue, ok := os.LookupEnv(key) + require.True(t, ok) + require.Equal(t, expectedValue, actualValue) + + // Ensure the environment variable is unset after the test execution + defer os.Unsetenv(key) + } + }) + } +}