Merge pull request #592 from Liujingfang1/namereference

resolve namereference in an array
This commit is contained in:
Jeff Regan
2018-12-04 15:51:00 -08:00
committed by GitHub
3 changed files with 168 additions and 17 deletions

View File

@@ -226,6 +226,10 @@ nameReference:
kind: StorageClass
- path: parameters/secretRef
kind: StorageClass
- path: rules/resourceNames
kind: Role
- path: rules/resourceNames
kind: ClusterRole
- kind: Service
version: v1

View File

@@ -71,24 +71,61 @@ func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error {
func (o *nameReferenceTransformer) updateNameReference(
backRef gvk.Gvk, m resmap.ResMap) func(in interface{}) (interface{}, error) {
return func(in interface{}) (interface{}, error) {
s, ok := in.(string)
if !ok {
return nil, fmt.Errorf("%#v is expected to be %T", in, s)
}
for id, res := range m {
if id.Gvk().IsSelected(&backRef) && id.Name() == s {
matchedIds := m.FindByGVKN(id)
// If there's more than one match, there's no way
// to know which one to pick, so emit error.
if len(matchedIds) > 1 {
return nil, fmt.Errorf(
"Multiple matches for name %s:\n %v", id, matchedIds)
switch in.(type) {
case string:
s, _ := in.(string)
for id, res := range m {
if id.Gvk().IsSelected(&backRef) && id.Name() == s {
matchedIds := m.FindByGVKN(id)
// If there's more than one match, there's no way
// to know which one to pick, so emit error.
if len(matchedIds) > 1 {
return nil, fmt.Errorf(
"Multiple matches for name %s:\n %v", id, matchedIds)
}
// Return transformed name of the object,
// complete with prefixes, hashes, etc.
return res.GetName(), nil
}
// Return transformed name of the object,
// complete with prefixes, hashes, etc.
return res.GetName(), nil
}
return in, nil
case []interface{}:
l, _ := in.([]interface{})
var names []string
for _, item := range l {
name, ok := item.(string)
if !ok {
return nil, fmt.Errorf("%#v is expected to be %T", item, name)
}
names = append(names, name)
}
for id, res := range m {
indexes := indexOf(id.Name(), names)
if id.Gvk().IsSelected(&backRef) && len(indexes) > 0 {
matchedIds := m.FindByGVKN(id)
if len(matchedIds) > 1 {
return nil, fmt.Errorf(
"Multiple matches for name %s:\n %v", id, matchedIds)
}
for _, index := range indexes {
l[index] = res.GetName()
}
return l, nil
}
}
return in, nil
default:
return nil, fmt.Errorf("%#v is expected to be either a string or a []interface{}", in)
}
return in, nil
}
}
func indexOf(s string, slice []string) []int {
var index []int
for i, item := range slice {
if item == s {
index = append(index, i)
}
}
return index
}

View File

@@ -18,6 +18,7 @@ package transformers
import (
"reflect"
"strings"
"testing"
"sigs.k8s.io/kustomize/k8sdeps/kunstruct"
@@ -26,7 +27,7 @@ import (
"sigs.k8s.io/kustomize/pkg/resource"
)
func TestNameReferenceRun(t *testing.T) {
func TestNameReferenceHappyRun(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
m := resmap.ResMap{
@@ -214,6 +215,26 @@ func TestNameReferenceRun(t *testing.T) {
},
},
}),
resid.NewResId(cr, "cr"): rf.FromMap(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": "cr",
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"secrets",
},
"resourceNames": []interface{}{
"secret1",
"secret1",
"secret2",
},
},
},
}),
}
expected := resmap.ResMap{}
@@ -364,6 +385,26 @@ func TestNameReferenceRun(t *testing.T) {
},
},
})
expected[resid.NewResId(cr, "cr")] = rf.FromMap(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": "cr",
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"secrets",
},
"resourceNames": []interface{}{
"someprefix-secret1-somehash",
"someprefix-secret1-somehash",
"secret2",
},
},
},
})
nrt, err := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
if err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -377,3 +418,72 @@ func TestNameReferenceRun(t *testing.T) {
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestNameReferenceUnhappyRun(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
tests := []struct {
resMap resmap.ResMap
expectedErr string
}{
{
resMap: resmap.ResMap{
resid.NewResId(cr, "cr"): rf.FromMap(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": "cr",
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"secrets",
},
"resourceNames": []interface{}{
[]interface{}{},
},
},
},
}),
},
expectedErr: "is expected to be string"},
{resMap: resmap.ResMap{
resid.NewResId(cr, "cr"): rf.FromMap(
map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": "cr",
},
"rules": []interface{}{
map[string]interface{}{
"resources": []interface{}{
"secrets",
},
"resourceNames": map[string]interface{}{
"foo": "bar",
},
},
},
}),
},
expectedErr: "is expected to be either a string or a []interface{}"},
}
nrt, err := NewNameReferenceTransformer(defaultTransformerConfig.NameReference)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
for _, test := range tests {
err = nrt.Transform(test.resMap)
if err == nil {
t.Fatalf("expected error to happen")
}
if !strings.Contains(err.Error(), test.expectedErr) {
t.Fatalf("Incorrect error.\nExpected: %s, but got %v", test.expectedErr, err)
}
}
}