diff --git a/cmd/config/internal/commands/cmdcreatesetter.go b/cmd/config/internal/commands/cmdcreatesetter.go index 010606c8e..54725c54c 100644 --- a/cmd/config/internal/commands/cmdcreatesetter.go +++ b/cmd/config/internal/commands/cmdcreatesetter.go @@ -8,6 +8,7 @@ import ( "sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/setters" + "sigs.k8s.io/kustomize/kyaml/setters2/settersutil" ) // NewCreateSetterRunner returns a command runner. @@ -23,21 +24,28 @@ func NewCreateSetterRunner(parent string) *CreateSetterRunner { RunE: r.runE, } set.Flags().StringVar(&r.Set.SetPartialField.SetBy, "set-by", "", - "set the setBy annotation.") + "record who the field was default by.") set.Flags().StringVar(&r.Set.SetPartialField.Description, "description", "", - "set the description of the field value.") + "record a description for the current setter value.") set.Flags().StringVar(&r.Set.SetPartialField.Field, "field", "", - "name of the field to set -- e.g. --field port") + "name of the field to set -- e.g. --field port. defaults to all fields match"+ + "VALUE. maybe be the field name, field path, or partial field path (suffix)") set.Flags().StringVar(&r.Set.ResourceMeta.Name, "name", "", "name of the Resource on which to create the setter.") + set.Flags().MarkHidden("name") set.Flags().StringVar(&r.Set.ResourceMeta.Kind, "kind", "", "kind of the Resource on which to create the setter.") + set.Flags().MarkHidden("kind") set.Flags().StringVar(&r.Set.SetPartialField.Type, "type", "", "valid OpenAPI field type -- e.g. integer,boolean,string.") + set.Flags().MarkHidden("type") set.Flags().BoolVar(&r.Set.SetPartialField.Partial, "partial", false, "create a partial setter for only part of the field value.") + set.Flags().MarkHidden("partial") + set.Flags().StringVar(&setterVersion, "version", "", + "use this version of the setter format") + set.Flags().MarkHidden("version") fixDocs(parent, set) - set.MarkFlagRequired("type") r.Command = set return r } @@ -47,8 +55,10 @@ func CreateSetterCommand(parent string) *cobra.Command { } type CreateSetterRunner struct { - Command *cobra.Command - Set setters.CreateSetter + Command *cobra.Command + Set setters.CreateSetter + CreateSetter settersutil.SetterCreator + OpenAPIFile string } func (r *CreateSetterRunner) runE(c *cobra.Command, args []string) error { @@ -56,12 +66,40 @@ func (r *CreateSetterRunner) runE(c *cobra.Command, args []string) error { } func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error { + var err error r.Set.SetPartialField.Setter.Name = args[1] r.Set.SetPartialField.Setter.Value = args[2] + r.CreateSetter.Name = args[1] + r.CreateSetter.FieldValue = args[2] + r.CreateSetter.FieldName, err = c.Flags().GetString("field") + if err != nil { + return err + } + + if setterVersion == "" { + if len(args) < 3 { + setterVersion = "v1" + } else if err := initSetterVersion(c, args); err != nil { + return err + } + } + if setterVersion == "v2" { + var err error + r.OpenAPIFile, err = GetOpenAPIFile(args) + r.CreateSetter.Description = r.Set.SetPartialField.Description + r.CreateSetter.SetBy = r.Set.SetPartialField.SetBy + if err != nil { + return err + } + } return nil } func (r *CreateSetterRunner) set(c *cobra.Command, args []string) error { + if setterVersion == "v2" { + return r.CreateSetter.Create(r.OpenAPIFile, args[0]) + } + rw := &kio.LocalPackageReadWriter{PackagePath: args[0]} err := kio.Pipeline{ Inputs: []kio.Reader{rw}, diff --git a/cmd/config/internal/commands/cmdcreatesetter_test.go b/cmd/config/internal/commands/cmdcreatesetter_test.go new file mode 100644 index 000000000..00cd1bb02 --- /dev/null +++ b/cmd/config/internal/commands/cmdcreatesetter_test.go @@ -0,0 +1,128 @@ +// 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 TestCreateSetterCommand(t *testing.T) { + var tests = []struct { + name string + input string + args []string + out string + expectedOpenAPI string + expectedResources string + }{ + { + name: "add replicas", + args: []string{"replicas", "3", "--description", "hello world", "--set-by", "me"}, + input: ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + replicas: 3 + `, + expectedOpenAPI: ` +apiVersion: v1alpha1 +kind: Example +openAPI: + definitions: + io.k8s.cli.setters.replicas: + description: hello world + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me + `, + expectedResources: ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"} + `, + }, + } + 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(` +apiVersion: v1alpha1 +kind: Example +`), 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.NewCreateSetterRunner("") + 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() + } + }) + } +}