mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Annotate With Subpackages
Delete Setters And Subst With Subpkgs
This commit is contained in:
@@ -4,9 +4,12 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
@@ -31,6 +34,8 @@ func NewAnnotateRunner(parent string) *AnnotateRunner {
|
|||||||
c.Flags().StringVar(&r.Name, "name", "", "Resource name to annotate")
|
c.Flags().StringVar(&r.Name, "name", "", "Resource name to annotate")
|
||||||
c.Flags().StringVar(&r.Namespace, "namespace", "", "Resource namespace to annotate")
|
c.Flags().StringVar(&r.Namespace, "namespace", "", "Resource namespace to annotate")
|
||||||
c.Flags().StringSliceVar(&r.Values, "kv", []string{}, "annotation as KEY=VALUE")
|
c.Flags().StringSliceVar(&r.Values, "kv", []string{}, "annotation as KEY=VALUE")
|
||||||
|
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false,
|
||||||
|
"add annotations recursively in all the nested subpackages")
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +51,7 @@ type AnnotateRunner struct {
|
|||||||
ApiVersion string
|
ApiVersion string
|
||||||
Namespace string
|
Namespace string
|
||||||
Path string
|
Path string
|
||||||
|
RecurseSubPackages bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AnnotateRunner) runE(c *cobra.Command, args []string) error {
|
func (r *AnnotateRunner) runE(c *cobra.Command, args []string) error {
|
||||||
@@ -55,11 +61,7 @@ func (r *AnnotateRunner) runE(c *cobra.Command, args []string) error {
|
|||||||
rw := &kio.ByteReadWriter{Reader: c.InOrStdin(), Writer: c.OutOrStdout()}
|
rw := &kio.ByteReadWriter{Reader: c.InOrStdin(), Writer: c.OutOrStdout()}
|
||||||
input = []kio.Reader{rw}
|
input = []kio.Reader{rw}
|
||||||
output = []kio.Writer{rw}
|
output = []kio.Writer{rw}
|
||||||
} else {
|
|
||||||
rw := &kio.LocalPackageReadWriter{PackagePath: args[0], NoDeleteFiles: true}
|
|
||||||
input = []kio.Reader{rw}
|
|
||||||
output = []kio.Writer{rw}
|
|
||||||
}
|
|
||||||
return handleError(c, kio.Pipeline{
|
return handleError(c, kio.Pipeline{
|
||||||
Inputs: input,
|
Inputs: input,
|
||||||
Filters: []kio.Filter{r},
|
Filters: []kio.Filter{r},
|
||||||
@@ -67,6 +69,48 @@ func (r *AnnotateRunner) runE(c *cobra.Command, args []string) error {
|
|||||||
}.Execute())
|
}.Execute())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e := executeCmdOnPkgs{
|
||||||
|
writer: c.OutOrStdout(),
|
||||||
|
needOpenAPI: false,
|
||||||
|
recurseSubPackages: r.RecurseSubPackages,
|
||||||
|
cmdRunner: r,
|
||||||
|
rootPkgPath: args[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.execute()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *AnnotateRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||||
|
openAPIFileName, err := ext.OpenAPIFileName()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rw := &kio.LocalPackageReadWriter{PackagePath: pkgPath, NoDeleteFiles: true, PackageFileName: openAPIFileName}
|
||||||
|
input := []kio.Reader{rw}
|
||||||
|
output := []kio.Writer{rw}
|
||||||
|
err = kio.Pipeline{
|
||||||
|
Inputs: input,
|
||||||
|
Filters: []kio.Filter{r},
|
||||||
|
Outputs: output,
|
||||||
|
}.Execute()
|
||||||
|
if err != nil {
|
||||||
|
// return err if there is only package
|
||||||
|
if !r.RecurseSubPackages {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
// print error message and continue if there are multiple packages to annotate
|
||||||
|
fmt.Fprintf(w, "%s in package %q\n", err.Error(), pkgPath)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "added annotations in package %q\n", pkgPath)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *AnnotateRunner) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (r *AnnotateRunner) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
n := nodes[i]
|
n := nodes[i]
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/copyutil"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAnnotateCommand(t *testing.T) {
|
func TestAnnotateCommand(t *testing.T) {
|
||||||
@@ -486,3 +488,71 @@ spec:
|
|||||||
replicas: 3
|
replicas: 3
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestAnnotateSubPackages(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
dataset string
|
||||||
|
packagePath string
|
||||||
|
args []string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "annotate-recurse-subpackages",
|
||||||
|
dataset: "dataset-without-setters",
|
||||||
|
args: []string{"--kv", "foo=bar", "-R"},
|
||||||
|
expected: `
|
||||||
|
added annotations in package "${baseDir}/mysql"
|
||||||
|
added annotations in package "${baseDir}/mysql/storage"
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "annotate-top-level-pkg-no-recurse-subpackages",
|
||||||
|
dataset: "dataset-without-setters",
|
||||||
|
packagePath: "mysql",
|
||||||
|
args: []string{"--kv", "foo=bar"},
|
||||||
|
expected: `added annotations in package "${baseDir}/mysql"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "annotate-nested-pkg-no-recurse-subpackages",
|
||||||
|
dataset: "dataset-without-setters",
|
||||||
|
packagePath: "mysql/storage",
|
||||||
|
args: []string{"--kv", "foo=bar"},
|
||||||
|
expected: `added annotations in package "${baseDir}/mysql/storage"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i := range tests {
|
||||||
|
test := tests[i]
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
// reset the openAPI afterward
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
|
defer openapi.ResetOpenAPI()
|
||||||
|
sourceDir := filepath.Join("test", "testdata", test.dataset)
|
||||||
|
baseDir, err := ioutil.TempDir("", "")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
copyutil.CopyDir(sourceDir, baseDir)
|
||||||
|
defer os.RemoveAll(baseDir)
|
||||||
|
runner := NewAnnotateRunner("")
|
||||||
|
actual := &bytes.Buffer{}
|
||||||
|
runner.Command.SetOut(actual)
|
||||||
|
runner.Command.SetArgs(append([]string{filepath.Join(baseDir, test.packagePath)}, test.args...))
|
||||||
|
err = runner.Command.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize path format for windows
|
||||||
|
actualNormalized := strings.Replace(
|
||||||
|
strings.Replace(actual.String(), "\\", "/", -1),
|
||||||
|
"//", "/", -1)
|
||||||
|
|
||||||
|
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
||||||
|
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
||||||
|
if !assert.Equal(t, strings.TrimSpace(expectedNormalized), strings.TrimSpace(actualNormalized)) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,11 +4,14 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
|
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,6 +27,8 @@ func NewDeleteSetterRunner(parent string) *DeleteSetterRunner {
|
|||||||
PreRunE: r.preRunE,
|
PreRunE: r.preRunE,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
}
|
}
|
||||||
|
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false,
|
||||||
|
"deletes setter recursively in all the nested subpackages")
|
||||||
fixDocs(parent, c)
|
fixDocs(parent, c)
|
||||||
r.Command = c
|
r.Command = c
|
||||||
|
|
||||||
@@ -38,6 +43,7 @@ type DeleteSetterRunner struct {
|
|||||||
Command *cobra.Command
|
Command *cobra.Command
|
||||||
DeleteSetter settersutil.DeleterCreator
|
DeleteSetter settersutil.DeleterCreator
|
||||||
OpenAPIFile string
|
OpenAPIFile string
|
||||||
|
RecurseSubPackages bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DeleteSetterRunner) preRunE(c *cobra.Command, args []string) error {
|
func (r *DeleteSetterRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
@@ -50,17 +56,49 @@ func (r *DeleteSetterRunner) preRunE(c *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := openapi.AddSchemaFromFile(r.OpenAPIFile); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DeleteSetterRunner) runE(c *cobra.Command, args []string) error {
|
func (r *DeleteSetterRunner) runE(c *cobra.Command, args []string) error {
|
||||||
return handleError(c, r.delete(c, args))
|
e := executeCmdOnPkgs{
|
||||||
|
needOpenAPI: true,
|
||||||
|
writer: c.OutOrStdout(),
|
||||||
|
rootPkgPath: args[0],
|
||||||
|
recurseSubPackages: r.RecurseSubPackages,
|
||||||
|
cmdRunner: r,
|
||||||
|
}
|
||||||
|
err := e.execute()
|
||||||
|
if err != nil {
|
||||||
|
return handleError(c, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DeleteSetterRunner) delete(c *cobra.Command, args []string) error {
|
func (r *DeleteSetterRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||||
return r.DeleteSetter.Delete(r.OpenAPIFile, args[0])
|
openAPIFileName, err := ext.OpenAPIFileName()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.DeleteSetter = settersutil.DeleterCreator{
|
||||||
|
Name: r.DeleteSetter.Name,
|
||||||
|
DefinitionPrefix: fieldmeta.SetterDefinitionPrefix,
|
||||||
|
RecurseSubPackages: r.RecurseSubPackages,
|
||||||
|
OpenAPIFileName: openAPIFileName,
|
||||||
|
OpenAPIPath: filepath.Join(pkgPath, openAPIFileName),
|
||||||
|
ResourcesPath: pkgPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.DeleteSetter.Delete()
|
||||||
|
if err != nil {
|
||||||
|
// return err if RecurseSubPackages is false
|
||||||
|
if !r.DeleteSetter.RecurseSubPackages {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
// print error message and continue if RecurseSubPackages is true
|
||||||
|
fmt.Fprintf(w, "%s in package %q\n\n", err.Error(), pkgPath)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "deleted setter %q in package %q\n\n", r.DeleteSetter.Name, pkgPath)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/copyutil"
|
||||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ openAPI:
|
|||||||
value: "3"
|
value: "3"
|
||||||
setBy: me
|
setBy: me
|
||||||
`,
|
`,
|
||||||
|
out: `deleted setter "replicas-setter" in package "${baseDir}"`,
|
||||||
expectedOpenAPI: `
|
expectedOpenAPI: `
|
||||||
apiVersion: v1alpha1
|
apiVersion: v1alpha1
|
||||||
kind: Example
|
kind: Example
|
||||||
@@ -95,6 +97,7 @@ openAPI:
|
|||||||
name: image
|
name: image
|
||||||
value: nginx
|
value: nginx
|
||||||
`,
|
`,
|
||||||
|
out: `deleted setter "replicas-setter" in package "${baseDir}"`,
|
||||||
expectedOpenAPI: `
|
expectedOpenAPI: `
|
||||||
apiVersion: v1alpha1
|
apiVersion: v1alpha1
|
||||||
kind: Example
|
kind: Example
|
||||||
@@ -158,6 +161,7 @@ spec:
|
|||||||
- "b"
|
- "b"
|
||||||
- "c"
|
- "c"
|
||||||
`,
|
`,
|
||||||
|
out: `deleted setter "list" in package "${baseDir}"`,
|
||||||
expectedResources: `
|
expectedResources: `
|
||||||
apiVersion: example.com/v1beta1
|
apiVersion: example.com/v1beta1
|
||||||
kind: Example1
|
kind: Example1
|
||||||
@@ -226,7 +230,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
replicas: 3 # {"$openapi" : "replicas-setter"}
|
replicas: 3 # {"$openapi" : "replicas-setter"}
|
||||||
`,
|
`,
|
||||||
err: `setter with name image does not exist`,
|
err: `setter "image" does not exist`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "delete setter used in substitution error",
|
name: "delete setter used in substitution error",
|
||||||
@@ -287,7 +291,7 @@ openAPI:
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
`,
|
`,
|
||||||
err: `setter is used in substitution image, please delete the parent substitution first`,
|
err: `setter "image-name" is used in substitution "image", please delete the parent substitution first`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i := range tests {
|
for i := range tests {
|
||||||
@@ -297,24 +301,18 @@ kind: Deployment
|
|||||||
openapi.ResetOpenAPI()
|
openapi.ResetOpenAPI()
|
||||||
defer openapi.ResetOpenAPI()
|
defer openapi.ResetOpenAPI()
|
||||||
|
|
||||||
f, err := ioutil.TempFile("", "k8s-cli-")
|
baseDir, err := ioutil.TempDir("", "")
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
defer os.Remove(f.Name())
|
defer os.RemoveAll(baseDir)
|
||||||
|
f := filepath.Join(baseDir, "Krmfile")
|
||||||
err = ioutil.WriteFile(f.Name(), []byte(test.inputOpenAPI), 0600)
|
err = ioutil.WriteFile(f, []byte(test.inputOpenAPI), 0600)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
old := ext.GetOpenAPIFile
|
r, err := ioutil.TempFile(baseDir, "k8s-cli-*.yaml")
|
||||||
defer func() { ext.GetOpenAPIFile = old }()
|
|
||||||
ext.GetOpenAPIFile = func(args []string) (s string, err error) {
|
|
||||||
return f.Name(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := ioutil.TempFile("", "k8s-cli-*.yaml")
|
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
@@ -327,21 +325,29 @@ kind: Deployment
|
|||||||
runner := commands.NewDeleteSetterRunner("")
|
runner := commands.NewDeleteSetterRunner("")
|
||||||
out := &bytes.Buffer{}
|
out := &bytes.Buffer{}
|
||||||
runner.Command.SetOut(out)
|
runner.Command.SetOut(out)
|
||||||
runner.Command.SetArgs(append([]string{r.Name()}, test.args...))
|
runner.Command.SetArgs(append([]string{baseDir}, test.args...))
|
||||||
err = runner.Command.Execute()
|
err = runner.Command.Execute()
|
||||||
|
|
||||||
if test.err != "" {
|
if test.err != "" {
|
||||||
if !assert.NotNil(t, err) {
|
if !assert.NotNil(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
} else {
|
|
||||||
assert.Equal(t, err.Error(), test.err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
assert.Equal(t, test.err, err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !assert.Equal(t, test.out, out.String()) {
|
// normalize path format for windows
|
||||||
|
actualNorm := strings.Replace(
|
||||||
|
strings.Replace(out.String(), "\\", "/", -1),
|
||||||
|
"//", "/", -1)
|
||||||
|
|
||||||
|
expectedOut := strings.Replace(test.out, "${baseDir}", baseDir, -1)
|
||||||
|
expectedNormalized := strings.Replace(expectedOut, "\\", "/", -1)
|
||||||
|
|
||||||
|
if !assert.Equal(t, expectedNormalized, strings.TrimSpace(actualNorm)) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +361,7 @@ kind: Deployment
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
actualOpenAPI, err := ioutil.ReadFile(f.Name())
|
actualOpenAPI, err := ioutil.ReadFile(f)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
@@ -367,3 +373,74 @@ kind: Deployment
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteSetterSubPackages(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
dataset string
|
||||||
|
packagePath string
|
||||||
|
args []string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "delete-setter-recurse-subpackages",
|
||||||
|
dataset: "dataset-with-setters",
|
||||||
|
args: []string{"namespace", "-R"},
|
||||||
|
expected: `
|
||||||
|
deleted setter "namespace" in package "${baseDir}/mysql"
|
||||||
|
|
||||||
|
setter "namespace" does not exist in package "${baseDir}/mysql/nosetters"
|
||||||
|
|
||||||
|
deleted setter "namespace" in package "${baseDir}/mysql/storage"
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete-setter-top-level-pkg-no-recurse-subpackages",
|
||||||
|
dataset: "dataset-with-setters",
|
||||||
|
packagePath: "mysql",
|
||||||
|
args: []string{"namespace"},
|
||||||
|
expected: `deleted setter "namespace" in package "${baseDir}/mysql"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete-setter-nested-pkg-no-recurse-subpackages",
|
||||||
|
dataset: "dataset-with-setters",
|
||||||
|
packagePath: "mysql/storage",
|
||||||
|
args: []string{"namespace"},
|
||||||
|
expected: `deleted setter "namespace" in package "${baseDir}/mysql/storage"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i := range tests {
|
||||||
|
test := tests[i]
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
// reset the openAPI afterward
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
|
defer openapi.ResetOpenAPI()
|
||||||
|
sourceDir := filepath.Join("test", "testdata", test.dataset)
|
||||||
|
baseDir, err := ioutil.TempDir("", "")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
copyutil.CopyDir(sourceDir, baseDir)
|
||||||
|
//defer os.RemoveAll(baseDir)
|
||||||
|
runner := commands.NewDeleteSetterRunner("")
|
||||||
|
actual := &bytes.Buffer{}
|
||||||
|
runner.Command.SetOut(actual)
|
||||||
|
runner.Command.SetArgs(append([]string{filepath.Join(baseDir, test.packagePath)}, test.args...))
|
||||||
|
err = runner.Command.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize path format for windows
|
||||||
|
actualNormalized := strings.Replace(
|
||||||
|
strings.Replace(actual.String(), "\\", "/", -1),
|
||||||
|
"//", "/", -1)
|
||||||
|
|
||||||
|
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
||||||
|
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
||||||
|
if !assert.Equal(t, strings.TrimSpace(expectedNormalized), strings.TrimSpace(actualNormalized)) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||||
@@ -20,6 +24,8 @@ func NewDeleteSubstitutionRunner(parent string) *DeleteSubstitutionRunner {
|
|||||||
PreRunE: r.preRunE,
|
PreRunE: r.preRunE,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
}
|
}
|
||||||
|
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false,
|
||||||
|
"deletes substitution recursively in all the nested subpackages")
|
||||||
fixDocs(parent, c)
|
fixDocs(parent, c)
|
||||||
r.Command = c
|
r.Command = c
|
||||||
|
|
||||||
@@ -34,6 +40,7 @@ type DeleteSubstitutionRunner struct {
|
|||||||
Command *cobra.Command
|
Command *cobra.Command
|
||||||
DeleteSubstitution settersutil.DeleterCreator
|
DeleteSubstitution settersutil.DeleterCreator
|
||||||
OpenAPIFile string
|
OpenAPIFile string
|
||||||
|
RecurseSubPackages bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DeleteSubstitutionRunner) preRunE(c *cobra.Command, args []string) error {
|
func (r *DeleteSubstitutionRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
@@ -54,9 +61,45 @@ func (r *DeleteSubstitutionRunner) preRunE(c *cobra.Command, args []string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *DeleteSubstitutionRunner) runE(c *cobra.Command, args []string) error {
|
func (r *DeleteSubstitutionRunner) runE(c *cobra.Command, args []string) error {
|
||||||
return handleError(c, r.delete(c, args))
|
e := executeCmdOnPkgs{
|
||||||
|
needOpenAPI: true,
|
||||||
|
writer: c.OutOrStdout(),
|
||||||
|
rootPkgPath: args[0],
|
||||||
|
recurseSubPackages: r.RecurseSubPackages,
|
||||||
|
cmdRunner: r,
|
||||||
|
}
|
||||||
|
err := e.execute()
|
||||||
|
if err != nil {
|
||||||
|
return handleError(c, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DeleteSubstitutionRunner) delete(c *cobra.Command, args []string) error {
|
func (r *DeleteSubstitutionRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||||
return r.DeleteSubstitution.Delete(r.OpenAPIFile, args[0])
|
openAPIFileName, err := ext.OpenAPIFileName()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.DeleteSubstitution = settersutil.DeleterCreator{
|
||||||
|
Name: r.DeleteSubstitution.Name,
|
||||||
|
DefinitionPrefix: fieldmeta.SubstitutionDefinitionPrefix,
|
||||||
|
RecurseSubPackages: r.RecurseSubPackages,
|
||||||
|
OpenAPIFileName: openAPIFileName,
|
||||||
|
OpenAPIPath: filepath.Join(pkgPath, openAPIFileName),
|
||||||
|
ResourcesPath: pkgPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.DeleteSubstitution.Delete()
|
||||||
|
if err != nil {
|
||||||
|
// return err if RecurseSubPackages is false
|
||||||
|
if !r.DeleteSubstitution.RecurseSubPackages {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
// print error message and continue if RecurseSubPackages is true
|
||||||
|
fmt.Fprintf(w, "%s in package %q\n\n", err.Error(), pkgPath)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "deleted substitution %q in package %q\n\n", r.DeleteSubstitution.Name, pkgPath)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
||||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||||
)
|
)
|
||||||
@@ -79,6 +79,7 @@ spec:
|
|||||||
- name: sidecar
|
- name: sidecar
|
||||||
image: nginx:1.7.9 # {"$ref":"#/definitions/io.k8s.cli.substitutions.my.image"}
|
image: nginx:1.7.9 # {"$ref":"#/definitions/io.k8s.cli.substitutions.my.image"}
|
||||||
`,
|
`,
|
||||||
|
out: `deleted substitution "my.image" in package "${baseDir}"`,
|
||||||
expectedResources: `
|
expectedResources: `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@@ -169,6 +170,7 @@ spec:
|
|||||||
- name: sidecar
|
- name: sidecar
|
||||||
image: nginx:1.7.9 # {"$openapi":"my-image-sub"}
|
image: nginx:1.7.9 # {"$openapi":"my-image-sub"}
|
||||||
`,
|
`,
|
||||||
|
out: `deleted substitution "my-image-sub" in package "${baseDir}"`,
|
||||||
expectedResources: `
|
expectedResources: `
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@@ -297,7 +299,7 @@ openAPI:
|
|||||||
value: "3"
|
value: "3"
|
||||||
setBy: me
|
setBy: me
|
||||||
`,
|
`,
|
||||||
err: "substitution with name my-image-sub-not-present does not exist",
|
err: `substitution "my-image-sub-not-present" does not exist`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -415,7 +417,7 @@ spec:
|
|||||||
- name: sidecar
|
- name: sidecar
|
||||||
image: nginx::1.7.9 # {"$openapi":"my-image-subst"}
|
image: nginx::1.7.9 # {"$openapi":"my-image-subst"}
|
||||||
`,
|
`,
|
||||||
err: "substitution is used in substitution my-nested-subst, please delete the parent substitution first",
|
err: `substitution "my-image-subst" is used in substitution "my-nested-subst", please delete the parent substitution first`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i := range tests {
|
for i := range tests {
|
||||||
@@ -425,24 +427,18 @@ spec:
|
|||||||
openapi.ResetOpenAPI()
|
openapi.ResetOpenAPI()
|
||||||
defer openapi.ResetOpenAPI()
|
defer openapi.ResetOpenAPI()
|
||||||
|
|
||||||
f, err := ioutil.TempFile("", "k8s-cli-")
|
baseDir, err := ioutil.TempDir("", "")
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
defer os.Remove(f.Name())
|
defer os.RemoveAll(baseDir)
|
||||||
|
f := filepath.Join(baseDir, "Krmfile")
|
||||||
err = ioutil.WriteFile(f.Name(), []byte(test.inputOpenAPI), 0600)
|
err = ioutil.WriteFile(f, []byte(test.inputOpenAPI), 0600)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
old := ext.GetOpenAPIFile
|
r, err := ioutil.TempFile(baseDir, "k8s-cli-*.yaml")
|
||||||
defer func() { ext.GetOpenAPIFile = old }()
|
|
||||||
ext.GetOpenAPIFile = func(args []string) (s string, err error) {
|
|
||||||
return f.Name(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := ioutil.TempFile("", "k8s-cli-*.yaml")
|
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
@@ -455,21 +451,38 @@ spec:
|
|||||||
runner := commands.NewDeleteSubstitutionRunner("")
|
runner := commands.NewDeleteSubstitutionRunner("")
|
||||||
out := &bytes.Buffer{}
|
out := &bytes.Buffer{}
|
||||||
runner.Command.SetOut(out)
|
runner.Command.SetOut(out)
|
||||||
runner.Command.SetArgs(append([]string{r.Name()}, test.args...))
|
runner.Command.SetArgs(append([]string{baseDir}, test.args...))
|
||||||
err = runner.Command.Execute()
|
err = runner.Command.Execute()
|
||||||
|
|
||||||
if test.err != "" {
|
if test.err != "" {
|
||||||
if !assert.NotNil(t, err) {
|
if !assert.NotNil(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
} else {
|
|
||||||
assert.Equal(t, err.Error(), test.err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
assert.Equal(t, test.err, err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !assert.Equal(t, test.out, out.String()) {
|
// normalize path format for windows
|
||||||
|
actualNorm := strings.Replace(
|
||||||
|
strings.Replace(out.String(), "\\", "/", -1),
|
||||||
|
"//", "/", -1)
|
||||||
|
expectedOut := strings.Replace(test.out, "${baseDir}", baseDir, -1)
|
||||||
|
expectedNorm := strings.Replace(expectedOut, "\\", "/", -1)
|
||||||
|
|
||||||
|
if !assert.Equal(t, expectedNorm, strings.TrimSpace(actualNorm)) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
actualOpenAPI, err := ioutil.ReadFile(f)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t,
|
||||||
|
strings.TrimSpace(test.expectedOpenAPI),
|
||||||
|
strings.TrimSpace(string(actualOpenAPI))) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,18 +493,9 @@ spec:
|
|||||||
if !assert.Equal(t,
|
if !assert.Equal(t,
|
||||||
strings.TrimSpace(test.expectedResources),
|
strings.TrimSpace(test.expectedResources),
|
||||||
strings.TrimSpace(string(actualResources))) {
|
strings.TrimSpace(string(actualResources))) {
|
||||||
return
|
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()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,18 +135,18 @@ func (dd DeleterDefinition) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
definitions, err := object.Pipe(yaml.Lookup(openapi.SupplementaryOpenAPIFieldName, "definitions"))
|
definitions, err := object.Pipe(yaml.Lookup(openapi.SupplementaryOpenAPIFieldName, "definitions"))
|
||||||
if err != nil || definitions == nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// return error if the setter to be deleted doesn't exist
|
// return error if the setter to be deleted doesn't exist
|
||||||
if definitions.Field(key) == nil {
|
if definitions == nil || definitions.Field(key) == nil {
|
||||||
return nil, errors.Errorf("%s with name %s does not exist", defType, dd.Name)
|
return nil, errors.Errorf("%s %q does not exist", defType, dd.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
subst := SubstReferringDefinition(definitions, key)
|
subst := SubstReferringDefinition(definitions, key)
|
||||||
|
|
||||||
if subst != "" {
|
if subst != "" {
|
||||||
return nil, errors.Errorf("%s is used in substitution %s, please delete the parent substitution first", defType, subst)
|
return nil, errors.Errorf("%s %q is used in substitution %q, please delete the parent substitution first", defType, dd.Name, subst)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = definitions.Pipe(yaml.FieldClearer{Name: key})
|
_, err = definitions.Pipe(yaml.FieldClearer{Name: key})
|
||||||
|
|||||||
@@ -75,8 +75,10 @@ func TestDeleterCreator_Delete(t *testing.T) {
|
|||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
dc.OpenAPIPath = openAPI.Name()
|
||||||
|
dc.ResourcesPath = resource.Name()
|
||||||
|
|
||||||
err = dc.Delete(openAPI.Name(), resource.Name())
|
err = dc.Delete()
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,24 +17,34 @@ type DeleterCreator struct {
|
|||||||
|
|
||||||
// DefinitionPrefix is the prefix of the OpenAPI definition type
|
// DefinitionPrefix is the prefix of the OpenAPI definition type
|
||||||
DefinitionPrefix string
|
DefinitionPrefix string
|
||||||
|
|
||||||
|
RecurseSubPackages bool
|
||||||
|
|
||||||
|
OpenAPIFileName string
|
||||||
|
|
||||||
|
// Path to openAPI file
|
||||||
|
OpenAPIPath string
|
||||||
|
|
||||||
|
// Path to resources folder
|
||||||
|
ResourcesPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d DeleterCreator) Delete(openAPIPath, resourcesPath string) error {
|
func (d DeleterCreator) Delete() error {
|
||||||
dd := setters2.DeleterDefinition{
|
dd := setters2.DeleterDefinition{
|
||||||
Name: d.Name,
|
Name: d.Name,
|
||||||
DefinitionPrefix: d.DefinitionPrefix,
|
DefinitionPrefix: d.DefinitionPrefix,
|
||||||
}
|
}
|
||||||
if err := dd.DeleteFromFile(openAPIPath); err != nil {
|
if err := dd.DeleteFromFile(d.OpenAPIPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the updated definitions
|
// Load the updated definitions
|
||||||
if err := openapi.AddSchemaFromFile(openAPIPath); err != nil {
|
if err := openapi.AddSchemaFromFile(d.OpenAPIPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the resources with the deleter reference
|
// Update the resources with the deleter reference
|
||||||
inout := &kio.LocalPackageReadWriter{PackagePath: resourcesPath}
|
inout := &kio.LocalPackageReadWriter{PackagePath: d.ResourcesPath, PackageFileName: d.OpenAPIFileName}
|
||||||
return kio.Pipeline{
|
return kio.Pipeline{
|
||||||
Inputs: []kio.Reader{inout},
|
Inputs: []kio.Reader{inout},
|
||||||
Filters: []kio.Filter{kio.FilterAll(
|
Filters: []kio.Filter{kio.FilterAll(
|
||||||
|
|||||||
Reference in New Issue
Block a user