Add support for using common base

This commit is contained in:
Jingfang Liu
2018-07-26 14:02:13 -07:00
parent 4569a09d54
commit 58bc4b14a2
8 changed files with 94 additions and 18 deletions

View File

@@ -292,7 +292,7 @@ func (a *Application) resolveRefVars(m resmap.ResMap) (map[string]string, error)
}
for _, v := range vars {
id := resource.NewResId(v.ObjRef.GroupVersionKind(), v.ObjRef.Name)
if r, found := m[id]; found {
if r, found := m.DemandOneMatchForId(id); found {
s, err := r.GetFieldValue(v.FieldRef.FieldPath)
if err != nil {
return nil, fmt.Errorf("failed to resolve referred var: %+v", v)

View File

@@ -91,7 +91,7 @@ var svc = schema.GroupVersionKind{Version: "v1", Kind: "Service"}
func TestResources1(t *testing.T) {
expected := resmap.ResMap{
resource.NewResId(deploy, "dply1"): resource.NewResourceFromMap(
resource.NewResIdWithPrefix(deploy, "dply1", "foo-"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
@@ -123,7 +123,7 @@ func TestResources1(t *testing.T) {
},
},
}),
resource.NewResId(cmap, "literalConfigMap"): resource.NewResourceFromMap(
resource.NewResIdWithPrefix(cmap, "literalConfigMap", "foo-"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -143,7 +143,7 @@ func TestResources1(t *testing.T) {
"DB_PASSWORD": "somepw",
},
}).SetBehavior(resource.BehaviorCreate),
resource.NewResId(secret, "secret"): resource.NewResourceFromMap(
resource.NewResIdWithPrefix(secret, "secret", "foo-"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
@@ -164,7 +164,7 @@ func TestResources1(t *testing.T) {
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}).SetBehavior(resource.BehaviorCreate),
resource.NewResId(ns, "ns1"): resource.NewResourceFromMap(
resource.NewResIdWithPrefix(ns, "ns1", "foo-"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
@@ -289,7 +289,7 @@ func makeLoader2(t *testing.T) loader.Loader {
// perhaps it's not worth supporting the command.
func TestRawResources2(t *testing.T) {
expected := resmap.ResMap{
resource.NewResId(deploy, "dply1"): resource.NewResourceFromMap(
resource.NewResIdWithPrefix(deploy, "dply1", "foo-"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",

View File

@@ -56,7 +56,7 @@ func writeYamlToNewDir(in resmap.ResMap, prefix string) (*directory, error) {
}
for id, obj := range in {
f, err := dir.newFile(id.String())
f, err := dir.newFile(id.GvknString())
if err != nil {
return nil, err
}

View File

@@ -37,6 +37,26 @@ import (
// ResMap is a map from ResId to Resource.
type ResMap map[resource.ResId]*resource.Resource
// FindByGVKN find the matched ResIds by Group/Version/Kind and Name
func (m ResMap) FindByGVKN(inputId resource.ResId) []resource.ResId {
var result []resource.ResId
for id := range m {
if id.GvknEquals(inputId) {
result = append(result, id)
}
}
return result
}
// DemandOneMatchForId find the matched resource by Group/Version/Kind and Name
func (m ResMap) DemandOneMatchForId(inputId resource.ResId) (*resource.Resource, bool) {
result := m.FindByGVKN(inputId)
if len(result) == 1 {
return m[result[0]], true
}
return nil, false
}
// EncodeAsYaml encodes a ResMap to YAML; encoded objects separated by `---`.
func (m ResMap) EncodeAsYaml() ([]byte, error) {
var ids []resource.ResId
@@ -217,10 +237,12 @@ func MergeWithoutOverride(maps ...ResMap) (ResMap, error) {
// must be BehaviorMerge or BehaviorReplace. If X is not in the map, then it's
// behavior cannot be merge or replace.
func MergeWithOverride(maps ...ResMap) (ResMap, error) {
result := ResMap{}
for _, m := range maps {
result := maps[0]
for _, m := range maps[1:] {
for id, r := range m {
if _, found := result[id]; found {
matchedId := result.FindByGVKN(id)
if len(matchedId) == 1 {
id = matchedId[0]
switch r.Behavior() {
case resource.BehaviorReplace:
glog.V(4).Infof("Replace %v with %v", result[id].Object, r.Object)
@@ -236,13 +258,15 @@ func MergeWithOverride(maps ...ResMap) (ResMap, error) {
default:
return nil, fmt.Errorf("id %#v exists; must merge or replace", id)
}
} else {
} else if len(matchedId) == 0 {
switch r.Behavior() {
case resource.BehaviorMerge, resource.BehaviorReplace:
return nil, fmt.Errorf("id %#v does not exist; cannot merge or replace", id)
default:
result[id] = r
}
} else {
return nil, fmt.Errorf("Merge conflict, found multiple objects %v the Resmap %v can merge into", matchedId, id)
}
}
}

View File

@@ -28,18 +28,49 @@ type ResId struct {
gvk schema.GroupVersionKind
// original name of the resource before transformation.
name string
// namePrefix of the resource
// an untransformed resource has no prefix, fully transformed resource has an arbitrary number of prefixes
// concatenated together.
prefix string
}
// NewResIdWithPrefix creates new resource identifier with a prefix
func NewResIdWithPrefix(g schema.GroupVersionKind, n, p string) ResId {
return ResId{gvk: g, name: n, prefix: p}
}
// NewResId creates new resource identifier
func NewResId(g schema.GroupVersionKind, n string) ResId {
return ResId{gvk: g, name: n}
return NewResIdWithPrefix(g, n, "")
}
// String of ResId based on GVK, name and prefix
func (n ResId) String() string {
//var fields []string
//for _, s := range []string{n.gvk.Group, n.gvk.Version, n.gvk.Kind, n.prefix, n.name} {
// if s != "" {
// fields = append(fields, s)
// }
//}
//return strings.Join(fields, "_") + ".yaml"
fields := []string{n.gvk.Group, n.gvk.Version, n.gvk.Kind, n.prefix, n.name}
return strings.Join(fields, "_") + ".yaml"
}
// GvknString of ResId based on GVK and name
func (n ResId) GvknString() string {
if n.gvk.Group == "" {
return strings.Join([]string{n.gvk.Version, n.gvk.Kind, n.name}, "_") + ".yaml"
}
return strings.Join([]string{n.gvk.Group, n.gvk.Version, n.gvk.Kind, n.name}, "_") + ".yaml"
}
// GvknEquals return if two ResId have the same Group/Version/Kind and name
// The comparison excludes prefix
func (n ResId) GvknEquals(id ResId) bool {
return n.gvk.Group == id.gvk.Group && n.gvk.Version == id.gvk.Version &&
n.gvk.Kind == id.gvk.Kind && n.name == id.name
}
// Gvk returns Group/Version/Kind of the resource.
@@ -51,3 +82,13 @@ func (n ResId) Gvk() schema.GroupVersionKind {
func (n ResId) Name() string {
return n.name
}
// Prefix returns name prefix.
func (n ResId) Prefix() string {
return n.prefix
}
// CopyWithNewPrefix make a new copy from current ResId and append a new prefix
func (n ResId) CopyWithNewPrefix(p string) ResId {
return ResId{gvk: n.gvk, name: n.name, prefix: p + n.prefix}
}

View File

@@ -55,10 +55,15 @@ func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error {
for _, patch := range patches {
// Merge patches with base resource.
id := patch.Id()
base, found := baseResourceMap[id]
if !found {
matchedIds := baseResourceMap.FindByGVKN(id)
if len(matchedIds) == 0 {
return fmt.Errorf("failed to find an object with %#v to apply the patch", id.Gvk())
}
if len(matchedIds) > 1 {
return fmt.Errorf("Found multiple objects %#v that the patch %#v can apply", matchedIds, id)
}
id = matchedIds[0]
base := baseResourceMap[id]
merged := map[string]interface{}{}
versionedObj, err := scheme.Scheme.New(id.Gvk())
baseName := base.GetName()

View File

@@ -69,13 +69,17 @@ func (o *namePrefixTransformer) Transform(m resmap.ResMap) error {
mf := resmap.ResMap{}
for id := range m {
mf[id] = m[id]
found := false
for _, path := range o.skipPathConfigs {
if selectByGVK(id.Gvk(), path.GroupVersionKind) {
delete(mf, id)
found = true
break
}
}
if !found {
mf[id] = m[id]
delete(m, id)
}
}
for id := range mf {
@@ -88,6 +92,8 @@ func (o *namePrefixTransformer) Transform(m resmap.ResMap) error {
if err != nil {
return err
}
newId := id.CopyWithNewPrefix(o.prefix)
m[newId] = mf[id]
}
}
return nil

View File

@@ -53,7 +53,7 @@ func TestPrefixNameRun(t *testing.T) {
}),
}
expected := resmap.ResMap{
resource.NewResId(cmap, "cm1"): resource.NewResourceFromMap(
resource.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -61,7 +61,7 @@ func TestPrefixNameRun(t *testing.T) {
"name": "someprefix-cm1",
},
}),
resource.NewResId(cmap, "cm2"): resource.NewResourceFromMap(
resource.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): resource.NewResourceFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",