arttor/helmify

View on GitHub
pkg/processor/secret/secret.go

Summary

Maintainability
B
4 hrs
Test Coverage
D
68%
package secret

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

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

    "github.com/arttor/helmify/pkg/helmify"
    yamlformat "github.com/arttor/helmify/pkg/yaml"
    "github.com/iancoleman/strcase"
    corev1 "k8s.io/api/core/v1"
    "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    "k8s.io/apimachinery/pkg/runtime"
    "k8s.io/apimachinery/pkg/runtime/schema"
)

var secretTempl, _ = template.New("secret").Parse(
    `{{ .Meta }}
{{- if .Data }}
{{ .Data }}
{{- end }}
{{- if .StringData }}
{{ .StringData }}
{{- end }}
{{- if .Type }}
{{ .Type }}
{{- end }}`)

var configMapGVC = schema.GroupVersionKind{
    Group:   "",
    Version: "v1",
    Kind:    "Secret",
}

// New creates processor for k8s Secret resource.
func New() helmify.Processor {
    return &secret{}
}

type secret struct{}

// Process k8s Secret object into template. Returns false if not capable of processing given resource type.
func (d secret) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructured) (bool, helmify.Template, error) {
    if obj.GroupVersionKind() != configMapGVC {
        return false, nil, nil
    }
    sec := corev1.Secret{}
    err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &sec)
    if err != nil {
        return true, nil, fmt.Errorf("%w: unable to cast to secret", err)
    }
    meta, err := processor.ProcessObjMeta(appMeta, obj)
    if err != nil {
        return true, nil, err
    }

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

    secretType := string(sec.Type)
    if secretType != "" {
        secretType, err = yamlformat.Marshal(map[string]interface{}{"type": secretType}, 0)
        if err != nil {
            return true, nil, err
        }
    }

    values := helmify.Values{}
    var data, stringData string
    templatedData := map[string]string{}
    for key := range sec.Data {
        keyCamelCase := strcase.ToLowerCamel(key)
        if key == strings.ToUpper(key) {
            keyCamelCase = strcase.ToLowerCamel(strings.ToLower(key))
        }
        templatedName, err := values.AddSecret(true, nameCamelCase, keyCamelCase)
        if err != nil {
            return true, nil, fmt.Errorf("%w: unable add secret to values", err)
        }
        templatedData[key] = templatedName
    }
    if len(templatedData) != 0 {
        data, err = yamlformat.Marshal(map[string]interface{}{"data": templatedData}, 0)
        if err != nil {
            return true, nil, err
        }
        data = strings.ReplaceAll(data, "'", "")
        data = format.FixUnterminatedQuotes(data)
    }

    templatedData = map[string]string{}
    for key := range sec.StringData {
        keyCamelCase := strcase.ToLowerCamel(key)
        if key == strings.ToUpper(key) {
            keyCamelCase = strcase.ToLowerCamel(strings.ToLower(key))
        }
        templatedName, err := values.AddSecret(false, nameCamelCase, keyCamelCase)
        if err != nil {
            return true, nil, fmt.Errorf("%w: unable add secret to values", err)
        }
        templatedData[key] = templatedName
    }
    if len(templatedData) != 0 {
        stringData, err = yamlformat.Marshal(map[string]interface{}{"stringData": templatedData}, 0)
        if err != nil {
            return true, nil, err
        }
        stringData = strings.ReplaceAll(stringData, "'", "")
        stringData = format.FixUnterminatedQuotes(stringData)
    }

    return true, &result{
        name: name + ".yaml",
        data: struct {
            Type       string
            Meta       string
            Data       string
            StringData string
        }{Type: secretType, Meta: meta, Data: data, StringData: stringData},
        values: values,
    }, nil
}

type result struct {
    name string
    data struct {
        Type       string
        Meta       string
        Data       string
        StringData string
    }
    values helmify.Values
}

func (r *result) Filename() string {
    return r.name
}

func (r *result) Values() helmify.Values {
    return r.values
}

func (r *result) Write(writer io.Writer) error {
    return secretTempl.Execute(writer, r.data)
}