diff --git a/pkg/plugins/execplugin.go b/pkg/plugins/execplugin.go index 604757715..2f2344a23 100644 --- a/pkg/plugins/execplugin.go +++ b/pkg/plugins/execplugin.go @@ -35,6 +35,7 @@ import ( const ( ArgsOneLiner = "argsOneLiner" ArgsFromFile = "argsFromFile" + idAnnotation = "kustomize.config.k8s.io/id" ) // ExecPlugin record the name and args of an executable @@ -155,34 +156,26 @@ func (p *ExecPlugin) Transform(rm resmap.ResMap) error { if err != nil { return err } - for id, r := range rm { - content, err := yaml.Marshal(r.Kunstructured) - if err != nil { - return err - } - cmd := exec.Command(p.name, args...) - cmd.Env = p.getEnv() - cmd.Stdin = bytes.NewReader(content) - cmd.Stderr = os.Stderr - if _, err := os.Stat(p.ldr.Root()); err == nil { - cmd.Dir = p.ldr.Root() - } - output, err := cmd.Output() - if err != nil { - return err - } - tmpMap, err := p.rf.NewResMapFromBytes(output) - if err != nil { - return err - } - if len(tmpMap) != 1 { - return fmt.Errorf("unable to put two resources into one") - } - for _, v := range tmpMap { - rm[id].Kunstructured = v.Kunstructured - } + + inputRM := p.getResMapWithIdAnnotation(rm) + resources, err := inputRM.EncodeAsYaml() + if err != nil { + return err } - return nil + + cmd := exec.Command(p.name, args...) + cmd.Env = p.getEnv() + cmd.Stdin = bytes.NewReader(resources) + cmd.Stderr = os.Stderr + if _, err := os.Stat(p.ldr.Root()); err == nil { + cmd.Dir = p.ldr.Root() + } + output, err := cmd.Output() + if err != nil { + return err + } + + return p.parseResMapFromOutput(output, rm) } // The first arg is always the absolute path to a temporary file @@ -202,3 +195,43 @@ func (p *ExecPlugin) getEnv() []string { "KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.ldr.Root()) return env } + +func (p *ExecPlugin) getResMapWithIdAnnotation(rm resmap.ResMap) resmap.ResMap { + inputRM := rm.DeepCopy(p.rf.RF()) + for id, r := range inputRM { + annotations := r.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + annotations[idAnnotation] = id.String() + r.SetAnnotations(annotations) + } + return inputRM +} + +func (p *ExecPlugin) parseResMapFromOutput(output []byte, rm resmap.ResMap) error { + outputRM, err := p.rf.NewResMapFromBytes(output) + if err != nil { + return err + } + for _, r := range outputRM { + annotations := r.GetAnnotations() + idString, ok := annotations[idAnnotation] + if !ok { + return fmt.Errorf("the transformer %s should not remove annotation %s", + p.name, idAnnotation) + } + id, err := resid.NewResIdFromString(idString) + if err != nil { + return err + } + res, ok := rm[id] + if !ok { + return fmt.Errorf("unable to find id %s in resource map", id.String()) + } + delete(annotations, idAnnotation) + r.SetAnnotations(annotations) + res.Kunstructured = r.Kunstructured + } + return nil +} diff --git a/pkg/resid/resid.go b/pkg/resid/resid.go index 68d92e345..bdff411fb 100644 --- a/pkg/resid/resid.go +++ b/pkg/resid/resid.go @@ -17,6 +17,7 @@ limitations under the License. package resid import ( + "fmt" "strings" "sigs.k8s.io/kustomize/pkg/gvk" @@ -99,6 +100,38 @@ func (n ResId) String() string { []string{n.ItemId.Gvk.String(), ns, p, nm, s}, separator) } +// NewResIdFromString makes a ResId from a string which represents a Resid +func NewResIdFromString(s string) (ResId, error) { + values := strings.Split(s, separator) + if len(values) != 5 { + return ResId{}, fmt.Errorf("The input string %s doesn't represent a ResId", s) + } + + g := gvk.FromString(values[0]) + ns := values[1] + p := values[2] + nm := values[3] + su := values[4] + if ns == noNamespace { + ns = "" + } + if p == noPrefix { + p = "" + } + if nm == noName { + nm = "" + } + if su == noSuffix { + su = "" + } + return ResId{ + ItemId: NewItemId(g, ns, nm), + prefix: p, + suffix: su, + }, nil + +} + // GvknString of ResId based on GVK and name func (n ResId) GvknString() string { return n.ItemId.Gvk.String() + separator + n.ItemId.Name diff --git a/pkg/target/transformerplugin_test.go b/pkg/target/transformerplugin_test.go index 6f22323a1..6a9e7c2de 100644 --- a/pkg/target/transformerplugin_test.go +++ b/pkg/target/transformerplugin_test.go @@ -144,6 +144,7 @@ data: FOO: foo kind: ConfigMap metadata: + annotations: {} name: test-k4bkhftttd `) }