mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-13 01:50:55 +00:00
write create-substitution into command
This commit is contained in:
@@ -45,22 +45,23 @@ Advanced Documentation Topics:
|
|||||||
|
|
||||||
// Export commands publicly for composition
|
// Export commands publicly for composition
|
||||||
var (
|
var (
|
||||||
Annotate = commands.AnnotateCommand
|
Annotate = commands.AnnotateCommand
|
||||||
Cat = commands.CatCommand
|
Cat = commands.CatCommand
|
||||||
Count = commands.CountCommand
|
Count = commands.CountCommand
|
||||||
CreateSetter = commands.CreateSetterCommand
|
CreateSetter = commands.CreateSetterCommand
|
||||||
Fmt = commands.FmtCommand
|
CreateSubstitution = commands.CreateSubstitutionCommand
|
||||||
Grep = commands.GrepCommand
|
Fmt = commands.FmtCommand
|
||||||
ListSetters = commands.ListSettersCommand
|
Grep = commands.GrepCommand
|
||||||
Merge = commands.MergeCommand
|
ListSetters = commands.ListSettersCommand
|
||||||
Merge3 = commands.Merge3Command
|
Merge = commands.MergeCommand
|
||||||
RunFn = commands.RunFnCommand
|
Merge3 = commands.Merge3Command
|
||||||
Set = commands.SetCommand
|
RunFn = commands.RunFnCommand
|
||||||
Sink = commands.SinkCommand
|
Set = commands.SetCommand
|
||||||
Source = commands.SourceCommand
|
Sink = commands.SinkCommand
|
||||||
Tree = commands.TreeCommand
|
Source = commands.SourceCommand
|
||||||
Wrap = commands.WrapCommand
|
Tree = commands.TreeCommand
|
||||||
XArgs = commands.XArgsCommand
|
Wrap = commands.WrapCommand
|
||||||
|
XArgs = commands.XArgsCommand
|
||||||
|
|
||||||
StackOnError = &commands.StackOnError
|
StackOnError = &commands.StackOnError
|
||||||
ExitOnError = &commands.ExitOnError
|
ExitOnError = &commands.ExitOnError
|
||||||
@@ -107,6 +108,7 @@ func NewConfigCommand(name string) *cobra.Command {
|
|||||||
root.AddCommand(commands.SetCommand(name))
|
root.AddCommand(commands.SetCommand(name))
|
||||||
root.AddCommand(commands.ListSettersCommand(name))
|
root.AddCommand(commands.ListSettersCommand(name))
|
||||||
root.AddCommand(commands.CreateSetterCommand(name))
|
root.AddCommand(commands.CreateSetterCommand(name))
|
||||||
|
root.AddCommand(commands.CreateSubstitutionCommand(name))
|
||||||
root.AddCommand(commands.SinkCommand(name))
|
root.AddCommand(commands.SinkCommand(name))
|
||||||
root.AddCommand(commands.SourceCommand(name))
|
root.AddCommand(commands.SourceCommand(name))
|
||||||
|
|
||||||
|
|||||||
80
cmd/config/internal/commands/cmdcreatesubstitution.go
Normal file
80
cmd/config/internal/commands/cmdcreatesubstitution.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/setters2"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewCreateSubstitutionRunner returns a command runner.
|
||||||
|
func NewCreateSubstitutionRunner(parent string) *CreateSubstitutionRunner {
|
||||||
|
r := &CreateSubstitutionRunner{}
|
||||||
|
cs := &cobra.Command{
|
||||||
|
Use: "create-subst DIR NAME VALUE",
|
||||||
|
Args: cobra.ExactArgs(3),
|
||||||
|
PreRunE: r.preRunE,
|
||||||
|
RunE: r.runE,
|
||||||
|
}
|
||||||
|
cs.Flags().StringVar(&r.CreateSubstitution.FieldName, "field", "",
|
||||||
|
"name of the field to set -- e.g. --field port")
|
||||||
|
cs.Flags().StringVar(&r.CreateSubstitution.Pattern, "pattern", "",
|
||||||
|
"substitution pattern")
|
||||||
|
cs.Flags().StringSliceVar(&r.Values, "value", []string{""},
|
||||||
|
"substitution values for the pattern. format is PATTERN_MARKER=SETTER_NAME"+
|
||||||
|
"where PATTERN_MARKER is the pattern substring to replace, and SETTER_NAME is the"+
|
||||||
|
"setter from which to take the replacement value.")
|
||||||
|
_ = cs.MarkFlagRequired("pattern")
|
||||||
|
fixDocs(parent, cs)
|
||||||
|
r.Command = cs
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateSubstitutionCommand(parent string) *cobra.Command {
|
||||||
|
return NewCreateSubstitutionRunner(parent).Command
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateSubstitutionRunner struct {
|
||||||
|
Command *cobra.Command
|
||||||
|
CreateSubstitution settersutil.SubstitutionCreator
|
||||||
|
OpenAPIFile string
|
||||||
|
Values []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CreateSubstitutionRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
return handleError(c, r.CreateSubstitution.Create(r.OpenAPIFile, args[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CreateSubstitutionRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
r.CreateSubstitution.Name = args[1]
|
||||||
|
r.CreateSubstitution.FieldValue = args[2]
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.OpenAPIFile, err = GetOpenAPIFile(args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the marker values
|
||||||
|
for i := range r.Values {
|
||||||
|
parts := strings.SplitN(r.Values[i], "=", 2)
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return errors.Errorf("values must be specified as PATTERN_MARKER=SETTER_NAME")
|
||||||
|
}
|
||||||
|
ref := setters2.DefinitionsPrefix + setters2.SetterDefinitionPrefix + parts[1]
|
||||||
|
r.CreateSubstitution.Values = append(
|
||||||
|
r.CreateSubstitution.Values,
|
||||||
|
setters2.Value{Marker: parts[0], Ref: ref},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
171
cmd/config/internal/commands/cmdcreatesubstitution_test.go
Normal file
171
cmd/config/internal/commands/cmdcreatesubstitution_test.go
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateSubstitutionCommand(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
inputOpenAPI string
|
||||||
|
input string
|
||||||
|
args []string
|
||||||
|
out string
|
||||||
|
expectedOpenAPI string
|
||||||
|
expectedResources string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "substitution replicas",
|
||||||
|
args: []string{
|
||||||
|
"image", "nginx:1.7.9", "--pattern", "IMAGE:TAG",
|
||||||
|
"--value", "IMAGE=image", "--value", "TAG=tag"},
|
||||||
|
input: `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-deployment
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.7.9
|
||||||
|
- name: sidecar
|
||||||
|
image: sidecar:1.7.9
|
||||||
|
`,
|
||||||
|
inputOpenAPI: `
|
||||||
|
apiVersion: v1alpha1
|
||||||
|
kind: Example
|
||||||
|
openAPI:
|
||||||
|
definitions:
|
||||||
|
io.k8s.cli.setters.image:
|
||||||
|
x-k8s-cli:
|
||||||
|
setter:
|
||||||
|
name: image
|
||||||
|
value: "nginx"
|
||||||
|
io.k8s.cli.setters.tag:
|
||||||
|
x-k8s-cli:
|
||||||
|
setter:
|
||||||
|
name: tag
|
||||||
|
value: "1.7.9"
|
||||||
|
`,
|
||||||
|
expectedOpenAPI: `
|
||||||
|
apiVersion: v1alpha1
|
||||||
|
kind: Example
|
||||||
|
openAPI:
|
||||||
|
definitions:
|
||||||
|
io.k8s.cli.setters.image:
|
||||||
|
x-k8s-cli:
|
||||||
|
setter:
|
||||||
|
name: image
|
||||||
|
value: "nginx"
|
||||||
|
io.k8s.cli.setters.tag:
|
||||||
|
x-k8s-cli:
|
||||||
|
setter:
|
||||||
|
name: tag
|
||||||
|
value: "1.7.9"
|
||||||
|
io.k8s.cli.substitutions.image:
|
||||||
|
x-k8s-cli:
|
||||||
|
substitution:
|
||||||
|
name: image
|
||||||
|
pattern: IMAGE:TAG
|
||||||
|
values:
|
||||||
|
- marker: IMAGE
|
||||||
|
ref: '#/definitions/io.k8s.cli.setters.image'
|
||||||
|
- marker: TAG
|
||||||
|
ref: '#/definitions/io.k8s.cli.setters.tag'
|
||||||
|
`,
|
||||||
|
expectedResources: `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-deployment
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.7.9 # {"$ref":"#/definitions/io.k8s.cli.substitutions.image"}
|
||||||
|
- name: sidecar
|
||||||
|
image: sidecar:1.7.9
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i := range tests {
|
||||||
|
test := tests[i]
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
// reset the openAPI afterward
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
|
defer openapi.ResetOpenAPI()
|
||||||
|
|
||||||
|
f, err := ioutil.TempFile("", "k8s-cli-")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
defer os.Remove(f.Name())
|
||||||
|
err = ioutil.WriteFile(f.Name(), []byte(test.inputOpenAPI), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
commands.GetOpenAPIFile = func(args []string) (s string, err error) {
|
||||||
|
return f.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := ioutil.TempFile("", "k8s-cli-*.yaml")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
defer os.Remove(r.Name())
|
||||||
|
err = ioutil.WriteFile(r.Name(), []byte(test.input), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
runner := commands.NewCreateSubstitutionRunner("")
|
||||||
|
out := &bytes.Buffer{}
|
||||||
|
runner.Command.SetOut(out)
|
||||||
|
runner.Command.SetArgs(append([]string{r.Name()}, test.args...))
|
||||||
|
err = runner.Command.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, test.out, out.String()) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
actualResources, err := ioutil.ReadFile(r.Name())
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t,
|
||||||
|
strings.TrimSpace(test.expectedResources),
|
||||||
|
strings.TrimSpace(string(actualResources))) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
actualOpenAPI, err := ioutil.ReadFile(f.Name())
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t,
|
||||||
|
strings.TrimSpace(test.expectedOpenAPI),
|
||||||
|
strings.TrimSpace(string(actualOpenAPI))) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user