mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-18 08:51:45 +00:00
140 lines
3.5 KiB
Go
140 lines
3.5 KiB
Go
// Copyright 2020 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package generators
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"github.com/go-errors/errors"
|
|
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
|
"sigs.k8s.io/kustomize/api/ifc"
|
|
"sigs.k8s.io/kustomize/api/types"
|
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
)
|
|
|
|
func makeBaseNode(kind, name, namespace string) (*yaml.RNode, error) {
|
|
rn, err := yaml.Parse(fmt.Sprintf(`
|
|
apiVersion: v1
|
|
kind: %s
|
|
`, kind))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if name == "" {
|
|
return nil, errors.Errorf("a configmap must have a name")
|
|
}
|
|
if _, err := rn.Pipe(yaml.SetK8sName(name)); err != nil {
|
|
return nil, err
|
|
}
|
|
if namespace != "" {
|
|
if _, err := rn.Pipe(yaml.SetK8sNamespace(namespace)); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return rn, nil
|
|
}
|
|
|
|
func makeValidatedDataMap(
|
|
ldr ifc.KvLoader, name string, sources types.KvPairSources) (map[string]string, error) {
|
|
pairs, err := ldr.Load(sources)
|
|
if err != nil {
|
|
return nil, errors.WrapPrefix(err, "loading KV pairs", 0)
|
|
}
|
|
knownKeys := make(map[string]string)
|
|
for _, p := range pairs {
|
|
// legal key: alphanumeric characters, '-', '_' or '.'
|
|
if err := ldr.Validator().ErrIfInvalidKey(p.Key); err != nil {
|
|
return nil, err
|
|
}
|
|
if _, ok := knownKeys[p.Key]; ok {
|
|
return nil, errors.Errorf(
|
|
"configmap %s illegally repeats the key `%s`", name, p.Key)
|
|
}
|
|
knownKeys[p.Key] = p.Value
|
|
}
|
|
return knownKeys, nil
|
|
}
|
|
|
|
// copyLabelsAndAnnotations copies labels and annotations from
|
|
// GeneratorOptions into the given object.
|
|
func copyLabelsAndAnnotations(
|
|
rn *yaml.RNode, opts *types.GeneratorOptions) error {
|
|
if opts == nil {
|
|
return nil
|
|
}
|
|
for _, k := range filtersutil.SortedMapKeys(opts.Labels) {
|
|
v := opts.Labels[k]
|
|
if _, err := rn.Pipe(yaml.SetLabel(k, v)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, k := range filtersutil.SortedMapKeys(opts.Annotations) {
|
|
v := opts.Annotations[k]
|
|
if _, err := rn.Pipe(yaml.SetAnnotation(k, v)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// In a secret, all data is base64 encoded, regardless of its conformance
|
|
// or lack thereof to UTF-8.
|
|
func makeSecretValueRNode(s string) *yaml.RNode {
|
|
yN := &yaml.Node{Kind: yaml.ScalarNode}
|
|
// Purposely don't use YAML tags to identify the data as being plain text or
|
|
// binary. It kubernetes Secrets the values in the `data` map are expected
|
|
// to be base64 encoded, and in ConfigMaps that same can be said for the
|
|
// values in the `binaryData` field.
|
|
yN.Tag = yaml.NodeTagString
|
|
yN.Value = encodeBase64(s)
|
|
if strings.Contains(yN.Value, "\n") {
|
|
yN.Style = yaml.LiteralStyle
|
|
}
|
|
return yaml.NewRNode(yN)
|
|
}
|
|
|
|
func makeConfigMapValueRNode(s string) (field string, rN *yaml.RNode) {
|
|
yN := &yaml.Node{Kind: yaml.ScalarNode}
|
|
yN.Tag = yaml.NodeTagString
|
|
if utf8.ValidString(s) {
|
|
field = yaml.DataField
|
|
yN.Value = s
|
|
} else {
|
|
field = yaml.BinaryDataField
|
|
yN.Value = encodeBase64(s)
|
|
}
|
|
if strings.Contains(yN.Value, "\n") {
|
|
yN.Style = yaml.LiteralStyle
|
|
}
|
|
return field, yaml.NewRNode(yN)
|
|
}
|
|
|
|
// encodeBase64 encodes s as base64 that is broken up into multiple lines
|
|
// as appropriate for the resulting length.
|
|
func encodeBase64(s string) string {
|
|
const lineLen = 70
|
|
encLen := base64.StdEncoding.EncodedLen(len(s))
|
|
lines := encLen/lineLen + 1
|
|
buf := make([]byte, encLen*2+lines)
|
|
in := buf[0:encLen]
|
|
out := buf[encLen:]
|
|
base64.StdEncoding.Encode(in, []byte(s))
|
|
k := 0
|
|
for i := 0; i < len(in); i += lineLen {
|
|
j := i + lineLen
|
|
if j > len(in) {
|
|
j = len(in)
|
|
}
|
|
k += copy(out[k:], in[i:j])
|
|
if lines > 1 {
|
|
out[k] = '\n'
|
|
k++
|
|
}
|
|
}
|
|
return string(out[:k])
|
|
}
|