-
Notifications
You must be signed in to change notification settings - Fork 2.3k
feat: emitStringData boolean for secretGenerator
#5894
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ef57ad8
2652351
072ae78
c0b3af1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,28 +4,36 @@ | |||||
| package generators | ||||||
|
|
||||||
| import ( | ||||||
| "fmt" | ||||||
|
|
||||||
| "sigs.k8s.io/kustomize/api/ifc" | ||||||
| "sigs.k8s.io/kustomize/api/types" | ||||||
| "sigs.k8s.io/kustomize/kyaml/yaml" | ||||||
| ) | ||||||
|
|
||||||
| // MakeSecret makes a kubernetes Secret. | ||||||
| // | ||||||
| // Secret: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#secret-v1-core | ||||||
| // Secret: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/secret-v1/ | ||||||
| // | ||||||
| // ConfigMaps and Secrets are similar. | ||||||
| // | ||||||
| // Like a ConfigMap, a Secret has a `data` field, but unlike a ConfigMap it has | ||||||
| // no `binaryData` field. | ||||||
| // no `binaryData` field. Secret also provides a `stringData` field. | ||||||
| // | ||||||
| // All of a Secret's data is assumed to be opaque in nature, and assumed to be | ||||||
| // A Secret's `data` is assumed to be opaque in nature, and assumed to be | ||||||
| // base64 encoded from its original representation, regardless of whether the | ||||||
| // original data was UTF-8 text or binary. | ||||||
| // | ||||||
| // This encoding provides no secrecy. It's just a neutral, common means to | ||||||
| // represent opaque text and binary data. Beneath the base64 encoding | ||||||
| // is presumably further encoding under control of the Secret's consumer. | ||||||
| // | ||||||
| // A Secret's `stringData` field is similar to ConfigMap's `data` field. | ||||||
| // `stringData` allows specifying non-binary, UTF-8 secret data in string form. | ||||||
| // It is provided as a write-only input field for convenience. | ||||||
| // All keys and values are merged into the data field on write, overwriting any | ||||||
| // existing values. The stringData field is never output when reading from the API. | ||||||
| // | ||||||
| // A Secret has string field `type` which holds an identifier, used by the | ||||||
| // client, to choose the algorithm to interpret the `data` field. Kubernetes | ||||||
| // cannot make use of this data; it's up to a controller or some pod's service | ||||||
|
|
@@ -50,8 +58,14 @@ func MakeSecret( | |||||
| if err != nil { | ||||||
| return nil, err | ||||||
| } | ||||||
| if err = rn.LoadMapIntoSecretData(m); err != nil { | ||||||
| return nil, err | ||||||
| if args.EmitStringData { | ||||||
| if err = rn.LoadMapIntoSecretStringData(m); err != nil { | ||||||
| return nil, fmt.Errorf("Failed to load map into Secret stringData: %w", err) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure whether kustomize eschews the general advice for Go programs to not capitalize the first word in an error message, assuming that this message might wind up serving as a suffix for more prefixes to be added onto it higher up in the call stack. If this capitalization isn't us playing along with the rest of the code base, consider this alternative:
Suggested change
The message adopts the advice from Preslav Rachev's essay Go's Error Handling Is a Form of Storytelling. |
||||||
| } | ||||||
| } else { | ||||||
| if err = rn.LoadMapIntoSecretData(m); err != nil { | ||||||
| return nil, fmt.Errorf("Failed to load map into Secret data: %w", err) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise with the capitalization. |
||||||
| } | ||||||
| } | ||||||
| copyLabelsAndAnnotations(rn, args.Options) | ||||||
| setImmutable(rn, args.Options) | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -193,6 +193,82 @@ data: | |||||
| c: SGVsbG8gV29ybGQ= | ||||||
| d: dHJ1ZQ== | ||||||
| immutable: true | ||||||
| `, | ||||||
| }, | ||||||
| }, | ||||||
| "construct secret from text file as stringData": { | ||||||
| args: types.SecretArgs{ | ||||||
| EmitStringData: true, | ||||||
| GeneratorArgs: types.GeneratorArgs{ | ||||||
| Name: "fileSecret1", | ||||||
| KvPairSources: types.KvPairSources{ | ||||||
| FileSources: []string{ | ||||||
| filepath.Join("secret", "app-init.ini"), | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| exp: expected{ | ||||||
| out: `apiVersion: v1 | ||||||
| kind: Secret | ||||||
| metadata: | ||||||
| name: fileSecret1 | ||||||
| type: Opaque | ||||||
| stringData: | ||||||
| app-init.ini: | | ||||||
| FOO=bar | ||||||
| BAR=baz | ||||||
| `, | ||||||
| }, | ||||||
| }, | ||||||
| "construct secret from text and binary file with stringData and data": { | ||||||
| args: types.SecretArgs{ | ||||||
| EmitStringData: true, | ||||||
| GeneratorArgs: types.GeneratorArgs{ | ||||||
| Name: "fileSecret2", | ||||||
| KvPairSources: types.KvPairSources{ | ||||||
| FileSources: []string{ | ||||||
| filepath.Join("secret", "app-init.ini"), | ||||||
| filepath.Join("secret", "app.bin"), | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| exp: expected{ | ||||||
| out: `apiVersion: v1 | ||||||
| kind: Secret | ||||||
| metadata: | ||||||
| name: fileSecret2 | ||||||
| type: Opaque | ||||||
| stringData: | ||||||
| app-init.ini: | | ||||||
| FOO=bar | ||||||
| BAR=baz | ||||||
| data: | ||||||
| app.bin: //0= | ||||||
| `, | ||||||
| }, | ||||||
| }, | ||||||
| "construct secret from a binary file and fallback to data from stringData": { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| args: types.SecretArgs{ | ||||||
| EmitStringData: true, | ||||||
| GeneratorArgs: types.GeneratorArgs{ | ||||||
| Name: "fileSecret2", | ||||||
| KvPairSources: types.KvPairSources{ | ||||||
| FileSources: []string{ | ||||||
| filepath.Join("secret", "app.bin"), | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| exp: expected{ | ||||||
| out: `apiVersion: v1 | ||||||
| kind: Secret | ||||||
| metadata: | ||||||
| name: fileSecret2 | ||||||
| type: Opaque | ||||||
| data: | ||||||
| app.bin: //0= | ||||||
| `, | ||||||
| }, | ||||||
| }, | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -87,10 +87,10 @@ func TestGeneratorFromProperties(t *testing.T) { | |||||
| th := kusttest_test.MakeHarness(t) | ||||||
| th.WriteK("base", ` | ||||||
| configMapGenerator: | ||||||
| - name: test-configmap | ||||||
| behavior: create | ||||||
| envs: | ||||||
| - properties | ||||||
| - name: test-configmap | ||||||
| behavior: create | ||||||
| envs: | ||||||
| - properties | ||||||
| `) | ||||||
| th.WriteF("base/properties", ` | ||||||
| VAR1=100 | ||||||
|
|
@@ -118,6 +118,104 @@ metadata: | |||||
| `) | ||||||
| } | ||||||
|
|
||||||
| func TestGeneratorOverrideDataWithBinaryDataInvalidAtKubeAPI(t *testing.T) { | ||||||
| // the resulting ConfigMap will fail Kubernetes API validation: | ||||||
stealthybox marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| // The ConfigMap "test-configmap-b6h9d5bfmt" is invalid: data[CHANGING]: Invalid value: "CHANGING": duplicate of key present in binaryData | ||||||
| th := kusttest_test.MakeHarness(t) | ||||||
| th.WriteK("base", ` | ||||||
| configMapGenerator: | ||||||
| - name: test-configmap | ||||||
| behavior: create | ||||||
| envs: | ||||||
| - properties | ||||||
| `) | ||||||
| th.WriteF("base/properties", ` | ||||||
| CHANGING=data-before | ||||||
| BASE=red | ||||||
| `) | ||||||
| th.WriteK("overlay", ` | ||||||
| resources: | ||||||
| - ../base | ||||||
| configMapGenerator: | ||||||
| - name: test-configmap | ||||||
| behavior: "merge" | ||||||
| envs: | ||||||
| - properties | ||||||
| files: | ||||||
| - CHANGING | ||||||
| `) | ||||||
| th.WriteF("overlay/CHANGING", string(manyHellos(30))) | ||||||
| th.WriteF("overlay/properties", ` | ||||||
| OVERLAY=blue | ||||||
| `) | ||||||
| m := th.Run("overlay", th.MakeDefaultOptions()) | ||||||
| th.AssertActualEqualsExpected(m, ` | ||||||
| apiVersion: v1 | ||||||
| binaryData: | ||||||
| CHANGING: | | ||||||
| /2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbG | ||||||
| xv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hl | ||||||
| bGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2 | ||||||
| hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv | ||||||
| data: | ||||||
| BASE: red | ||||||
| CHANGING: data-before | ||||||
| OVERLAY: blue | ||||||
| kind: ConfigMap | ||||||
| metadata: | ||||||
| name: test-configmap-b6h9d5bfmt | ||||||
| `) | ||||||
| } | ||||||
|
|
||||||
| func TestGeneratorOverrideBinaryDataWithDataInvalidAtKubeAPI(t *testing.T) { | ||||||
| // the resulting ConfigMap will fail Kubernetes API validation: | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| // The ConfigMap "test-configmap-kt6d6mk694" is invalid: data[CHANGING]: Invalid value: "CHANGING": duplicate of key present in binaryData | ||||||
| th := kusttest_test.MakeHarness(t) | ||||||
| th.WriteK("base", ` | ||||||
| configMapGenerator: | ||||||
| - name: test-configmap | ||||||
| behavior: create | ||||||
| envs: | ||||||
| - properties | ||||||
| files: | ||||||
| - CHANGING | ||||||
| `) | ||||||
| th.WriteF("base/CHANGING", string(manyHellos(30))) | ||||||
| th.WriteF("base/properties", ` | ||||||
| BASE=red | ||||||
| `) | ||||||
| th.WriteK("overlay", ` | ||||||
| resources: | ||||||
| - ../base | ||||||
| configMapGenerator: | ||||||
| - name: test-configmap | ||||||
| behavior: "merge" | ||||||
| envs: | ||||||
| - properties | ||||||
| `) | ||||||
| th.WriteF("overlay/properties", ` | ||||||
| CHANGING=data-after | ||||||
| OVERLAY=blue | ||||||
| `) | ||||||
| m := th.Run("overlay", th.MakeDefaultOptions()) | ||||||
| th.AssertActualEqualsExpected(m, ` | ||||||
| apiVersion: v1 | ||||||
| binaryData: | ||||||
| CHANGING: | | ||||||
| /2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbG | ||||||
| xv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hl | ||||||
| bGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv/2 | ||||||
| hlbGxv/2hlbGxv/2hlbGxv/2hlbGxv | ||||||
| data: | ||||||
| BASE: red | ||||||
| CHANGING: data-after | ||||||
| OVERLAY: blue | ||||||
| kind: ConfigMap | ||||||
| metadata: | ||||||
| name: test-configmap-kt6d6mk694 | ||||||
| `) | ||||||
| } | ||||||
|
|
||||||
| // Generate a Secret and a ConfigMap from the same data | ||||||
| // to compare the result. | ||||||
| func TestGeneratorBasics(t *testing.T) { | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Thank you for this.