Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Usage:
| -cert-manager-install-crd | Allows the user to install cert-manager CRD as part of the cert-manager subchart.(default "true") | `helmify -cert-manager-install-crd` |
| -preserve-ns | Allows users to use the object's original namespace instead of adding all the resources to a common namespace. (default "false") | `helmify -preserve-ns` |
| -add-webhook-option | Adds an option to enable/disable webhook installation | `helmify -add-webhook-option`|
| -optional-secrets | Secrets whose values should not be required by helm | `helmify -optional-secrets mysecret1,mysecret2`|
## Status
Supported k8s resources:
- Deployment, DaemonSet, StatefulSet
Expand Down
3 changes: 3 additions & 0 deletions cmd/helmify/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func (i *arrayFlags) Set(value string) error {
// ReadFlags command-line flags into app config.
func ReadFlags() config.Config {
files := arrayFlags{}
optionalSecrets := arrayFlags{}
result := config.Config{}
var h, help, version, crd, preservens bool
flag.BoolVar(&h, "h", false, "Print help. Example: helmify -h")
Expand All @@ -69,6 +70,7 @@ func ReadFlags() config.Config {
flag.BoolVar(&result.FilesRecursively, "r", false, "Scan dirs from -f option recursively")
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.")
flag.Var(&files, "f", "File or directory containing k8s manifests")
flag.Var(&optionalSecrets, "optional-secrets", "List of secrets to be templated as optional (their values will not be required).")
flag.BoolVar(&preservens, "preserve-ns", false, "Use the object's original namespace instead of adding all the resources to a common namespace")
flag.BoolVar(&result.AddWebhookOption, "add-webhook-option", false, "Allows the user to add webhook option in values.yaml")

Expand All @@ -94,5 +96,6 @@ func ReadFlags() config.Config {
result.PreserveNs = true
}
result.Files = files
result.OptionalSecrets = optionalSecrets
return result
}
2 changes: 2 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type Config struct {
PreserveNs bool
// AddWebhookOption enables the generation of a webhook option in values.yamlß
AddWebhookOption bool
// OptionalSecrets - list of secrets that are optional and should only be generated if values are given
OptionalSecrets []string
}

func (c *Config) Validate() error {
Expand Down
14 changes: 9 additions & 5 deletions pkg/helmify/values.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package helmify

import (
"dario.cat/mergo"
"fmt"
"strconv"
"strings"

"dario.cat/mergo"

"github.com/iancoleman/strcase"

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

// AddSecret - adds empty value to values and returns its helm template representation {{ required "<valueName>" .Values.<valueName> }}.
// Set toBase64=true for Secret data to be base64 encoded and set false for Secret stringData.
func (v *Values) AddSecret(toBase64 bool, name ...string) (string, error) {
func (v *Values) AddSecret(toBase64 bool, optionalSecret bool, name ...string) (string, error) {
name = toCamelCase(name)
nameStr := strings.Join(name, ".")
err := unstructured.SetNestedField(*v, "", name...)
if err != nil {
return "", fmt.Errorf("%w: unable to set value: %v", err, nameStr)
var err error = nil
if !optionalSecret {
err = unstructured.SetNestedField(*v, "", name...)
if err != nil {
return "", fmt.Errorf("%w: unable to set value: %v", err, nameStr)
}
}
res := fmt.Sprintf(`{{ required "%[1]s is required" .Values.%[1]s`, nameStr)
if toBase64 {
Expand Down
4 changes: 2 additions & 2 deletions pkg/helmify/values_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ func TestValues_Add(t *testing.T) {
func TestValues_AddSecret(t *testing.T) {
t.Run("add base64 enc secret", func(t *testing.T) {
testVal := Values{}
res, err := testVal.AddSecret(true, "a", "b")
res, err := testVal.AddSecret(true, false, "a", "b")
assert.NoError(t, err)
assert.Contains(t, res, "b64enc")
})
t.Run("add not encoded secret", func(t *testing.T) {
testVal := Values{}
res, err := testVal.AddSecret(false, "a", "b")
res, err := testVal.AddSecret(false, false, "a", "b")
assert.NoError(t, err)
assert.NotContains(t, res, "b64enc")
})
Expand Down
45 changes: 30 additions & 15 deletions pkg/processor/secret/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package secret

import (
"fmt"
"github.com/arttor/helmify/pkg/format"
"io"
"slices"
"strings"
"text/template"

"github.com/arttor/helmify/pkg/format"

"github.com/arttor/helmify/pkg/processor"

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

var secretTempl, _ = template.New("secret").Parse(
`{{ .Meta }}
{{- if .Data }}
{{ .Data }}
// Template uses << and >> as delimiters because if we used the default ones "{{" and ""}}"
// we would not be able ton insert {{- end }} in the template.
var secretTempl, _ = template.New("secret").Delims("<<", ">>").Parse(`<< if .Optional ->>
<< .Optional >>
<< end ->>
<< .Meta >>
<<- if .Data >>
<< .Data >>
<<- end >>
<<- if .StringData >>
<< .StringData >>
<<- end >>
<<- if .Type >>
<< .Type >>
<<- end >>
<<- if .Optional >>
{{- end }}
{{- if .StringData }}
{{ .StringData }}
{{- end }}
{{- if .Type }}
{{ .Type }}
{{- end }}`)
<<- end >>`)

var configMapGVC = schema.GroupVersionKind{
Group: "",
Expand Down Expand Up @@ -60,7 +69,11 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu

name := appMeta.TrimName(obj.GetName())
nameCamelCase := strcase.ToLowerCamel(name)

isOptional := slices.Contains(appMeta.Config().OptionalSecrets, obj.GetName())
var optionalData string
if isOptional {
optionalData = fmt.Sprintf("{{- if not (empty .Values.%s) }}", nameCamelCase)
}
secretType := string(sec.Type)
if secretType != "" {
secretType, err = yamlformat.Marshal(map[string]interface{}{"type": secretType}, 0)
Expand All @@ -77,7 +90,7 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu
if key == strings.ToUpper(key) {
keyCamelCase = strcase.ToLowerCamel(strings.ToLower(key))
}
templatedName, err := values.AddSecret(true, nameCamelCase, keyCamelCase)
templatedName, err := values.AddSecret(true, isOptional, nameCamelCase, keyCamelCase)
if err != nil {
return true, nil, fmt.Errorf("%w: unable add secret to values", err)
}
Expand All @@ -98,7 +111,7 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu
if key == strings.ToUpper(key) {
keyCamelCase = strcase.ToLowerCamel(strings.ToLower(key))
}
templatedName, err := values.AddSecret(false, nameCamelCase, keyCamelCase)
templatedName, err := values.AddSecret(false, isOptional, nameCamelCase, keyCamelCase)
if err != nil {
return true, nil, fmt.Errorf("%w: unable add secret to values", err)
}
Expand All @@ -120,7 +133,8 @@ func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructu
Meta string
Data string
StringData string
}{Type: secretType, Meta: meta, Data: data, StringData: stringData},
Optional string
}{Type: secretType, Meta: meta, Data: data, StringData: stringData, Optional: optionalData},
values: values,
}, nil
}
Expand All @@ -132,6 +146,7 @@ type result struct {
Meta string
Data string
StringData string
Optional string
}
values helmify.Values
}
Expand Down
Loading