change args to use flags instead, so that values starting with hyphen can be correctly parsed.

This commit is contained in:
Jijie Wei
2020-05-26 17:22:04 -07:00
parent 144471ce78
commit 572260c0f0
5 changed files with 335 additions and 13 deletions

View File

@@ -20,14 +20,16 @@ import (
func NewCreateSetterRunner(parent string) *CreateSetterRunner { func NewCreateSetterRunner(parent string) *CreateSetterRunner {
r := &CreateSetterRunner{} r := &CreateSetterRunner{}
set := &cobra.Command{ set := &cobra.Command{
Use: "create-setter DIR NAME VALUE", Use: "create-setter DIR NAME --value VALUE",
Args: cobra.ExactArgs(3), Args: cobra.RangeArgs(2, 3),
Short: commands.CreateSetterShort, Short: commands.CreateSetterShort,
Long: commands.CreateSetterLong, Long: commands.CreateSetterLong,
Example: commands.CreateSetterExamples, Example: commands.CreateSetterExamples,
PreRunE: r.preRunE, PreRunE: r.preRunE,
RunE: r.runE, RunE: r.runE,
} }
set.Flags().StringVar(&r.Set.SetPartialField.Setter.Value, "value", "",
"optional flag, the value of the setter to be set to")
set.Flags().StringVar(&r.Set.SetPartialField.SetBy, "set-by", "", set.Flags().StringVar(&r.Set.SetPartialField.SetBy, "set-by", "",
"record who the field was default by.") "record who the field was default by.")
set.Flags().StringVar(&r.Set.SetPartialField.Description, "description", "", set.Flags().StringVar(&r.Set.SetPartialField.Description, "description", "",
@@ -73,18 +75,23 @@ func (r *CreateSetterRunner) runE(c *cobra.Command, args []string) error {
} }
func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error { func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error {
valueSetFromFlag := isFlagSet("value", c)
var err error var err error
r.Set.SetPartialField.Setter.Name = args[1] r.Set.SetPartialField.Setter.Name = args[1]
r.Set.SetPartialField.Setter.Value = args[2]
r.CreateSetter.Name = args[1] r.CreateSetter.Name = args[1]
r.CreateSetter.FieldValue = args[2] if valueSetFromFlag {
r.CreateSetter.FieldValue = r.Set.SetPartialField.Setter.Value
} else if len(args) > 2 {
r.Set.SetPartialField.Setter.Value = args[2]
r.CreateSetter.FieldValue = args[2]
}
r.CreateSetter.FieldName, err = c.Flags().GetString("field") r.CreateSetter.FieldName, err = c.Flags().GetString("field")
if err != nil { if err != nil {
return err return err
} }
if setterVersion == "" { if setterVersion == "" {
if len(args) < 3 { if len(args) < 2 || !valueSetFromFlag && len(args) < 3 {
setterVersion = "v1" setterVersion = "v1"
} else if err := initSetterVersion(c, args); err != nil { } else if err := initSetterVersion(c, args); err != nil {
return err return err

View File

@@ -166,6 +166,43 @@ kind: Example
spec: spec:
list: list:
- "a" # {"$openapi":"list"} - "a" # {"$openapi":"list"}
`,
},
{
name: "add replicas with value set by flag",
args: []string{"replicas", "--value", "3", "--description", "hello world", "--set-by", "me"},
input: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
`,
inputOpenAPI: `
apiVersion: v1alpha1
kind: Example
`,
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"}
`, `,
}, },
} }

View File

@@ -11,6 +11,7 @@ import (
"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/errors"
"sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/setters" "sigs.k8s.io/kustomize/kyaml/setters"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil" "sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
@@ -20,8 +21,8 @@ import (
func NewSetRunner(parent string) *SetRunner { func NewSetRunner(parent string) *SetRunner {
r := &SetRunner{} r := &SetRunner{}
c := &cobra.Command{ c := &cobra.Command{
Use: "set DIR NAME [VALUE]", Use: "set DIR NAME --values [VALUE]",
Args: cobra.MinimumNArgs(3), Args: cobra.MinimumNArgs(2),
Short: commands.SetShort, Short: commands.SetShort,
Long: commands.SetLong, Long: commands.SetLong,
Example: commands.SetExamples, Example: commands.SetExamples,
@@ -30,6 +31,8 @@ func NewSetRunner(parent string) *SetRunner {
} }
fixDocs(parent, c) fixDocs(parent, c)
r.Command = c r.Command = c
c.Flags().StringArrayVar(&r.Values, "values", []string{},
"optional flag, the values of the setter to be set to")
c.Flags().StringVar(&r.Perform.SetBy, "set-by", "", c.Flags().StringVar(&r.Perform.SetBy, "set-by", "",
"annotate the field with who set it") "annotate the field with who set it")
c.Flags().StringVar(&r.Perform.Description, "description", "", c.Flags().StringVar(&r.Perform.Description, "description", "",
@@ -53,6 +56,7 @@ type SetRunner struct {
Perform setters.PerformSetters Perform setters.PerformSetters
Set settersutil.FieldSetter Set settersutil.FieldSetter
OpenAPIFile string OpenAPIFile string
Values []string
} }
func initSetterVersion(c *cobra.Command, args []string) error { func initSetterVersion(c *cobra.Command, args []string) error {
@@ -75,16 +79,25 @@ func initSetterVersion(c *cobra.Command, args []string) error {
} }
func (r *SetRunner) preRunE(c *cobra.Command, args []string) error { func (r *SetRunner) preRunE(c *cobra.Command, args []string) error {
valueFlagSet := isFlagSet("values", c)
if valueFlagSet && len(args) > 2 {
return errors.Errorf("value should set either from flag or arg")
}
if len(args) > 1 { if len(args) > 1 {
r.Perform.Name = args[1] r.Perform.Name = args[1]
r.Lookup.Name = args[1] r.Lookup.Name = args[1]
} }
if len(args) > 2 {
if isFlagSet("values", c) && len(r.Values) == 1 {
r.Perform.Value = r.Values[0]
} else if len(args) > 2 {
r.Perform.Value = args[2] r.Perform.Value = args[2]
} }
if setterVersion == "" { if setterVersion == "" {
if len(args) < 3 { if len(args) < 2 || len(args) < 3 && !valueFlagSet {
setterVersion = "v1" setterVersion = "v1"
} else if err := initSetterVersion(c, args); err != nil { } else if err := initSetterVersion(c, args); err != nil {
return err return err
@@ -93,12 +106,19 @@ func (r *SetRunner) preRunE(c *cobra.Command, args []string) error {
if setterVersion == "v2" { if setterVersion == "v2" {
var err error var err error
r.Set.Name = args[1] r.Set.Name = args[1]
r.Set.Value = args[2] if valueFlagSet {
r.Set.Value = r.Values[0]
} else {
r.Set.Value = args[2]
}
// set remaining values as list values // set remaining values as list values
if len(args) > 3 { if valueFlagSet && len(r.Values) > 1 {
r.Set.ListValues = r.Values[1:]
} else if !valueFlagSet && len(args) > 3 {
r.Set.ListValues = args[3:] r.Set.ListValues = args[3:]
} }
r.Set.Description = r.Perform.Description r.Set.Description = r.Perform.Description
r.Set.SetBy = r.Perform.SetBy r.Set.SetBy = r.Perform.SetBy
r.OpenAPIFile, err = ext.GetOpenAPIFile(args) r.OpenAPIFile, err = ext.GetOpenAPIFile(args)
@@ -116,7 +136,7 @@ func (r *SetRunner) runE(c *cobra.Command, args []string) error {
fmt.Fprintf(c.OutOrStdout(), "set %d fields\n", count) fmt.Fprintf(c.OutOrStdout(), "set %d fields\n", count)
return handleError(c, err) return handleError(c, err)
} }
if len(args) == 3 { if len(args) > 2 || isFlagSet("values", c) {
return handleError(c, r.perform(c, args)) return handleError(c, r.perform(c, args))
} }
return handleError(c, lookup(r.Lookup, c, args)) return handleError(c, lookup(r.Lookup, c, args))

View File

@@ -74,6 +74,54 @@ spec:
replicas: 4 # {"$openapi":"replicas"} replicas: 4 # {"$openapi":"replicas"}
`, `,
}, },
{
name: "validate length of argument",
args: []string{"--description", "hi there", "--set-by", "pw"},
inputOpenAPI: `
apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.replicas:
description: hello world
x-k8s-cli:
setter:
name: replicas
value: "3"
setBy: me
`,
input: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
`,
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"}
`,
errMsg: "requires at least 2 arg(s), only received 1",
},
{ {
name: "set replicas no description", name: "set replicas no description",
args: []string{"replicas", "4"}, args: []string{"replicas", "4"},
@@ -121,7 +169,7 @@ spec:
`, `,
}, },
{ {
name: "set image", name: "set image with value",
args: []string{"tag", "1.8.1"}, args: []string{"tag", "1.8.1"},
out: "set 1 fields\n", out: "set 1 fields\n",
inputOpenAPI: ` inputOpenAPI: `
@@ -453,6 +501,205 @@ spec:
`, `,
errMsg: `list in body must be of type integer: "string" errMsg: `list in body must be of type integer: "string"
list in body must be of type integer: "boolean" list in body must be of type integer: "boolean"
list in body should have at most 2 items`,
},
{
name: "set replicas with value set by flag",
args: []string{"replicas", "--values", "4", "--description", "hi there"},
out: "set 1 fields\n",
inputOpenAPI: `
apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.replicas:
description: hello world
x-k8s-cli:
setter:
name: replicas
value: "3"
setBy: me
`,
input: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
`,
expectedOpenAPI: `
apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.replicas:
description: hi there
x-k8s-cli:
setter:
name: replicas
value: "4"
`,
expectedResources: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 4 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
`,
},
{
name: "validate values set from either flag or arg",
args: []string{"replicas", "4", "--values", "4", "--description", "hi there"},
inputOpenAPI: `
apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.replicas:
description: hello world
x-k8s-cli:
setter:
name: replicas
value: "3"
setBy: me
`,
input: `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
`,
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"}
`,
errMsg: `value should set either from flag or arg`,
},
{
name: "openAPI list values set by flag success",
args: []string{"list", "--values", "10", "--values", "11"},
out: "set 1 fields\n",
inputOpenAPI: `
kind: Kptfile
openAPI:
definitions:
io.k8s.cli.setters.list:
type: array
maxItems: 2
items:
type: integer
x-k8s-cli:
setter:
name: list
listValues:
- 0
`,
input: `
apiVersion: example.com/v1beta1
kind: Example
spec:
list: # {"$ref":"#/definitions/io.k8s.cli.setters.list"}
- 0
`,
expectedOpenAPI: `
kind: Kptfile
openAPI:
definitions:
io.k8s.cli.setters.list:
type: array
maxItems: 2
items:
type: integer
x-k8s-cli:
setter:
name: list
listValues:
- "10"
- "11"
`,
expectedResources: `
apiVersion: example.com/v1beta1
kind: Example
spec:
list: # {"$ref":"#/definitions/io.k8s.cli.setters.list"}
- "10"
- "11"
`,
},
{
name: "validate openAPI list values set by flag error",
args: []string{"list", "--values", "10", "--values", "hi", "--values", "true"},
inputOpenAPI: `
kind: Kptfile
openAPI:
definitions:
io.k8s.cli.setters.list:
type: array
maxItems: 2
items:
type: integer
x-k8s-cli:
setter:
name: list
listValues:
- 0
`,
input: `
apiVersion: example.com/v1beta1
kind: Example
spec:
list: # {"$ref":"#/definitions/io.k8s.cli.setters.list"}
- 0
`,
expectedOpenAPI: `
kind: Kptfile
openAPI:
definitions:
io.k8s.cli.setters.list:
type: array
maxItems: 2
items:
type: integer
x-k8s-cli:
setter:
name: list
listValues:
- 0
`,
expectedResources: `
apiVersion: example.com/v1beta1
kind: Example
spec:
list: # {"$ref":"#/definitions/io.k8s.cli.setters.list"}
- 0
`,
errMsg: `list in body must be of type integer: "string"
list in body must be of type integer: "boolean"
list in body should have at most 2 items`, list in body should have at most 2 items`,
}, },
} }

View File

@@ -10,6 +10,7 @@ import (
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
flag "github.com/spf13/pflag"
) )
// parseFieldPath parse a flag value into a field path // parseFieldPath parse a flag value into a field path
@@ -39,6 +40,16 @@ func parseFieldPath(path string) ([]string, error) {
return newParts, nil return newParts, nil
} }
func isFlagSet(name string, c *cobra.Command) bool {
set := false
c.Flags().Visit(func(f *flag.Flag) {
if f.Name == name {
set = true
}
})
return set
}
func handleError(c *cobra.Command, err error) error { func handleError(c *cobra.Command, err error) error {
if err == nil { if err == nil {
return nil return nil