From dbf37e01d10c70da2912a0c6cd45e36a15ccf7a0 Mon Sep 17 00:00:00 2001 From: TonyAdo <71679464+adohe@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:01:25 +0800 Subject: [PATCH] chore: secret generator add more test cases (#740) --- .../app_configurations_generator.go | 2 +- .../workload/secret/secret_generator.go | 22 ++-- .../workload/secret/secret_generator_test.go | 118 +++++++++++++++--- pkg/modules/interfaces.go | 4 +- 4 files changed, 116 insertions(+), 30 deletions(-) diff --git a/pkg/modules/generators/app_configurations_generator.go b/pkg/modules/generators/app_configurations_generator.go index 685907c0..a53fc9cb 100644 --- a/pkg/modules/generators/app_configurations_generator.go +++ b/pkg/modules/generators/app_configurations_generator.go @@ -95,7 +95,7 @@ func (g *appConfigurationGenerator) Generate(i *apiv1.Intent) error { Namespace: namespaceName, ModuleInputs: modulesConfig, TerraformConfig: terraformConfig, - SecretStore: g.ws.SecretStore, + SecretStoreSpec: g.ws.SecretStore, } // Generate resources diff --git a/pkg/modules/generators/workload/secret/secret_generator.go b/pkg/modules/generators/workload/secret/secret_generator.go index 92e146ee..84c55b1a 100644 --- a/pkg/modules/generators/workload/secret/secret_generator.go +++ b/pkg/modules/generators/workload/secret/secret_generator.go @@ -19,10 +19,10 @@ import ( ) type secretGenerator struct { - project *apiv1.Project - namespace string - secrets map[string]workload.Secret - secretStore *apiv1.SecretStoreSpec + project *apiv1.Project + namespace string + secrets map[string]workload.Secret + secretStoreSpec *apiv1.SecretStoreSpec } func NewSecretGenerator(ctx modules.GeneratorContext) (modules.Generator, error) { @@ -38,10 +38,10 @@ func NewSecretGenerator(ctx modules.GeneratorContext) (modules.Generator, error) } return &secretGenerator{ - project: ctx.Project, - secrets: secretMap, - namespace: ctx.Namespace, - secretStore: ctx.SecretStore, + project: ctx.Project, + secrets: secretMap, + namespace: ctx.Namespace, + secretStoreSpec: ctx.SecretStoreSpec, }, nil } @@ -146,7 +146,7 @@ func (g *secretGenerator) generateCertificate(secretName string, secretRef workl // generateSecretWithExternalProvider retrieves target sensitive information from external secret provider and // generates corresponding Kubernetes Secret object. func (g *secretGenerator) generateSecretWithExternalProvider(secretName string, secretRef workload.Secret) (*v1.Secret, error) { - if g.secretStore == nil { + if g.secretStoreSpec == nil { return nil, errors.New("secret store is missing, please add valid secret store spec in workspace") } @@ -160,12 +160,12 @@ func (g *secretGenerator) generateSecretWithExternalProvider(secretName string, allErrs = append(allErrs, err) continue } - provider, exist := secrets.GetProvider(g.secretStore.Provider) + provider, exist := secrets.GetProvider(g.secretStoreSpec.Provider) if !exist { allErrs = append(allErrs, errors.New("no matched secret store found, please check workspace yaml")) continue } - secretStore, err := provider.NewSecretStore(*g.secretStore) + secretStore, err := provider.NewSecretStore(*g.secretStoreSpec) if err != nil { allErrs = append(allErrs, err) continue diff --git a/pkg/modules/generators/workload/secret/secret_generator_test.go b/pkg/modules/generators/workload/secret/secret_generator_test.go index 49036eff..2e4ca513 100644 --- a/pkg/modules/generators/workload/secret/secret_generator_test.go +++ b/pkg/modules/generators/workload/secret/secret_generator_test.go @@ -10,8 +10,45 @@ import ( "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/workload" + // ensure we can get correct secret store provider + _ "kusionstack.io/kusion/pkg/secrets/providers/register" ) +var testProject = &apiv1.Project{ + Name: "helloworld", +} + +func initGeneratorContext( + project *apiv1.Project, + secrets map[string]workload.Secret, + secretStoreSpec *apiv1.SecretStoreSpec, +) modules.GeneratorContext { + return modules.GeneratorContext{ + Project: project, + Application: &inputs.AppConfiguration{ + Workload: &workload.Workload{ + Service: &workload.Service{ + Base: workload.Base{ + Secrets: secrets, + }, + }, + }, + }, + Namespace: project.Name, + SecretStoreSpec: secretStoreSpec, + } +} + +func initSecretStoreSpec(data []apiv1.FakeProviderData) *apiv1.SecretStoreSpec { + return &apiv1.SecretStoreSpec{ + Provider: &apiv1.ProviderSpec{ + Fake: &apiv1.FakeProvider{ + Data: data, + }, + }, + } +} + func TestGenerateSecret(t *testing.T) { tests := map[string]struct { secretName string @@ -72,9 +109,6 @@ func TestGenerateSecret(t *testing.T) { }, } - project := &apiv1.Project{ - Name: "helloworld", - } // run all the tests for name, test := range tests { t.Run(name, func(t *testing.T) { @@ -84,22 +118,74 @@ func TestGenerateSecret(t *testing.T) { Data: test.secretData, }, } - intent := &apiv1.Intent{} - context := modules.GeneratorContext{ - Project: project, - Application: &inputs.AppConfiguration{ - Workload: &workload.Workload{ - Service: &workload.Service{ - Base: workload.Base{ - Secrets: secrets, - }, - }, - }, + context := initGeneratorContext(testProject, secrets, nil) + generator, _ := NewSecretGenerator(context) + err := generator.Generate(&apiv1.Intent{}) + if test.expectErr == "" { + require.NoError(t, err) + } else { + require.Error(t, err) + require.EqualError(t, err, test.expectErr) + } + }) + } +} + +func TestGenerateSecretWithExternalRef(t *testing.T) { + tests := map[string]struct { + secretName string + secretType string + secretData map[string]string + + providerData []apiv1.FakeProviderData + + expectErr string + }{ + "create_external_secret": { + secretName: "api-auth", + secretType: "external", + secretData: map[string]string{ + "accessKey": "ref://api-auth-info/accessKey?version=1", + "secretKey": "ref://api-auth-info/secretKey?version=1", + }, + providerData: []apiv1.FakeProviderData{ + { + Key: "api-auth-info", + Value: `{"accessKey":"some sensitive info","secretKey":"*******"}`, + Version: "1", + }, + }, + }, + "create_external_secret_not_found": { + secretName: "access-token", + secretType: "external", + secretData: map[string]string{ + "accessToken": "ref://token?version=1", + }, + providerData: []apiv1.FakeProviderData{ + { + Key: "token-info", + Value: "some sensitive info", + Version: "1", + }, + }, + expectErr: "Secret does not exist", + }, + } + + // run all the tests + for name, test := range tests { + t.Run(name, func(t *testing.T) { + secrets := map[string]workload.Secret{ + name: { + Type: test.secretType, + Data: test.secretData, }, - Namespace: project.Name, } + secretStoreSpec := initSecretStoreSpec(test.providerData) + context := initGeneratorContext(testProject, secrets, secretStoreSpec) generator, _ := NewSecretGenerator(context) - err := generator.Generate(intent) + err := generator.Generate(&apiv1.Intent{}) if test.expectErr == "" { require.NoError(t, err) } else { diff --git a/pkg/modules/interfaces.go b/pkg/modules/interfaces.go index 2ea2882b..739e9c89 100644 --- a/pkg/modules/interfaces.go +++ b/pkg/modules/interfaces.go @@ -48,6 +48,6 @@ type GeneratorContext struct { // TerraformConfig is the collection of provider configs for the terraform runtime. TerraformConfig v1.TerraformConfig - // SecretStore is the external secret store spec - SecretStore *v1.SecretStoreSpec + // SecretStoreSpec is the external secret store spec + SecretStoreSpec *v1.SecretStoreSpec }