Skip to content

Commit c980604

Browse files
committed
add support for optional secrets using flag optional-secrets
1 parent 98a79ff commit c980604

File tree

5 files changed

+47
-22
lines changed

5 files changed

+47
-22
lines changed

cmd/helmify/flags.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func (i *arrayFlags) Set(value string) error {
5353
// ReadFlags command-line flags into app config.
5454
func ReadFlags() config.Config {
5555
files := arrayFlags{}
56+
optionalSecrets := arrayFlags{}
5657
result := config.Config{}
5758
var h, help, version, crd, preservens bool
5859
flag.BoolVar(&h, "h", false, "Print help. Example: helmify -h")
@@ -69,6 +70,7 @@ func ReadFlags() config.Config {
6970
flag.BoolVar(&result.FilesRecursively, "r", false, "Scan dirs from -f option recursively")
7071
flag.BoolVar(&result.OriginalName, "original-name", false, "Use the object's original name instead of adding the chart's release name as the common prefix.")
7172
flag.Var(&files, "f", "File or directory containing k8s manifests")
73+
flag.Var(&optionalSecrets, "optional-secrets", "List of secrets to be templated as optional (their values will not be required).")
7274
flag.BoolVar(&preservens, "preserve-ns", false, "Use the object's original namespace instead of adding all the resources to a common namespace")
7375
flag.BoolVar(&result.AddWebhookOption, "add-webhook-option", false, "Allows the user to add webhook option in values.yaml")
7476

@@ -94,5 +96,6 @@ func ReadFlags() config.Config {
9496
result.PreserveNs = true
9597
}
9698
result.Files = files
99+
result.OptionalSecrets = optionalSecrets
97100
return result
98101
}

pkg/config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ type Config struct {
4343
PreserveNs bool
4444
// AddWebhookOption enables the generation of a webhook option in values.yamlß
4545
AddWebhookOption bool
46+
// OptionalSecrets - list of secrets that are optional and should only be generated if values are given
47+
OptionalSecrets []string
4648
}
4749

4850
func (c *Config) Validate() error {

pkg/helmify/values.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package helmify
22

33
import (
4-
"dario.cat/mergo"
54
"fmt"
65
"strconv"
76
"strings"
87

8+
"dario.cat/mergo"
9+
910
"github.com/iancoleman/strcase"
1011

1112
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -71,12 +72,15 @@ func (v *Values) AddYaml(value interface{}, indent int, newLine bool, name ...st
7172

7273
// AddSecret - adds empty value to values and returns its helm template representation {{ required "<valueName>" .Values.<valueName> }}.
7374
// Set toBase64=true for Secret data to be base64 encoded and set false for Secret stringData.
74-
func (v *Values) AddSecret(toBase64 bool, name ...string) (string, error) {
75+
func (v *Values) AddSecret(toBase64 bool, optionalSecret bool, name ...string) (string, error) {
7576
name = toCamelCase(name)
7677
nameStr := strings.Join(name, ".")
77-
err := unstructured.SetNestedField(*v, "", name...)
78-
if err != nil {
79-
return "", fmt.Errorf("%w: unable to set value: %v", err, nameStr)
78+
var err error = nil
79+
if !optionalSecret {
80+
err = unstructured.SetNestedField(*v, "", name...)
81+
if err != nil {
82+
return "", fmt.Errorf("%w: unable to set value: %v", err, nameStr)
83+
}
8084
}
8185
res := fmt.Sprintf(`{{ required "%[1]s is required" .Values.%[1]s`, nameStr)
8286
if toBase64 {

pkg/helmify/values_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,13 @@ func TestValues_Add(t *testing.T) {
7171
func TestValues_AddSecret(t *testing.T) {
7272
t.Run("add base64 enc secret", func(t *testing.T) {
7373
testVal := Values{}
74-
res, err := testVal.AddSecret(true, "a", "b")
74+
res, err := testVal.AddSecret(true, true, "a", "b")
7575
assert.NoError(t, err)
7676
assert.Contains(t, res, "b64enc")
7777
})
7878
t.Run("add not encoded secret", func(t *testing.T) {
7979
testVal := Values{}
80-
res, err := testVal.AddSecret(false, "a", "b")
80+
res, err := testVal.AddSecret(true, true, "a", "b")
8181
assert.NoError(t, err)
8282
assert.NotContains(t, res, "b64enc")
8383
})

pkg/processor/secret/secret.go

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package secret
22

33
import (
44
"fmt"
5-
"github.com/arttor/helmify/pkg/format"
65
"io"
6+
"slices"
77
"strings"
88
"text/template"
99

10+
"github.com/arttor/helmify/pkg/format"
11+
1012
"github.com/arttor/helmify/pkg/processor"
1113

1214
"github.com/arttor/helmify/pkg/helmify"
@@ -18,17 +20,24 @@ import (
1820
"k8s.io/apimachinery/pkg/runtime/schema"
1921
)
2022

21-
var secretTempl, _ = template.New("secret").Parse(
22-
`{{ .Meta }}
23-
{{- if .Data }}
24-
{{ .Data }}
23+
// Template uses << and >> as delimiters because if we used the default ones "{{" and ""}}"
24+
// we would not be able ton insert {{- end }} in the template.
25+
var secretTempl, _ = template.New("secret").Delims("<<", ">>").Parse(`<<- if .Optional >>
26+
<< .Optional >>
27+
<<- end >>
28+
<< .Meta >>
29+
<<- if .Data >>
30+
<< .Data >>
31+
<<- end >>
32+
<<- if .StringData >>
33+
<< .StringData >>
34+
<<- end >>
35+
<<- if .Type >>
36+
<< .Type >>
37+
<<- end >>
38+
<<- if .Optional >>
2539
{{- end }}
26-
{{- if .StringData }}
27-
{{ .StringData }}
28-
{{- end }}
29-
{{- if .Type }}
30-
{{ .Type }}
31-
{{- end }}`)
40+
<<- end >>`)
3241

3342
var configMapGVC = schema.GroupVersionKind{
3443
Group: "",
@@ -60,7 +69,12 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu
6069

6170
name := appMeta.TrimName(obj.GetName())
6271
nameCamelCase := strcase.ToLowerCamel(name)
63-
72+
isOptional := slices.Contains(appMeta.Config().OptionalSecrets, obj.GetName())
73+
//isOptional := false
74+
optionalData := ""
75+
if isOptional {
76+
optionalData = fmt.Sprintf("{{- if not (empty .Values.%s) }}", nameCamelCase)
77+
}
6478
secretType := string(sec.Type)
6579
if secretType != "" {
6680
secretType, err = yamlformat.Marshal(map[string]interface{}{"type": secretType}, 0)
@@ -77,7 +91,7 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu
7791
if key == strings.ToUpper(key) {
7892
keyCamelCase = strcase.ToLowerCamel(strings.ToLower(key))
7993
}
80-
templatedName, err := values.AddSecret(true, nameCamelCase, keyCamelCase)
94+
templatedName, err := values.AddSecret(true, isOptional, nameCamelCase, keyCamelCase)
8195
if err != nil {
8296
return true, nil, fmt.Errorf("%w: unable add secret to values", err)
8397
}
@@ -98,7 +112,7 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu
98112
if key == strings.ToUpper(key) {
99113
keyCamelCase = strcase.ToLowerCamel(strings.ToLower(key))
100114
}
101-
templatedName, err := values.AddSecret(false, nameCamelCase, keyCamelCase)
115+
templatedName, err := values.AddSecret(false, isOptional, nameCamelCase, keyCamelCase)
102116
if err != nil {
103117
return true, nil, fmt.Errorf("%w: unable add secret to values", err)
104118
}
@@ -120,7 +134,8 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu
120134
Meta string
121135
Data string
122136
StringData string
123-
}{Type: secretType, Meta: meta, Data: data, StringData: stringData},
137+
Optional string
138+
}{Type: secretType, Meta: meta, Data: data, StringData: stringData, Optional: optionalData},
124139
values: values,
125140
}, nil
126141
}
@@ -132,6 +147,7 @@ type result struct {
132147
Meta string
133148
Data string
134149
StringData string
150+
Optional string
135151
}
136152
values helmify.Values
137153
}

0 commit comments

Comments
 (0)