diff --git a/kyaml/setters2/types.go b/kyaml/setters2/types.go index 5c1bc1407..c5a686cfc 100644 --- a/kyaml/setters2/types.go +++ b/kyaml/setters2/types.go @@ -21,6 +21,8 @@ type setter struct { Value string `yaml:"value,omitempty" json:"value,omitempty"` ListValues []string `yaml:"listValues,omitempty" json:"listValues,omitempty"` EnumValues map[string]string `yaml:"enumValues,omitempty" json:"enumValues,omitempty"` + Required bool `yaml:"required,omitempty" json:"required,omitempty"` + IsSet bool `yaml:"isSet,omitempty" json:"isSet,omitempty"` } type substitution struct { diff --git a/kyaml/setters2/util.go b/kyaml/setters2/util.go new file mode 100644 index 000000000..464e5a6e1 --- /dev/null +++ b/kyaml/setters2/util.go @@ -0,0 +1,31 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package setters2 + +import ( + "strings" + + "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/fieldmeta" + "sigs.k8s.io/kustomize/kyaml/openapi" +) + +// CheckRequiredSettersSet iterates through all the setter definitions in openAPI +// schema and returns error if any of the setter has required field true and isSet false +func CheckRequiredSettersSet() error { + for key := range openapi.Schema().Definitions { + if strings.Contains(key, fieldmeta.SetterDefinitionPrefix) { + val := openapi.Schema().Definitions[key] + defExt, err := GetExtFromSchema(&val) // parse the extension out of the openAPI + if err != nil { + return errors.Wrap(err) + } + if defExt.Setter.Required && !defExt.Setter.IsSet { + return errors.Errorf("setter %s is required but not set, "+ + "please set it to new value and try again", strings.TrimPrefix(key, fieldmeta.SetterDefinitionPrefix)) + } + } + } + return nil +} diff --git a/kyaml/setters2/util_test.go b/kyaml/setters2/util_test.go new file mode 100644 index 000000000..415ed89bc --- /dev/null +++ b/kyaml/setters2/util_test.go @@ -0,0 +1,172 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package setters2 + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "sigs.k8s.io/kustomize/kyaml/openapi" +) + +func TestCheckRequiredSettersSet(t *testing.T) { + var tests = []struct { + name string + inputOpenAPIfile string + expectedError bool + }{ + { + name: "no required, no isSet", + inputOpenAPIfile: ` +apiVersion: v1alpha1 +kind: OpenAPIfile +openAPI: + definitions: + io.k8s.cli.setters.gcloud.project.projectNumber: + description: hello world + x-k8s-cli: + setter: + name: gcloud.project.projectNumber + value: "123" + setBy: me + io.k8s.cli.setters.replicas: + description: hello world + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me + `, + expectedError: false, + }, + { + name: "required true, no isSet", + inputOpenAPIfile: ` +apiVersion: v1alpha1 +kind: Example +openAPI: + definitions: + io.k8s.cli.setters.replicas: + description: hello world + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me + required: true + `, + expectedError: true, + }, + { + name: "required true, isSet true", + inputOpenAPIfile: ` +apiVersion: v1alpha1 +kind: Example +openAPI: + definitions: + io.k8s.cli.setters.replicas: + description: hello world + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me + required: true + isSet: true + `, + expectedError: false, + }, + + { + name: "required false, isSet true", + inputOpenAPIfile: ` +apiVersion: v1alpha1 +kind: OpenAPIfile +openAPI: + definitions: + io.k8s.cli.setters.gcloud.project.projectNumber: + description: hello world + x-k8s-cli: + setter: + name: gcloud.project.projectNumber + value: "123" + setBy: me + io.k8s.cli.setters.replicas: + description: hello world + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me + required: false + isSet: true + `, + expectedError: false, + }, + + { + name: "required true, isSet false", + inputOpenAPIfile: ` +apiVersion: v1alpha1 +kind: OpenAPIfile +openAPI: + definitions: + io.k8s.cli.setters.gcloud.project.projectNumber: + description: hello world + x-k8s-cli: + setter: + name: gcloud.project.projectNumber + value: "123" + setBy: me + io.k8s.cli.setters.replicas: + description: hello world + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me + required: true + isSet: false + `, + expectedError: true, + }, + + { + name: "no openAPI", + inputOpenAPIfile: ``, + expectedError: false, + }, + } + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + openapi.ResetOpenAPI() + defer openapi.ResetOpenAPI() + dir, err := ioutil.TempDir("", "") + assert.NoError(t, err) + defer os.RemoveAll(dir) + err = ioutil.WriteFile(filepath.Join(dir, "Krmfile"), []byte(test.inputOpenAPIfile), 0600) + if !assert.NoError(t, err) { + t.FailNow() + } + err = openapi.AddSchemaFromFile(filepath.Join(dir, "Krmfile")) + if err != nil { + // do nothing if openAPI file or schema doesn't exist, CheckRequiredSettersSet() + // should not throw any error + fmt.Println("Unable to load schema from file, continuing...") + } + err = CheckRequiredSettersSet() + if test.expectedError && !assert.Error(t, err) { + t.FailNow() + } + if !test.expectedError && !assert.NoError(t, err) { + t.FailNow() + } + }) + } +} diff --git a/kyaml/yaml/merge2/smpdirective_string.go b/kyaml/yaml/merge2/smpdirective_string.go index b4f937f0e..c17256a25 100644 --- a/kyaml/yaml/merge2/smpdirective_string.go +++ b/kyaml/yaml/merge2/smpdirective_string.go @@ -1,3 +1,6 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + // Code generated by "stringer -type=smpDirective -linecomment"; DO NOT EDIT. package merge2