mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-10 08:20:59 +00:00
setters 2.0: support for adding references to setters
This commit is contained in:
@@ -17,7 +17,7 @@ import (
|
||||
type FieldMeta struct {
|
||||
Schema spec.Schema
|
||||
|
||||
Extensions XKustomize
|
||||
Extensions *XKustomize
|
||||
}
|
||||
|
||||
type XKustomize struct {
|
||||
@@ -64,7 +64,11 @@ func (fm *FieldMeta) Read(n *yaml.RNode) error {
|
||||
|
||||
// Write writes the FieldMeta to a node
|
||||
func (fm *FieldMeta) Write(n *yaml.RNode) error {
|
||||
fm.Schema.VendorExtensible.AddExtension("x-kustomize", fm.Extensions)
|
||||
if fm.Extensions != nil {
|
||||
fm.Schema.VendorExtensible.AddExtension("x-kustomize", fm.Extensions)
|
||||
} else {
|
||||
delete(fm.Schema.VendorExtensible.Extensions, "x-kustomize")
|
||||
}
|
||||
b, err := json.Marshal(fm.Schema)
|
||||
if err != nil {
|
||||
return errors.Wrap(err)
|
||||
|
||||
74
kyaml/setters2/add.go
Normal file
74
kyaml/setters2/add.go
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package setters2
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
// Add creates or updates setter or substitution references from resource fields.
|
||||
// Requires that at least one of FieldValue and FieldName have been set.
|
||||
type Add struct {
|
||||
// FieldValue if set will add the OpenAPI reference to fields if they have this value.
|
||||
// Optional. If unspecified match all field values.
|
||||
FieldValue string
|
||||
|
||||
// FieldName if set will add the OpenAPI reference to fields with this name or path
|
||||
// FieldName may be the full name of the field, full path to the field, or the path suffix.
|
||||
// e.g. all of the following would match spec.template.spec.containers.image --
|
||||
// [image, containers.image, spec.containers.image, template.spec.containers.image,
|
||||
// spec.template.spec.containers.image]
|
||||
// Optional. If unspecified match all field names.
|
||||
FieldName string
|
||||
|
||||
// Ref is the OpenAPI reference to set on the matching fields as a comment.
|
||||
Ref string
|
||||
}
|
||||
|
||||
// Filter implements yaml.Filter
|
||||
func (a *Add) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
if a.FieldName == "" && a.FieldValue == "" {
|
||||
return nil, errors.Errorf("must specify either fieldName or fieldValue")
|
||||
}
|
||||
if a.Ref == "" {
|
||||
return nil, errors.Errorf("must specify ref")
|
||||
}
|
||||
return object, accept(a, object)
|
||||
}
|
||||
|
||||
// visitScalar implements visitor
|
||||
// visitScalar will set the field metadata on each scalar field whose name + value match
|
||||
func (a *Add) visitScalar(object *yaml.RNode, p string) error {
|
||||
// check if the field matches
|
||||
if a.FieldName != "" && !strings.HasSuffix(p, a.FieldName) {
|
||||
return nil
|
||||
}
|
||||
if a.FieldValue != "" && a.FieldValue != object.YNode().Value {
|
||||
return nil
|
||||
}
|
||||
|
||||
// read the field metadata
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(object); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create the ref on the field metadata
|
||||
r, err := spec.NewRef(a.Ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fm.Schema.Ref = r
|
||||
|
||||
// write the field metadata
|
||||
if err := fm.Write(object); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
206
kyaml/setters2/add_test.go
Normal file
206
kyaml/setters2/add_test.go
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package setters2
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func TestAdd_Filter(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
add Add
|
||||
input string
|
||||
expected string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "add-replicas",
|
||||
add: Add{
|
||||
FieldValue: "3",
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
},
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "add-replicas-annotations",
|
||||
add: Add{
|
||||
FieldValue: "3",
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
},
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
something: 3
|
||||
spec:
|
||||
replicas: 3
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
something: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
spec:
|
||||
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "add-replicas-name",
|
||||
add: Add{
|
||||
FieldValue: "3",
|
||||
FieldName: "replicas",
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
},
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
something: 3
|
||||
spec:
|
||||
replicas: 3
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
something: 3
|
||||
spec:
|
||||
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "add-replicas-2x",
|
||||
add: Add{
|
||||
FieldValue: "3",
|
||||
FieldName: "replicas",
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
},
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
replicas: 3
|
||||
spec:
|
||||
replicas: 3
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
spec:
|
||||
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "add-replicas-1x",
|
||||
add: Add{
|
||||
FieldValue: "3",
|
||||
FieldName: "spec.replicas",
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
},
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
replicas: 3
|
||||
spec:
|
||||
replicas: 3
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
replicas: 3
|
||||
spec:
|
||||
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "add-replicas-error",
|
||||
add: Add{
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
},
|
||||
err: "must specify either fieldName or fieldValue",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
`,
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
test := tests[i]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// parse the input to be modified
|
||||
r, err := yaml.Parse(test.input)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// invoke add
|
||||
result, err := test.add.Filter(r)
|
||||
if test.err != "" {
|
||||
if !assert.Equal(t, test.err, err.Error()) {
|
||||
t.FailNow()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// compare the actual and expected output
|
||||
actual, err := result.String()
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
actual = strings.TrimSpace(actual)
|
||||
expected := strings.TrimSpace(test.expected)
|
||||
if !assert.Equal(t, expected, actual) {
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -154,4 +154,10 @@
|
||||
// to "1.8.2", then calling either Set{Name: "image-name"}.Filter(deployment) or
|
||||
// Set{Name: "image-tag"}.Filter(deployment) would update the Deployment field
|
||||
// spec.template.spec.container[name=nginx].image from "nginx:1.8.1" to "nginx:1.8.2".
|
||||
//
|
||||
// Adding Field References
|
||||
//
|
||||
// References to setters and substitutions may be added to fields using the Add Filter.
|
||||
// Add will write a JSON OpenAPI string as a comment to any fields matching the specified
|
||||
// FieldName add FieldValue.
|
||||
package setters2
|
||||
|
||||
@@ -128,3 +128,75 @@ spec:
|
||||
// - name: nginx
|
||||
// image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
}
|
||||
|
||||
// ExampleAdd demonstrates adding a setter reference to fields.
|
||||
func ExampleAdd_fieldName() {
|
||||
deployment := `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
something: 3
|
||||
spec:
|
||||
replicas: 3
|
||||
`
|
||||
|
||||
object := yaml.MustParse(deployment) // parse the configuration
|
||||
err := object.PipeE(&Add{
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
FieldName: "replicas",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Print the object with the update value
|
||||
fmt.Println(object.MustString())
|
||||
|
||||
// Output:
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: nginx-deployment
|
||||
// annotations:
|
||||
// something: 3
|
||||
// spec:
|
||||
// replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
}
|
||||
|
||||
// ExampleAdd demonstrates adding a setter reference to fields.
|
||||
func ExampleAdd_fieldValue() {
|
||||
deployment := `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
something: 3
|
||||
spec:
|
||||
replicas: 3
|
||||
`
|
||||
|
||||
object := yaml.MustParse(deployment) // parse the configuration
|
||||
err := object.PipeE(&Add{
|
||||
Ref: "#/definitions/io.k8s.cli.setters.replicas",
|
||||
FieldValue: "3",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Print the object with the update value
|
||||
fmt.Println(object.MustString())
|
||||
|
||||
// Output:
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: nginx-deployment
|
||||
// annotations:
|
||||
// something: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
// spec:
|
||||
// replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user