mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-12 01:14:22 +00:00
Function framework support for patching containers
This commit is contained in:
60
kyaml/fn/framework/containers.go
Normal file
60
kyaml/fn/framework/containers.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package framework
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml/merge2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PatchTemplateContainers executes t as a template and patches each container in each resource
|
||||||
|
// with the result.
|
||||||
|
func PatchTemplateContainers(resources []*yaml.RNode, t string, input interface{}, containers ...string) error {
|
||||||
|
resourcePatch := template.Must(template.New("containers").Parse(t))
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := resourcePatch.Execute(&b, input); err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
patch, err := yaml.Parse(b.String())
|
||||||
|
if err != nil {
|
||||||
|
return errors.WrapPrefixf(err, b.String())
|
||||||
|
}
|
||||||
|
return PatchContainers(resources, patch, containers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PatchContainers applies patch to each container in each resource.
|
||||||
|
func PatchContainers(resources []*yaml.RNode, patch *yaml.RNode, containers ...string) error {
|
||||||
|
names := sets.String{}
|
||||||
|
names.Insert(containers...)
|
||||||
|
|
||||||
|
for i := range resources {
|
||||||
|
containers, err := resources[i].Pipe(yaml.Lookup("spec", "template", "spec", "containers"))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
if containers == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = containers.VisitElements(func(node *yaml.RNode) error {
|
||||||
|
f := node.Field("name")
|
||||||
|
if f == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if names.Len() > 0 && !names.Has(yaml.GetValue(f.Value)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_, err := merge2.Merge(patch, node, yaml.MergeOptions{})
|
||||||
|
return errors.Wrap(err)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -6,12 +6,14 @@ package framework_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"sigs.k8s.io/kustomize/kyaml/fn/framework"
|
"sigs.k8s.io/kustomize/kyaml/fn/framework"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -890,3 +892,226 @@ metadata:
|
|||||||
// key: bar
|
// key: bar
|
||||||
// config.kubernetes.io/index: '1'
|
// config.kubernetes.io/index: '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExamplePatchTemplateContainers_names patches all containers.
|
||||||
|
func ExamplePatchTemplateContainers() {
|
||||||
|
resources, err := kio.ParseAll(`
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: foo
|
||||||
|
image: a
|
||||||
|
- name: bar
|
||||||
|
image: b
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
foo: bar
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: bar
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: foo
|
||||||
|
image: a
|
||||||
|
- name: baz
|
||||||
|
image: b
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: bar
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
foo: bar
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
input := struct{ Value string }{Value: "new-value"}
|
||||||
|
err = framework.PatchTemplateContainers(resources, `
|
||||||
|
env:
|
||||||
|
KEY: {{ .Value }}
|
||||||
|
`, input)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(kio.StringAll(resources))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// apiVersion: apps/v1
|
||||||
|
// kind: Deployment
|
||||||
|
// metadata:
|
||||||
|
// name: foo
|
||||||
|
// spec:
|
||||||
|
// template:
|
||||||
|
// spec:
|
||||||
|
// containers:
|
||||||
|
// - name: foo
|
||||||
|
// image: a
|
||||||
|
// env:
|
||||||
|
// KEY: new-value
|
||||||
|
// - name: bar
|
||||||
|
// image: b
|
||||||
|
// env:
|
||||||
|
// KEY: new-value
|
||||||
|
// ---
|
||||||
|
// apiVersion: v1
|
||||||
|
// kind: Service
|
||||||
|
// metadata:
|
||||||
|
// name: foo
|
||||||
|
// spec:
|
||||||
|
// selector:
|
||||||
|
// foo: bar
|
||||||
|
// ---
|
||||||
|
// apiVersion: apps/v1
|
||||||
|
// kind: Deployment
|
||||||
|
// metadata:
|
||||||
|
// name: bar
|
||||||
|
// spec:
|
||||||
|
// template:
|
||||||
|
// spec:
|
||||||
|
// containers:
|
||||||
|
// - name: foo
|
||||||
|
// image: a
|
||||||
|
// env:
|
||||||
|
// KEY: new-value
|
||||||
|
// - name: baz
|
||||||
|
// image: b
|
||||||
|
// env:
|
||||||
|
// KEY: new-value
|
||||||
|
// ---
|
||||||
|
// apiVersion: v1
|
||||||
|
// kind: Service
|
||||||
|
// metadata:
|
||||||
|
// name: bar
|
||||||
|
// spec:
|
||||||
|
// selector:
|
||||||
|
// foo: bar
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExamplePatchTemplateContainers_names patches containers matching
|
||||||
|
// a specific name.
|
||||||
|
func ExamplePatchTemplateContainers_names() {
|
||||||
|
resources, err := kio.ParseAll(`
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: foo
|
||||||
|
image: a
|
||||||
|
- name: bar
|
||||||
|
image: b
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
foo: bar
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: bar
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: foo
|
||||||
|
image: a
|
||||||
|
- name: baz
|
||||||
|
image: b
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: bar
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
foo: bar
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
input := struct{ Value string }{Value: "new-value"}
|
||||||
|
err = framework.PatchTemplateContainers(resources, `
|
||||||
|
env:
|
||||||
|
KEY: {{ .Value }}
|
||||||
|
`, input, "foo")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(kio.StringAll(resources))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// apiVersion: apps/v1
|
||||||
|
// kind: Deployment
|
||||||
|
// metadata:
|
||||||
|
// name: foo
|
||||||
|
// spec:
|
||||||
|
// template:
|
||||||
|
// spec:
|
||||||
|
// containers:
|
||||||
|
// - name: foo
|
||||||
|
// image: a
|
||||||
|
// env:
|
||||||
|
// KEY: new-value
|
||||||
|
// - name: bar
|
||||||
|
// image: b
|
||||||
|
// ---
|
||||||
|
// apiVersion: v1
|
||||||
|
// kind: Service
|
||||||
|
// metadata:
|
||||||
|
// name: foo
|
||||||
|
// spec:
|
||||||
|
// selector:
|
||||||
|
// foo: bar
|
||||||
|
// ---
|
||||||
|
// apiVersion: apps/v1
|
||||||
|
// kind: Deployment
|
||||||
|
// metadata:
|
||||||
|
// name: bar
|
||||||
|
// spec:
|
||||||
|
// template:
|
||||||
|
// spec:
|
||||||
|
// containers:
|
||||||
|
// - name: foo
|
||||||
|
// image: a
|
||||||
|
// env:
|
||||||
|
// KEY: new-value
|
||||||
|
// - name: baz
|
||||||
|
// image: b
|
||||||
|
// ---
|
||||||
|
// apiVersion: v1
|
||||||
|
// kind: Service
|
||||||
|
// metadata:
|
||||||
|
// name: bar
|
||||||
|
// spec:
|
||||||
|
// selector:
|
||||||
|
// foo: bar
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
|||||||
@@ -78,6 +78,20 @@ func (rw *ByteReadWriter) Write(nodes []*yaml.RNode) error {
|
|||||||
}.Write(nodes)
|
}.Write(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseAll reads all of the inputs into resources
|
||||||
|
func ParseAll(inputs ...string) ([]*yaml.RNode, error) {
|
||||||
|
return (&ByteReader{
|
||||||
|
Reader: bytes.NewBufferString(strings.Join(inputs, "\n---\n")),
|
||||||
|
}).Read()
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringAll writes all of the resources to a string
|
||||||
|
func StringAll(resources []*yaml.RNode) (string, error) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
err := (&ByteWriter{Writer: &b}).Write(resources)
|
||||||
|
return b.String(), err
|
||||||
|
}
|
||||||
|
|
||||||
// ByteReader decodes ResourceNodes from bytes.
|
// ByteReader decodes ResourceNodes from bytes.
|
||||||
// By default, Read will set the config.kubernetes.io/index annotation on each RNode as it
|
// By default, Read will set the config.kubernetes.io/index annotation on each RNode as it
|
||||||
// is read so they can be written back in the same order.
|
// is read so they can be written back in the same order.
|
||||||
|
|||||||
Reference in New Issue
Block a user