diff --git a/plugin/builtin/ImageTagTransformer.go b/plugin/builtin/ImageTagTransformer.go index 43273339e..a2ae13e43 100644 --- a/plugin/builtin/ImageTagTransformer.go +++ b/plugin/builtin/ImageTagTransformer.go @@ -59,30 +59,28 @@ func (p *ImageTagTransformerPlugin) mutateImage(in interface{}) (interface{}, er return nil, fmt.Errorf("image path is not of type string but %T", in) } - nTag := p.ImageTag - if !isImageMatched(original, nTag.Name) { + if !isImageMatched(original, p.ImageTag.Name) { return original, nil } name, tag := split(original) - if nTag.NewName != "" { - name = nTag.NewName + if p.ImageTag.NewName != "" { + name = p.ImageTag.NewName } - if nTag.NewTag != "" { - tag = ":" + nTag.NewTag + if p.ImageTag.NewTag != "" { + tag = ":" + p.ImageTag.NewTag } - if nTag.Digest != "" { - tag = "@" + nTag.Digest + if p.ImageTag.Digest != "" { + tag = "@" + p.ImageTag.Digest } return name + tag, nil - } -/* - findAndReplaceImage replaces the image name and tags inside one object - It searches the object for container session - then loops though all images inside containers session, - finds matched ones and update the image name and tag name -*/ +// findAndReplaceImage replaces the image name and +// tags inside one object. +// It searches the object for container session +// then loops though all images inside containers +// session, finds matched ones and update the +// image name and tag name func (p *ImageTagTransformerPlugin) findAndReplaceImage(obj map[string]interface{}) error { paths := []string{"containers", "initContainers"} updated := false @@ -104,7 +102,8 @@ func (p *ImageTagTransformerPlugin) findAndReplaceImage(obj map[string]interface func (p *ImageTagTransformerPlugin) updateContainers(in interface{}) (interface{}, error) { containers, ok := in.([]interface{}) if !ok { - return nil, fmt.Errorf("containers path is not of type []interface{} but %T", in) + return nil, fmt.Errorf( + "containers path is not of type []interface{} but %T", in) } for i := range containers { container := containers[i].(map[string]interface{}) @@ -112,7 +111,6 @@ func (p *ImageTagTransformerPlugin) updateContainers(in interface{}) (interface{ if !found { continue } - imageName := containerImage.(string) if isImageMatched(imageName, p.ImageTag.Name) { newImage, err := p.mutateImage(imageName) diff --git a/plugin/builtin/NamespaceTransformer.go b/plugin/builtin/NamespaceTransformer.go index 0e89ca54b..66e83d760 100644 --- a/plugin/builtin/NamespaceTransformer.go +++ b/plugin/builtin/NamespaceTransformer.go @@ -2,8 +2,11 @@ package builtin import ( + "sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/transformers" "sigs.k8s.io/kustomize/pkg/transformers/config" "sigs.k8s.io/yaml" @@ -28,6 +31,96 @@ func (p *NamespaceTransformerPlugin) Config( } func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error { - return transformers.NewNamespaceTransformer( - p.Namespace, p.FieldSpecs).Transform(m) + if len(p.Namespace) == 0 { + return nil + } + for _, r := range m.Resources() { + id := r.OrgId() + fs, ok := p.isSelected(id) + if !ok { + continue + } + if len(r.Map()) == 0 { + // Don't mutate empty objects? + continue + } + if doIt(id, fs) { + if err := p.changeNamespace(r, fs); err != nil { + return err + } + } + } + p.updateClusterRoleBinding(m) + return nil +} + +const metaNamespace = "metadata/namespace" + +// Special casing metadata.namespace since +// all objects have it, even "ClusterKind" objects +// that don't exist in a namespace (the Namespace +// object itself doesn't live in a namespace). +func doIt(id resid.ResId, fs *config.FieldSpec) bool { + return fs.Path != metaNamespace || + (fs.Path == metaNamespace && !id.IsClusterKind()) +} + +func (p *NamespaceTransformerPlugin) changeNamespace( + r *resource.Resource, fs *config.FieldSpec) error { + return transformers.MutateField( + r.Map(), fs.PathSlice(), fs.CreateIfNotPresent, + func(_ interface{}) (interface{}, error) { + return p.Namespace, nil + }) +} + +func (p *NamespaceTransformerPlugin) isSelected( + id resid.ResId) (*config.FieldSpec, bool) { + for _, fs := range p.FieldSpecs { + if id.IsSelected(&fs.Gvk) { + return &fs, true + } + } + return nil, false +} + +func (p *NamespaceTransformerPlugin) updateClusterRoleBinding(m resmap.ResMap) { + srvAccount := gvk.Gvk{Version: "v1", Kind: "ServiceAccount"} + saMap := map[string]bool{} + for _, id := range m.AllIds() { + if id.Gvk.Equals(srvAccount) { + saMap[id.Name] = true + } + } + + for _, res := range m.Resources() { + if res.OrgId().Kind != "ClusterRoleBinding" && + res.OrgId().Kind != "RoleBinding" { + continue + } + objMap := res.Map() + subjects, ok := objMap["subjects"].([]interface{}) + if subjects == nil || !ok { + continue + } + for i := range subjects { + subject := subjects[i].(map[string]interface{}) + kind, foundK := subject["kind"] + name, foundN := subject["name"] + if !foundK || !foundN || kind.(string) != srvAccount.Kind { + continue + } + // a ServiceAccount named “default” exists in every active namespace + if name.(string) == "default" || saMap[name.(string)] { + subject := subjects[i].(map[string]interface{}) + transformers.MutateField( + subject, []string{"namespace"}, + true, func(_ interface{}) (interface{}, error) { + return p.Namespace, nil + }) + subjects[i] = subject + } + } + objMap["subjects"] = subjects + } }