Reduce indirection.

This commit is contained in:
jregan
2018-06-07 21:34:54 -07:00
parent a82bd23f8f
commit a42c72b2e0
16 changed files with 221 additions and 211 deletions

View File

@@ -28,42 +28,37 @@ import (
"k8s.io/apimachinery/pkg/util/validation"
)
func newResourceFromConfigMap(l loader.Loader, cm types.ConfigMapArgs) (*resource.Resource, error) {
corev1CM, err := makeConfigMap(l, cm)
func newResourceFromConfigMap(l loader.Loader, cmArgs types.ConfigMapArgs) (*resource.Resource, error) {
cm, err := makeConfigMap(l, cmArgs)
if err != nil {
return nil, err
}
data, err := newUnstructuredFromObject(corev1CM)
if err != nil {
return nil, err
}
return resource.NewResource(data, cm.Behavior), nil
return resource.NewResourceWithBehavior(cm, resource.NewGenerationBehavior(cmArgs.Behavior))
}
func makeConfigMap(l loader.Loader, cm types.ConfigMapArgs) (*corev1.ConfigMap, error) {
func makeConfigMap(l loader.Loader, cmArgs types.ConfigMapArgs) (*corev1.ConfigMap, error) {
var envPairs, literalPairs, filePairs []kvPair
var err error
corev1cm := &corev1.ConfigMap{}
corev1cm.APIVersion = "v1"
corev1cm.Kind = "ConfigMap"
corev1cm.Name = cm.Name
corev1cm.Data = map[string]string{}
cm := &corev1.ConfigMap{}
cm.APIVersion = "v1"
cm.Kind = "ConfigMap"
cm.Name = cmArgs.Name
cm.Data = map[string]string{}
if cm.EnvSource != "" {
envPairs, err = keyValuesFromEnvFile(l, cm.EnvSource)
if cmArgs.EnvSource != "" {
envPairs, err = keyValuesFromEnvFile(l, cmArgs.EnvSource)
if err != nil {
return nil, fmt.Errorf("error reading keys from env source file: %s %v", cm.EnvSource, err)
return nil, fmt.Errorf("error reading keys from env source file: %s %v", cmArgs.EnvSource, err)
}
}
literalPairs, err = keyValuesFromLiteralSources(cm.LiteralSources)
literalPairs, err = keyValuesFromLiteralSources(cmArgs.LiteralSources)
if err != nil {
return nil, fmt.Errorf("error reading key values from literal sources: %v", err)
}
filePairs, err = keyValuesFromFileSources(l, cm.FileSources)
filePairs, err = keyValuesFromFileSources(l, cmArgs.FileSources)
if err != nil {
return nil, fmt.Errorf("error reading key values from file sources: %v", err)
}
@@ -72,13 +67,13 @@ func makeConfigMap(l loader.Loader, cm types.ConfigMapArgs) (*corev1.ConfigMap,
// merge key value pairs from all the sources
for _, kv := range allPairs {
err = addKV(corev1cm.Data, kv)
err = addKV(cm.Data, kv)
if err != nil {
return nil, fmt.Errorf("error adding key in configmap: %v", err)
}
}
return corev1cm, nil
return cm, nil
}
func keyValuesFromEnvFile(l loader.Loader, path string) ([]kvPair, error) {

View File

@@ -19,7 +19,6 @@ package resmap
import (
"bytes"
"encoding/json"
"fmt"
"io"
"reflect"
@@ -30,7 +29,6 @@ import (
"github.com/kubernetes-sigs/kustomize/pkg/loader"
"github.com/kubernetes-sigs/kustomize/pkg/resource"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
)
@@ -40,8 +38,8 @@ type ResMap map[resource.ResId]*resource.Resource
// EncodeAsYaml encodes a ResMap to YAML; encoded objects separated by `---`.
func (m ResMap) EncodeAsYaml() ([]byte, error) {
ids := []resource.ResId{}
for gvkn := range m {
ids = append(ids, gvkn)
for id := range m {
ids = append(ids, id)
}
sort.Sort(IdSlice(ids))
@@ -49,7 +47,7 @@ func (m ResMap) EncodeAsYaml() ([]byte, error) {
var b []byte
buf := bytes.NewBuffer(b)
for _, id := range ids {
obj := m[id].Unstruct()
obj := m[id]
out, err := yaml.Marshal(obj)
if err != nil {
return nil, err
@@ -87,8 +85,8 @@ func (m1 ResMap) ErrorIfNotEqual(m2 ResMap) error {
if !found {
return fmt.Errorf("%#v doesn't exist in %#v", id, m2)
}
if !reflect.DeepEqual(obj1.Unstruct(), obj2.Unstruct()) {
return fmt.Errorf("%#v doesn't match %#v", obj1.Unstruct(), obj2.Unstruct())
if !reflect.DeepEqual(obj1, obj2) {
return fmt.Errorf("%#v doesn't match %#v", obj1, obj2)
}
}
return nil
@@ -153,11 +151,11 @@ func newResMapFromBytes(b []byte) (ResMap, error) {
result := ResMap{}
for _, res := range resources {
gvkn := res.Id()
if _, found := result[gvkn]; found {
return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", gvkn)
id := res.Id()
if _, found := result[id]; found {
return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", id)
}
result[gvkn] = res
result[id] = res
}
return result, nil
}
@@ -165,11 +163,11 @@ func newResMapFromBytes(b []byte) (ResMap, error) {
func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) {
result := ResMap{}
for _, res := range resources {
gvkn := res.Id()
if _, found := result[gvkn]; found {
return nil, fmt.Errorf("duplicated %#v is not allowed", gvkn)
id := res.Id()
if _, found := result[id]; found {
return nil, fmt.Errorf("duplicated %#v is not allowed", id)
}
result[gvkn] = res
result[id] = res
}
return result, nil
}
@@ -197,21 +195,17 @@ func newResourceSliceFromBytes(in []byte) ([]*resource.Resource, error) {
func Merge(maps ...ResMap) (ResMap, error) {
result := ResMap{}
for _, m := range maps {
for gvkn, obj := range m {
if _, found := result[gvkn]; found {
return nil, fmt.Errorf("there is already an entry: %q", gvkn)
for id, obj := range m {
if _, found := result[id]; found {
return nil, fmt.Errorf("there is already an entry: %q", id)
}
result[gvkn] = obj
result[id] = obj
}
}
return result, nil
}
const behaviorCreate = "create"
const behaviorReplace = "replace"
const behaviorMerge = "merge"
// MergeWithOverride merges the entries in the ResMap slice with Override.
// If there is already an entry with the same Id , different actions are performed
// according to value of behavior field:
@@ -221,44 +215,30 @@ const behaviorMerge = "merge"
func MergeWithOverride(maps ...ResMap) (ResMap, error) {
result := ResMap{}
for _, m := range maps {
for gvkn, resource := range m {
if _, found := result[gvkn]; found {
switch resource.Behavior() {
case "", behaviorCreate:
return nil, fmt.Errorf("Create an existing gvkn %#v is not allowed", gvkn)
case behaviorReplace:
glog.V(4).Infof("Replace object %v by %v", result[gvkn].Unstruct().Object, resource.Unstruct().Object)
resource.Replace(result[gvkn])
result[gvkn] = resource
case behaviorMerge:
glog.V(4).Infof("Merge object %v with %v", result[gvkn].Unstruct().Object, resource.Unstruct().Object)
resource.Merge(result[gvkn])
result[gvkn] = resource
glog.V(4).Infof("The merged object is %v", result[gvkn].Unstruct().Object)
for id, r := range m {
if _, found := result[id]; found {
switch r.Behavior() {
case resource.BehaviorReplace:
glog.V(4).Infof("Replace object %v by %v", result[id].Object, r.Object)
r.Replace(result[id])
result[id] = r
case resource.BehaviorMerge:
glog.V(4).Infof("Merge object %v with %v", result[id].Object, r.Object)
r.Merge(result[id])
result[id] = r
glog.V(4).Infof("The merged object is %v", result[id].Object)
default:
return nil, fmt.Errorf("The behavior of %#v must be one of merge and replace since it already exists in the base", gvkn)
return nil, fmt.Errorf("Id %#v exists; must merge or replace.", id)
}
} else {
switch resource.Behavior() {
case "", behaviorCreate:
result[gvkn] = resource
case behaviorMerge, behaviorReplace:
return nil, fmt.Errorf("No merge or replace is allowed for non existing gvkn %#v", gvkn)
switch r.Behavior() {
case resource.BehaviorMerge, resource.BehaviorReplace:
return nil, fmt.Errorf("Id %#v does not exist; cannot merge or replace.", id)
default:
return nil, fmt.Errorf("The behavior of %#v must be create since it doesn't exist", gvkn)
result[id] = r
}
}
}
}
return result, nil
}
func newUnstructuredFromObject(in runtime.Object) (*unstructured.Unstructured, error) {
marshaled, err := json.Marshal(in)
if err != nil {
return nil, err
}
var out unstructured.Unstructured
err = out.UnmarshalJSON(marshaled)
return &out, err
}

View File

@@ -28,32 +28,34 @@ import (
corev1 "k8s.io/api/core/v1"
)
func newFromSecretGenerator(p string, s types.SecretArgs) (*resource.Resource, error) {
corev1secret := &corev1.Secret{}
corev1secret.APIVersion = "v1"
corev1secret.Kind = "Secret"
corev1secret.Name = s.Name
corev1secret.Type = corev1.SecretType(s.Type)
if corev1secret.Type == "" {
corev1secret.Type = corev1.SecretTypeOpaque
func newResourceFromSecretGenerator(p string, sArgs types.SecretArgs) (*resource.Resource, error) {
s, err := makeSecret(p, sArgs)
if err != nil {
return nil, err
}
corev1secret.Data = map[string][]byte{}
return resource.NewResourceWithBehavior(
s, resource.NewGenerationBehavior(sArgs.Behavior))
}
for k, v := range s.Commands {
func makeSecret(p string, sArgs types.SecretArgs) (*corev1.Secret, error) {
s := &corev1.Secret{}
s.APIVersion = "v1"
s.Kind = "Secret"
s.Name = sArgs.Name
s.Type = corev1.SecretType(sArgs.Type)
if s.Type == "" {
s.Type = corev1.SecretTypeOpaque
}
s.Data = map[string][]byte{}
for k, v := range sArgs.Commands {
out, err := createSecretKey(p, v)
if err != nil {
return nil, err
}
corev1secret.Data[k] = out
s.Data[k] = out
}
obj, err := newUnstructuredFromObject(corev1secret)
if err != nil {
return nil, err
}
return resource.NewResource(obj, s.Behavior), nil
return s, nil
}
func createSecretKey(wd string, command string) ([]byte, error) {
@@ -65,7 +67,6 @@ func createSecretKey(wd string, command string) ([]byte, error) {
defer cancel()
cmd := exec.CommandContext(ctx, "sh", "-c", command)
cmd.Dir = wd
return cmd.Output()
}
@@ -74,7 +75,7 @@ func createSecretKey(wd string, command string) ([]byte, error) {
func NewResMapFromSecretArgs(p string, secretList []types.SecretArgs) (ResMap, error) {
allResources := []*resource.Resource{}
for _, secret := range secretList {
res, err := newFromSecretGenerator(p, secret)
res, err := newResourceFromSecretGenerator(p, secret)
if err != nil {
return nil, err
}

View File

@@ -30,10 +30,10 @@ import (
var secret = schema.GroupVersionKind{Version: "v1", Kind: "Secret"}
func TestNewFromSecretGenerators(t *testing.T) {
func TestNewResMapFromSecretArgs(t *testing.T) {
secrets := []types.SecretArgs{
{
Name: "secret",
Name: "apple",
Commands: map[string]string{
"DB_USERNAME": "printf admin",
"DB_PASSWORD": "printf somepw",
@@ -41,19 +41,20 @@ func TestNewFromSecretGenerators(t *testing.T) {
Type: "Opaque",
},
}
re, err := NewResMapFromSecretArgs(".", secrets)
actual, err := NewResMapFromSecretArgs(".", secrets)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expected := ResMap{
resource.NewResId(secret, "secret"): resource.NewResource(
resource.NewResId(secret, "apple"): resource.NewBehaviorlessResource(
&unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "secret",
"name": "apple",
"creationTimestamp": nil,
},
"type": string(corev1.SecretTypeOpaque),
@@ -62,11 +63,9 @@ func TestNewFromSecretGenerators(t *testing.T) {
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
},
},
""),
}),
}
if !reflect.DeepEqual(re, expected) {
t.Fatalf("%#v\ndoesn't match expected:\n%#v", re, expected)
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("%#v\ndoesn't match expected:\n%#v", actual, expected)
}
}