diff --git a/pkg/resmap/resmap.go b/pkg/resmap/resmap.go index d0a2586fd..60ec6f131 100644 --- a/pkg/resmap/resmap.go +++ b/pkg/resmap/resmap.go @@ -140,6 +140,18 @@ func (m ResMap) insert(newName string, obj *unstructured.Unstructured) error { return nil } +// FilterBy returns a ResMap containing ResIds with the same namespace and nameprefix +// with the inputId +func (m ResMap) FilterBy(inputId resource.ResId) ResMap { + result := ResMap{} + for id, res := range m { + if id.Namespace() == inputId.Namespace() && id.HasSamePrefix(inputId) { + result[id] = res + } + } + return result +} + // NewResourceSliceFromPatches returns a slice of resources given a patch path slice from a kustomization file. func NewResourceSliceFromPatches( loader loader.Loader, paths []patch.PatchStrategicMerge) ([]*resource.Resource, error) { diff --git a/pkg/resource/resid.go b/pkg/resource/resid.go index 5104a81cd..563e8701e 100644 --- a/pkg/resource/resid.go +++ b/pkg/resource/resid.go @@ -97,10 +97,35 @@ func (n ResId) Namespace() string { // 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, namespace: n.namespace} + return ResId{gvk: n.gvk, name: n.name, prefix: n.concatePrefix(p), namespace: n.namespace} } // CopyWithNewNamespace make a new copy from current ResId and set a new namespace func (n ResId) CopyWithNewNamespace(ns string) ResId { return ResId{gvk: n.gvk, name: n.name, prefix: n.prefix, namespace: ns} } + +// HasSamePrefix check if two ResIds have the same leading prefix +func (n ResId) HasSamePrefix(id ResId) bool { + prefixes1 := n.prefixList() + prefixes2 := id.prefixList() + return len(prefixes1) == 0 || len(prefixes2) == 0 || prefixes1[0] == prefixes2[0] +} + +func (n ResId) concatePrefix(p string) string { + if p == "" { + return n.prefix + } + if n.prefix == "" { + return p + } + return p + ":" + n.prefix +} + +func (n ResId) prefixList() []string { + var plist []string + if n.prefix == "" { + return plist + } + return strings.Split(n.prefix, ":") +} diff --git a/pkg/transformers/namereference.go b/pkg/transformers/namereference.go index 008f76fc4..89e887b01 100644 --- a/pkg/transformers/namereference.go +++ b/pkg/transformers/namereference.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/kubernetes-sigs/kustomize/pkg/resmap" + "github.com/kubernetes-sigs/kustomize/pkg/resource" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -58,7 +59,7 @@ func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error { continue } err := mutateField(objMap, path.Path, path.CreateIfNotPresent, - o.updateNameReference(referencePathConfig.referencedGVK, m)) + o.updateNameReference(referencePathConfig.referencedGVK, m.FilterBy(id))) if err != nil { return err } @@ -81,9 +82,21 @@ func (o *nameReferenceTransformer) updateNameReference( continue } if id.Name() == s { + err := o.detectConflict(id, m, s) + if err != nil { + return nil, err + } return res.GetName(), nil } } return in, nil } } + +func (o *nameReferenceTransformer) detectConflict(id resource.ResId, m resmap.ResMap, name string) error { + matchedIds := m.FindByGVKN(id) + if len(matchedIds) > 1 { + return fmt.Errorf("detected conflicts when resolving name references %s:\n%v", name, matchedIds) + } + return nil +}