Skip to content

Commit

Permalink
rebase cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
lakshmimsft committed Feb 26, 2024
1 parent 96370be commit 0a7d6a8
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 99 deletions.
35 changes: 22 additions & 13 deletions pkg/recipes/terraform/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ func (cfg *TerraformConfig) Save(ctx context.Context, workingDir string) error {
// by Radius to generate custom provider configurations. Save() must be called to save
// the generated providers config. requiredProviders contains a list of provider names
// that are required for the module.
func (cfg *TerraformConfig) AddProviders(ctx context.Context, requiredProviders []string, ucpSupportedProviders map[string]providers.Provider, envConfig *recipes.Configuration) error {
providerConfigs, err := getProviderConfigs(ctx, requiredProviders, ucpSupportedProviders, envConfig)
func (cfg *TerraformConfig) AddProviders(ctx context.Context, requiredProviders []string, ucpConfiguredProviders map[string]providers.Provider, envConfig *recipes.Configuration) error {
providerConfigs, err := getProviderConfigs(ctx, requiredProviders, ucpConfiguredProviders, envConfig)
if err != nil {
return err
}
Expand Down Expand Up @@ -165,21 +165,21 @@ func newModuleConfig(moduleSource string, moduleVersion string, params ...Recipe
return moduleConfig
}

// getProviderConfigs generates the Terraform provider configurations for the required providers.
func getProviderConfigs(ctx context.Context, requiredProviders []string, ucpSupportedProviders map[string]providers.Provider, envConfig *recipes.Configuration) (map[string]any, error) {
providerConfigs := make(map[string]any)

// getProviderConfigs generates the Terraform provider configurations. This is built from a combination of environment level recipe configuration for
// providers and the provider configurations registered with UCP. The environment level recipe configuration for providers takes precedence over UCP provider configurations.
func getProviderConfigs(ctx context.Context, requiredProviders []string, ucpConfiguredProviders map[string]providers.Provider, envConfig *recipes.Configuration) (map[string]any, error) {
// Get recipe provider configurations from the environment configuration
providerConfigs = getRecipeProviderConfigs(ctx, envConfig)
providerConfigs := getRecipeProviderConfigs(ctx, envConfig)

// Build provider configurations for required providers excluding the ones already present in providerConfigs
for _, provider := range requiredProviders {
if _, ok := providerConfigs[provider]; ok {
// If provider is in providerConfigs, skip this iteration
// Environment level recipe configuration for providers will take precedence over
// UCP provider configuration (currently these include azurerm, aws, kubernetes providers)
continue
}

builder, ok := ucpSupportedProviders[provider]
builder, ok := ucpConfiguredProviders[provider]
if !ok {
// No-op: For any other provider under required_providers, Radius doesn't generate any custom configuration.
continue
Expand All @@ -189,7 +189,6 @@ func getProviderConfigs(ctx context.Context, requiredProviders []string, ucpSupp
if err != nil {
return nil, err
}

if len(config) > 0 {
providerConfigs[provider] = config
}
Expand All @@ -198,15 +197,25 @@ func getProviderConfigs(ctx context.Context, requiredProviders []string, ucpSupp
return providerConfigs, nil
}

// getRecipeProviderConfigs returns the Terraform provider configurations for Terraform providers.
// getRecipeProviderConfigs returns the Terraform provider configurations for Terraform providers
// specified under the RecipeConfig/Terraform/Providers section under environment configuration.
func getRecipeProviderConfigs(ctx context.Context, envConfig *recipes.Configuration) map[string]any {
providerConfigs := make(map[string]any)

// If the provider is not configured, or has empty configuration, skip this iteration
if envConfig.RecipeConfig.Terraform.Providers != nil {
if envConfig != nil && envConfig.RecipeConfig.Terraform.Providers != nil {
for provider, config := range envConfig.RecipeConfig.Terraform.Providers {
if len(config) > 0 {
providerConfigs[provider] = config
configList := make([]any, 0)

for _, configDetails := range config {
//for _, additionalProperty := range configDetails.AdditionalProperties {
// configList = append(configList, additionalProperty)
//}
configList = append(configList, configDetails.AdditionalProperties)
}

providerConfigs[provider] = configList
}
}
}
Expand Down
101 changes: 48 additions & 53 deletions pkg/recipes/terraform/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package config

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -330,7 +331,7 @@ func Test_AddRecipeContext(t *testing.T) {
}

func Test_AddProviders(t *testing.T) {
mProvider, supportedUCPProviders, mBackend := setup(t)
mProvider, ucpConfiguredProviders, mBackend := setup(t)
envRecipe, resourceRecipe := getTestInputs()
expectedBackend := map[string]any{
"kubernetes": map[string]any{
Expand All @@ -341,17 +342,16 @@ func Test_AddProviders(t *testing.T) {
}

configTests := []struct {
desc string
envConfig recipes.Configuration
requiredProviders []string
expectedUCPSupportedProviders []map[string]any
expectedConfigFile string
Err error
times int
desc string
envConfig recipes.Configuration
requiredProviders []string
expectedUCPConfiguredProviders []map[string]any
expectedConfigFile string
Err error
}{
{
desc: "valid all supported providers",
expectedUCPSupportedProviders: []map[string]any{
expectedUCPConfiguredProviders: []map[string]any{
{
"region": "test-region",
},
Expand Down Expand Up @@ -380,13 +380,12 @@ func Test_AddProviders(t *testing.T) {
providers.KubernetesProviderName,
"sql",
},
times: 1,
expectedConfigFile: "testdata/providers-valid.tf.json",
},
/*{
desc: "invalid aws scope",
expectedUCPSupportedProviders: nil,
Err: errors.New("Invalid AWS provider scope"),
{
desc: "invalid aws scope",
expectedUCPConfiguredProviders: nil,
Err: errors.New("Invalid AWS provider scope"),
envConfig: recipes.Configuration{
Providers: datamodel.Providers{
AWS: datamodel.ProvidersAWS{
Expand All @@ -397,24 +396,22 @@ func Test_AddProviders(t *testing.T) {
requiredProviders: []string{
providers.AWSProviderName,
},
times: 1,
},
{
desc: "empty aws provider config",
expectedUCPSupportedProviders: []map[string]any{
expectedUCPConfiguredProviders: []map[string]any{
{},
},
Err: nil,
envConfig: recipes.Configuration{},
requiredProviders: []string{
providers.AWSProviderName,
},
times: 1,
expectedConfigFile: "testdata/providers-empty.tf.json",
},
{
desc: "empty aws scope",
expectedUCPSupportedProviders: []map[string]any{
expectedUCPConfiguredProviders: []map[string]any{
nil,
},
Err: nil,
Expand All @@ -431,12 +428,11 @@ func Test_AddProviders(t *testing.T) {
requiredProviders: []string{
providers.AWSProviderName,
},
times: 1,
expectedConfigFile: "testdata/providers-empty.tf.json",
},
{
desc: "empty azure provider config",
expectedUCPSupportedProviders: []map[string]any{
expectedUCPConfiguredProviders: []map[string]any{
{
"features": map[string]any{},
},
Expand All @@ -446,13 +442,12 @@ func Test_AddProviders(t *testing.T) {
requiredProviders: []string{
providers.AzureProviderName,
},
times: 1,
expectedConfigFile: "testdata/providers-emptyazureconfig.tf.json",
},
{
desc: "valid recipe providers",
expectedUCPSupportedProviders: nil,
Err: nil,
desc: "valid recipe providers in env config",
expectedUCPConfiguredProviders: nil,
Err: nil,
envConfig: recipes.Configuration{
RecipeConfig: datamodel.RecipeConfigProperties{
Terraform: datamodel.TerraformConfigProperties{
Expand All @@ -477,18 +472,14 @@ func Test_AddProviders(t *testing.T) {
},
},
requiredProviders: nil,
times: 1,
expectedConfigFile: "testdata/providers-envrecipeproviders.tf.json",
},
{
desc: "overridding required provider configs",
expectedUCPSupportedProviders: []map[string]any{
desc: "recipe provider config overridding required provider configs",
expectedUCPConfiguredProviders: []map[string]any{
{
"region": "test-region",
},
{
"config_path": "/home/radius/.kube/config",
},
},
Err: nil,
envConfig: recipes.Configuration{
Expand All @@ -515,57 +506,61 @@ func Test_AddProviders(t *testing.T) {
providers.AWSProviderName,
providers.KubernetesProviderName,
},
times: -1,
expectedConfigFile: "testdata/providers-overridereqproviders.tf.json",
},
{
desc: "recipe providers not populated",
expectedUCPSupportedProviders: nil,
Err: nil,
desc: "recipe providers not populated",
expectedUCPConfiguredProviders: nil,
Err: nil,
envConfig: recipes.Configuration{
RecipeConfig: datamodel.RecipeConfigProperties{
Terraform: datamodel.TerraformConfigProperties{},
},
},
requiredProviders: nil,
times: 1,
expectedConfigFile: "testdata/providers-empty.tf.json",
},
{
desc: "recipe providers not populated",
expectedUCPSupportedProviders: nil,
Err: nil,
desc: "recipe providers and tfconfigproperties not populated",
expectedUCPConfiguredProviders: nil,
Err: nil,
envConfig: recipes.Configuration{
RecipeConfig: datamodel.RecipeConfigProperties{},
},
requiredProviders: nil,
times: 1,
expectedConfigFile: "testdata/providers-empty.tf.json",
},*/
},
{
desc: "envConfig set to empty recipe config",
expectedUCPConfiguredProviders: nil,
Err: nil,
envConfig: recipes.Configuration{},
requiredProviders: nil,
expectedConfigFile: "testdata/providers-empty.tf.json",
},
{
desc: "envConfig not populated",
expectedUCPConfiguredProviders: nil,
Err: nil,
requiredProviders: nil,
expectedConfigFile: "testdata/providers-empty.tf.json",
},
}

for _, tc := range configTests {
t.Run(tc.desc, func(t *testing.T) {
ctx := testcontext.New(t)
workingDir := t.TempDir()

tfconfig, err := New(ctx, testRecipeName, &envRecipe, nil, &tc.envConfig)
tfconfig, err := New(ctx, testRecipeName, &envRecipe, &resourceRecipe, &tc.envConfig)
require.NoError(t, err)
for _, p := range tc.expectedUCPSupportedProviders {
if tc.times > 0 {
mProvider.EXPECT().BuildConfig(ctx, &tc.envConfig).Times(tc.times).Return(p, nil)
} else {
mProvider.EXPECT().BuildConfig(ctx, &tc.envConfig).Return(p, tc.Err).AnyTimes()
}
for _, p := range tc.expectedUCPConfiguredProviders {
mProvider.EXPECT().BuildConfig(ctx, &tc.envConfig).Times(1).Return(p, nil)
}
if tc.Err != nil {
if tc.times > 0 {
mProvider.EXPECT().BuildConfig(ctx, &tc.envConfig).Times(1).Return(nil, tc.Err)
} else {
mProvider.EXPECT().BuildConfig(ctx, &tc.envConfig).Return(nil, tc.Err).AnyTimes()
}
mProvider.EXPECT().BuildConfig(ctx, &tc.envConfig).Times(1).Return(nil, tc.Err)
}
err = tfconfig.AddProviders(ctx, tc.requiredProviders, supportedUCPProviders, &tc.envConfig)
err = tfconfig.AddProviders(ctx, tc.requiredProviders, ucpConfiguredProviders, &tc.envConfig)
if tc.Err != nil {
require.ErrorContains(t, err, tc.Err.Error())
return
Expand Down
32 changes: 28 additions & 4 deletions pkg/recipes/terraform/config/providers/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,37 @@ type Provider interface {
BuildConfig(ctx context.Context, envConfig *recipes.Configuration) (map[string]any, error)
}

// GetUCPSupportedTerraformProviders returns a map of Terraform provider names with configuration details stored in UCP, to provider config builder.
// These providers represent Terraform providers for which Radius generates custom provider configurations based on credentials stored with UCP.
// For example, the Azure subscription id is added to Azure provider config using Radius Environment's Azure provider scope.
func GetUCPSupportedTerraformProviders(ucpConn sdk.Connection, secretProvider *ucp_provider.SecretProvider) map[string]Provider {
// GetUCPConfiguredTerraformProviders returns a map of Terraform provider names with configuration details stored in UCP, to provider config builder.
// These providers represent Terraform providers for which Radius generates custom provider configurations based on credentials stored with UCP
// and providers configured on the Radius environment. For example, the Azure subscription id is added to Azure provider config using Radius Environment's Azure provider scope.
func GetUCPConfiguredTerraformProviders(ucpConn sdk.Connection, secretProvider *ucp_provider.SecretProvider) map[string]Provider {
return map[string]Provider{
AWSProviderName: NewAWSProvider(ucpConn, secretProvider),
AzureProviderName: NewAzureProvider(ucpConn, secretProvider),
KubernetesProviderName: &kubernetesProvider{},
}
}

// GetRecipeProviderConfigs returns the Terraform provider configurations for Terraform providers
// specified under the RecipeConfig/Terraform/Providers section under environment configuration.
func GetRecipeProviderConfigs(ctx context.Context, envConfig *recipes.Configuration) map[string]any {
providerConfigs := make(map[string]any)

// If the provider is not configured, or has empty configuration, skip this iteration
if envConfig != nil && envConfig.RecipeConfig.Terraform.Providers != nil {
for provider, config := range envConfig.RecipeConfig.Terraform.Providers {
if len(config) > 0 {
configList := make([]any, 0)

// Retrieve configuration details from 'AdditionalProperties' property and add to the list.
for _, configDetails := range config {
configList = append(configList, configDetails.AdditionalProperties)
}

providerConfigs[provider] = configList
}
}
}

return providerConfigs
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@
}
},
"provider": {
"azurerm": [
{
"features": {}
}
]
"azurerm": {
"features": {}
}
},
"module": {
"redis-azure": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@
}
},
"provider": {
"aws": [
{
"region": "test-region"
}
],
"aws": {
"region": "test-region"
},
"kubernetes": [
{
"config_path": "/home/radius/.kube/configPath1"
"ConfigPath": "/home/radius/.kube/configPath1"
},
{
"config_path": "/home/radius/.kube/configPath2"
"ConfigPath": "/home/radius/.kube/configPath2"
}
]
},
Expand Down
Loading

0 comments on commit 0a7d6a8

Please sign in to comment.