mirror of
https://github.com/fluxcd/flux2.git
synced 2026-05-23 01:45:53 +00:00
Merge ce8d638489 into fa7cd5f847
This commit is contained in:
commit
3a0ff34671
13 changed files with 397 additions and 6 deletions
|
|
@ -68,6 +68,7 @@ type buildKsFlags struct {
|
|||
kustomizationFile string
|
||||
path string
|
||||
ignorePaths []string
|
||||
stripSopsMetadata bool
|
||||
dryRun bool
|
||||
strictSubst bool
|
||||
recursive bool
|
||||
|
|
@ -81,6 +82,8 @@ func init() {
|
|||
buildKsCmd.Flags().StringVar(&buildKsArgs.path, "path", "", "Path to the manifests location.")
|
||||
buildKsCmd.Flags().StringVar(&buildKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.")
|
||||
buildKsCmd.Flags().StringSliceVar(&buildKsArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore in .gitignore format")
|
||||
buildKsCmd.Flags().BoolVar(&buildKsArgs.stripSopsMetadata, "strip-sops-metadata", false,
|
||||
"Strip top-level .sops metadata from non-Secret resources in build output.")
|
||||
buildKsCmd.Flags().BoolVar(&buildKsArgs.dryRun, "dry-run", false, "Dry run mode.")
|
||||
buildKsCmd.Flags().BoolVar(&buildKsArgs.strictSubst, "strict-substitute", false,
|
||||
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
|
||||
|
|
@ -128,6 +131,7 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
|
|||
build.WithTimeout(rootArgs.timeout),
|
||||
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
||||
build.WithDryRun(buildKsArgs.dryRun),
|
||||
build.WithStripSopsMetadata(buildKsArgs.stripSopsMetadata),
|
||||
build.WithNamespace(*kubeconfigArgs.Namespace),
|
||||
build.WithIgnore(buildKsArgs.ignorePaths),
|
||||
build.WithStrictSubstitute(buildKsArgs.strictSubst),
|
||||
|
|
@ -140,6 +144,7 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
|
|||
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
||||
build.WithTimeout(rootArgs.timeout),
|
||||
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
||||
build.WithStripSopsMetadata(buildKsArgs.stripSopsMetadata),
|
||||
build.WithIgnore(buildKsArgs.ignorePaths),
|
||||
build.WithStrictSubstitute(buildKsArgs.strictSubst),
|
||||
build.WithRecursive(buildKsArgs.recursive),
|
||||
|
|
|
|||
|
|
@ -211,6 +211,18 @@ spec:
|
|||
resultFile: "./testdata/build-kustomization/podinfo-with-my-app-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build helmrelease with sops metadata",
|
||||
args: "build kustomization podinfo --kustomization-file " + tmpFile + " --path ./testdata/build-kustomization/sops-helmrelease --strip-sops-metadata",
|
||||
resultFile: "./testdata/build-kustomization/sops-helmrelease-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build configmap with sops metadata",
|
||||
args: "build kustomization podinfo --kustomization-file " + tmpFile + " --path ./testdata/build-kustomization/sops-configmap --strip-sops-metadata",
|
||||
resultFile: "./testdata/build-kustomization/sops-configmap-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
}
|
||||
|
||||
tmpl := map[string]string{
|
||||
|
|
|
|||
|
|
@ -34,6 +34,20 @@ func TestCreateKustomization(t *testing.T) {
|
|||
args: "create kustomization my-app --path=./deploy --export",
|
||||
assert: assertError("source is required"),
|
||||
},
|
||||
{
|
||||
// Verify that --decryption-provider and --decryption-secret produce the
|
||||
// expected Kustomization YAML with a spec.decryption block.
|
||||
name: "with sops decryption",
|
||||
args: "create kustomization mysql " +
|
||||
"--source=GitRepository/apps " +
|
||||
"--path=./apps " +
|
||||
"--decryption-provider=sops " +
|
||||
"--decryption-secret=sops-age " +
|
||||
"--namespace=flux-system " +
|
||||
"--interval=1m " +
|
||||
"--export",
|
||||
assert: assertGoldenFile("testdata/create_kustomization/with-sops-decryption.yaml"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ type diffKsFlags struct {
|
|||
kustomizationFile string
|
||||
path string
|
||||
ignorePaths []string
|
||||
stripSopsMetadata bool
|
||||
progressBar bool
|
||||
strictSubst bool
|
||||
recursive bool
|
||||
|
|
@ -73,6 +74,8 @@ func init() {
|
|||
diffKsCmd.Flags().BoolVar(&diffKsArgs.progressBar, "progress-bar", true, "Boolean to set the progress bar. The default value is true.")
|
||||
diffKsCmd.Flags().StringSliceVar(&diffKsArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore in .gitignore format")
|
||||
diffKsCmd.Flags().StringVar(&diffKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.")
|
||||
diffKsCmd.Flags().BoolVar(&diffKsArgs.stripSopsMetadata, "strip-sops-metadata", false,
|
||||
"Strip top-level .sops metadata from non-Secret resources in diff output.")
|
||||
diffKsCmd.Flags().BoolVar(&diffKsArgs.strictSubst, "strict-substitute", false,
|
||||
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
|
||||
diffKsCmd.Flags().BoolVarP(&diffKsArgs.recursive, "recursive", "r", false, "Recursively diff Kustomizations")
|
||||
|
|
@ -115,6 +118,7 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
|||
build.WithKustomizationFile(diffKsArgs.kustomizationFile),
|
||||
build.WithProgressBar(),
|
||||
build.WithIgnore(diffKsArgs.ignorePaths),
|
||||
build.WithStripSopsMetadata(diffKsArgs.stripSopsMetadata),
|
||||
build.WithStrictSubstitute(diffKsArgs.strictSubst),
|
||||
build.WithRecursive(diffKsArgs.recursive),
|
||||
build.WithLocalSources(diffKsArgs.localSources),
|
||||
|
|
@ -128,6 +132,7 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
|||
build.WithTimeout(rootArgs.timeout),
|
||||
build.WithKustomizationFile(diffKsArgs.kustomizationFile),
|
||||
build.WithIgnore(diffKsArgs.ignorePaths),
|
||||
build.WithStripSopsMetadata(diffKsArgs.stripSopsMetadata),
|
||||
build.WithStrictSubstitute(diffKsArgs.strictSubst),
|
||||
build.WithRecursive(diffKsArgs.recursive),
|
||||
build.WithLocalSources(diffKsArgs.localSources),
|
||||
|
|
|
|||
11
cmd/flux/testdata/build-kustomization/sops-configmap-result.yaml
vendored
Normal file
11
cmd/flux/testdata/build-kustomization/sops-configmap-result.yaml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: v1
|
||||
data:
|
||||
api-key: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: app-config
|
||||
namespace: default
|
||||
---
|
||||
22
cmd/flux/testdata/build-kustomization/sops-configmap/configmap.yaml
vendored
Normal file
22
cmd/flux/testdata/build-kustomization/sops-configmap/configmap.yaml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
namespace: default
|
||||
data:
|
||||
api-key: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age10la2ge0wtvx3qr7datqf7rs4yngxszdal927fs9rukamr8u2pshsvtz7ce
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
abc
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2023-07-15T00:00:00Z"
|
||||
mac: ENC[AES256_GCM,data:mac,iv:iv,tag:tag,type:str]
|
||||
encrypted_regex: ^(data)$
|
||||
version: 3.7.3
|
||||
4
cmd/flux/testdata/build-kustomization/sops-configmap/kustomization.yaml
vendored
Normal file
4
cmd/flux/testdata/build-kustomization/sops-configmap/kustomization.yaml
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./configmap.yaml
|
||||
19
cmd/flux/testdata/build-kustomization/sops-helmrelease-result.yaml
vendored
Normal file
19
cmd/flux/testdata/build-kustomization/sops-helmrelease-result.yaml
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: mysql
|
||||
namespace: default
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: mysql
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bitnami
|
||||
values:
|
||||
mysql:
|
||||
rootPassword: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
---
|
||||
30
cmd/flux/testdata/build-kustomization/sops-helmrelease/helmrelease.yaml
vendored
Normal file
30
cmd/flux/testdata/build-kustomization/sops-helmrelease/helmrelease.yaml
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: mysql
|
||||
namespace: default
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: mysql
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bitnami
|
||||
values:
|
||||
mysql:
|
||||
rootPassword: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age10la2ge0wtvx3qr7datqf7rs4yngxszdal927fs9rukamr8u2pshsvtz7ce
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
abc
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2023-07-15T00:00:00Z"
|
||||
mac: ENC[AES256_GCM,data:mac,iv:iv,tag:tag,type:str]
|
||||
encrypted_regex: ^(values)$
|
||||
version: 3.7.3
|
||||
4
cmd/flux/testdata/build-kustomization/sops-helmrelease/kustomization.yaml
vendored
Normal file
4
cmd/flux/testdata/build-kustomization/sops-helmrelease/kustomization.yaml
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./helmrelease.yaml
|
||||
17
cmd/flux/testdata/create_kustomization/with-sops-decryption.yaml
vendored
Normal file
17
cmd/flux/testdata/create_kustomization/with-sops-decryption.yaml
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: mysql
|
||||
namespace: flux-system
|
||||
spec:
|
||||
decryption:
|
||||
provider: sops
|
||||
secretRef:
|
||||
name: sops-age
|
||||
interval: 1m0s
|
||||
path: ./apps
|
||||
prune: false
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: apps
|
||||
|
|
@ -146,6 +146,9 @@ type Builder struct {
|
|||
strictSubst bool
|
||||
recursive bool
|
||||
localSources map[string]string
|
||||
// stripSopsMetadata controls whether top-level .sops metadata is stripped
|
||||
// from non-Secret resources in build/diff output.
|
||||
stripSopsMetadata bool
|
||||
// diff needs to handle kustomizations one by one, and opt-in to ignore kustomizations missing on cluster
|
||||
singleKustomization bool
|
||||
ignoreNotFound bool
|
||||
|
|
@ -256,6 +259,15 @@ func WithLocalSources(localSources map[string]string) BuilderOptionFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// WithStripSopsMetadata enables stripping top-level .sops metadata from
|
||||
// non-Secret resources in build/diff output.
|
||||
func WithStripSopsMetadata(strip bool) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.stripSopsMetadata = strip
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithInMemoryBuild sets the in-memory build backend
|
||||
func WithInMemoryBuild(inMemoryBuild bool) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
|
|
@ -493,7 +505,7 @@ func (b *Builder) build() (m resmap.ResMap, err error) {
|
|||
}
|
||||
|
||||
// make sure secrets are masked
|
||||
err = maskSopsData(res)
|
||||
err = maskSopsData(res, b.stripSopsMetadata)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -520,6 +532,7 @@ func (b *Builder) kustomizationBuild(k *kustomizev1.Kustomization) ([]*unstructu
|
|||
WithStrictSubstitute(b.strictSubst),
|
||||
WithRecursive(b.recursive),
|
||||
WithLocalSources(b.localSources),
|
||||
WithStripSopsMetadata(b.stripSopsMetadata),
|
||||
WithDryRun(b.dryRun),
|
||||
withFsBackend(b.fsBackend),
|
||||
)
|
||||
|
|
@ -672,7 +685,7 @@ func (b *Builder) setOwnerLabels(res *resource.Resource) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func maskSopsData(res *resource.Resource) error {
|
||||
func maskSopsData(res *resource.Resource, stripNonSecretSopsMetadata bool) error {
|
||||
// sopsMess is the base64 encoded mask
|
||||
sopsMess := base64.StdEncoding.EncodeToString([]byte(mask))
|
||||
|
||||
|
|
@ -689,7 +702,9 @@ func maskSopsData(res *resource.Resource) error {
|
|||
// assume that both data and stringdata are encrypted
|
||||
if bytes.Contains(asYaml, []byte("sops:")) && bytes.Contains(asYaml, []byte("mac: ENC[")) {
|
||||
// delete the sops object
|
||||
res.PipeE(yaml.FieldClearer{Name: "sops"})
|
||||
if err := res.PipeE(yaml.FieldClearer{Name: "sops"}); err != nil {
|
||||
return fmt.Errorf("failed to clear sops field from %s %s: %w", res.GetKind(), res.GetName(), err)
|
||||
}
|
||||
|
||||
secretType, err := res.GetFieldValue(typeField)
|
||||
// If the intended type is Opaque, then it can be omitted from the manifest, since it's the default
|
||||
|
|
@ -742,6 +757,19 @@ func maskSopsData(res *resource.Resource) error {
|
|||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
}
|
||||
} else if stripNonSecretSopsMetadata {
|
||||
// For non-Secret resources (e.g. HelmRelease), strip top-level .sops metadata
|
||||
// so it is not persisted in the cluster or exposed in build/diff output.
|
||||
sopsField, err := res.Pipe(yaml.Lookup("sops"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to inspect %s %s for top-level sops field: %w", res.GetKind(), res.GetName(), err)
|
||||
}
|
||||
|
||||
if sopsField != nil {
|
||||
if err := res.PipeE(yaml.FieldClearer{Name: "sops"}); err != nil {
|
||||
return fmt.Errorf("failed to strip top-level sops field from %s %s: %w", res.GetKind(), res.GetName(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -146,13 +146,16 @@ type: kubernetes.io/dockerconfigjson
|
|||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
r, err := yaml.Parse(tc.yamlStr)
|
||||
input := strings.ReplaceAll(tc.yamlStr, "\t", " ")
|
||||
expected := strings.ReplaceAll(tc.expected, "\t", " ")
|
||||
|
||||
r, err := yaml.Parse(input)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse yaml: %v", err)
|
||||
}
|
||||
|
||||
resource := &resource.Resource{RNode: *r}
|
||||
err = maskSopsData(resource)
|
||||
err = maskSopsData(resource, true)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to trim sops data: %v", err)
|
||||
}
|
||||
|
|
@ -161,13 +164,230 @@ type: kubernetes.io/dockerconfigjson
|
|||
if err != nil {
|
||||
t.Fatalf("unable to convert sanitized resources to yaml: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(string(sYaml), tc.expected); diff != "" {
|
||||
if diff := cmp.Diff(string(sYaml), expected); diff != "" {
|
||||
t.Errorf("unexpected sanitized resources: (-got +want)%v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaskSopsDataNonSecret(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
yamlStr string
|
||||
strip bool
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "HelmRelease with sops metadata and opt-in strip",
|
||||
strip: true,
|
||||
yamlStr: `apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: mysql
|
||||
namespace: default
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: mysql
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bitnami
|
||||
values:
|
||||
mysql:
|
||||
rootPassword: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
replicationPassword: ENC[AES256_GCM,data:def456,iv:xyz,tag:tag,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age10la2ge0wtvx3qr7datqf7rs4yngxszdal927fs9rukamr8u2pshsvtz7ce
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
abc
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2023-07-15T00:00:00Z"
|
||||
mac: ENC[AES256_GCM,data:mac,iv:iv,tag:tag,type:str]
|
||||
encrypted_regex: ^(values)$
|
||||
version: 3.7.3
|
||||
`,
|
||||
expected: `apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: mysql
|
||||
namespace: default
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: mysql
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bitnami
|
||||
values:
|
||||
mysql:
|
||||
replicationPassword: ENC[AES256_GCM,data:def456,iv:xyz,tag:tag,type:str]
|
||||
rootPassword: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "HelmRelease without sops metadata",
|
||||
strip: true,
|
||||
yamlStr: `apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: podinfo
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: podinfo
|
||||
values:
|
||||
replicaCount: 2
|
||||
`,
|
||||
expected: `apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: podinfo
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: podinfo
|
||||
values:
|
||||
replicaCount: 2
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "ConfigMap with top-level sops and opt-in strip",
|
||||
strip: true,
|
||||
yamlStr: `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
namespace: default
|
||||
data:
|
||||
values.yaml: |
|
||||
hello: world
|
||||
sops:
|
||||
version: 3.7.0
|
||||
encrypted_regex: ^(data)$
|
||||
`,
|
||||
expected: `apiVersion: v1
|
||||
data:
|
||||
values.yaml: |
|
||||
hello: world
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
namespace: default
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "HelmRelease with sops metadata without opt-in strip",
|
||||
strip: false,
|
||||
yamlStr: `apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: mysql
|
||||
namespace: default
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: mysql
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bitnami
|
||||
values:
|
||||
mysql:
|
||||
rootPassword: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
replicationPassword: ENC[AES256_GCM,data:def456,iv:xyz,tag:tag,type:str]
|
||||
sops:
|
||||
version: 3.7.3
|
||||
`,
|
||||
expected: `apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: mysql
|
||||
namespace: default
|
||||
sops:
|
||||
version: 3.7.3
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: mysql
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bitnami
|
||||
values:
|
||||
mysql:
|
||||
replicationPassword: ENC[AES256_GCM,data:def456,iv:xyz,tag:tag,type:str]
|
||||
rootPassword: ENC[AES256_GCM,data:abc123,iv:xyz,tag:tag,type:str]
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "ConfigMap with top-level sops without opt-in strip",
|
||||
strip: false,
|
||||
yamlStr: `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
namespace: default
|
||||
data:
|
||||
values.yaml: |
|
||||
hello: world
|
||||
sops:
|
||||
version: 3.7.0
|
||||
encrypted_regex: ^(data)$
|
||||
`,
|
||||
expected: `apiVersion: v1
|
||||
data:
|
||||
values.yaml: |
|
||||
hello: world
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
namespace: default
|
||||
sops:
|
||||
encrypted_regex: ^(data)$
|
||||
version: 3.7.0
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
input := strings.ReplaceAll(tc.yamlStr, "\t", " ")
|
||||
expected := strings.ReplaceAll(tc.expected, "\t", " ")
|
||||
|
||||
r, err := yaml.Parse(input)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse yaml: %v", err)
|
||||
}
|
||||
|
||||
res := &resource.Resource{RNode: *r}
|
||||
if err := maskSopsData(res, tc.strip); err != nil {
|
||||
t.Fatalf("maskSopsData returned unexpected error: %v", err)
|
||||
}
|
||||
|
||||
got, err := res.AsYAML()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to convert resource to yaml: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(string(got), expected); diff != "" {
|
||||
t.Errorf("unexpected output (-got +want):\n%v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_unMarshallKustomization(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue