From 29fbc564e31453b01c68946ded85af7ac64bc8cc Mon Sep 17 00:00:00 2001 From: Phani Teja Marupaka Date: Tue, 11 Feb 2020 09:22:38 -0800 Subject: [PATCH 1/2] Setter Definitions read and write --- kyaml/openapi/openapi.go | 35 ++++++++++ kyaml/openapi/openapi_test.go | 77 ++++++++++++++++++++++ kyaml/setters2/setterdefinition.go | 56 ++++++++++++++++ kyaml/setters2/setterdefinition_test.go | 88 +++++++++++++++++++++++++ 4 files changed, 256 insertions(+) create mode 100644 kyaml/setters2/setterdefinition.go create mode 100644 kyaml/setters2/setterdefinition_test.go diff --git a/kyaml/openapi/openapi.go b/kyaml/openapi/openapi.go index 7587968f1..7b93f7e07 100644 --- a/kyaml/openapi/openapi.go +++ b/kyaml/openapi/openapi.go @@ -291,6 +291,41 @@ func resolve(root interface{}, ref *spec.Ref) (*spec.Schema, error) { } } +func PopulateDefsInOpenAPI(s string) error { + y, err := yaml.Parse(s) + if err != nil { + return err + } + // get the field containing the openAPI + f := y.Field("openAPI") + + defs, err := f.Value.String() + if err != nil { + return err + } + + // convert the yaml openAPI to an interface{} + // which can be marshalled into json + var o interface{} + err = yaml.Unmarshal([]byte(defs), &o) + if err != nil { + return err + } + + // convert the interface{} into a json string + j, err := json.Marshal(o) + if err != nil { + return err + } + + // add the json schema to the global schema + _, err = AddSchema(j) + if err != nil { + return err + } + return nil +} + func rootSchema() *spec.Schema { initSchema() return &globalSchema.schema diff --git a/kyaml/openapi/openapi_test.go b/kyaml/openapi/openapi_test.go index 04bf26f0b..9e4bf455b 100644 --- a/kyaml/openapi/openapi_test.go +++ b/kyaml/openapi/openapi_test.go @@ -122,3 +122,80 @@ func TestSchemaForResourceType(t *testing.T) { t.FailNow() } } + +func TestPopulateDefsInOpenAPI_Setter(t *testing.T) { + globalSchema = openapiData{} + inputyaml := ` +openAPI: + definitions: + io.k8s.cli.setters.image-name: + x-k8s-cli: + setter: + name: image-name + value: "nginx" + ` + err := PopulateDefsInOpenAPI(inputyaml) + + if !assert.NoError(t, err) { + t.FailNow() + } + + s, err := GetSchema(`{"$ref": "#/definitions/io.k8s.cli.setters.image-name"}`) + + if !assert.NoError(t, err) { + t.FailNow() + } + if !assert.Greater(t, len(globalSchema.schema.Definitions), 200) { + t.FailNow() + } + assert.Equal(t, `map[x-k8s-cli:map[setter:map[name:image-name value:nginx]]]`, + fmt.Sprintf("%v", s.Schema.Extensions)) +} + +func TestPopulateDefsInOpenAPI_Substitution(t *testing.T) { + globalSchema = openapiData{} + inputyaml := ` +openAPI: + definitions: + io.k8s.cli.setters.image-name: + x-k8s-cli: + setter: + name: image-name + value: "nginx" + io.k8s.cli.setters.image-tag: + x-k8s-cli: + setter: + name: image-tag + value: "1.8.1" + io.k8s.cli.substitutions.image: + x-k8s-cli: + substitution: + name: image + pattern: IMAGE_NAME:IMAGE_TAG + values: + - marker: "IMAGE_NAME" + ref: "#/definitions/io.k8s.cli.setters.image-name" + - marker: "IMAGE_TAG" + ref: "#/definitions/io.k8s.cli.setters.image-tag" + ` + err := PopulateDefsInOpenAPI(inputyaml) + + if !assert.NoError(t, err) { + t.FailNow() + } + + s, err := GetSchema(`{"$ref": "#/definitions/io.k8s.cli.substitutions.image"}`) + + if !assert.NoError(t, err) { + t.FailNow() + } + if !assert.Greater(t, len(globalSchema.schema.Definitions), 200) { + t.FailNow() + } + + assert.Equal(t, + `map[x-k8s-cli:map[substitution:map[name:image pattern:IMAGE_NAME:IMAGE_TAG`+ + ` values:[map[marker:IMAGE_NAME ref:#/definitions/io.k8s.cli.setters.image-name]`+ + ` map[marker:IMAGE_TAG ref:#/definitions/io.k8s.cli.setters.image-tag]]]]]`, + fmt.Sprintf("%v", s.Schema.Extensions)) +} diff --git a/kyaml/setters2/setterdefinition.go b/kyaml/setters2/setterdefinition.go new file mode 100644 index 000000000..be8604dcf --- /dev/null +++ b/kyaml/setters2/setterdefinition.go @@ -0,0 +1,56 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package setters2 + +import ( + "io/ioutil" + + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +const DefinitionPrefix = "io.k8s.cli.setters." + +type SetterDefinition struct { + Name string + Value string +} + +func (sd SetterDefinition) AddSetterToFile(path string) error { + b, err := ioutil.ReadFile(path) + if err != nil { + return err + } + y, err := yaml.Parse(string(b)) + if err != nil { + return err + } + if err := y.PipeE(sd); err != nil { + return err + } + out, err := y.String() + if err != nil { + return err + } + if err := ioutil.WriteFile(path, []byte(out), 0600); err != nil { + return err + } + return nil +} + +func (sd SetterDefinition) Filter(object *yaml.RNode) (*yaml.RNode, error) { + key := DefinitionPrefix + sd.Name + + def, err := object.Pipe(yaml.LookupCreate( + yaml.MappingNode, "openAPI", "definitions", key, "x-k8s-cli", "setter")) + if err != nil { + return nil, err + } + if err := def.PipeE(yaml.FieldSetter{Name: "name", StringValue: sd.Name}); err != nil { + return nil, err + } + if err := def.PipeE(yaml.FieldSetter{Name: "value", StringValue: sd.Value}); err != nil { + return nil, err + } + return object, nil +} diff --git a/kyaml/setters2/setterdefinition_test.go b/kyaml/setters2/setterdefinition_test.go new file mode 100644 index 000000000..2ea8ea151 --- /dev/null +++ b/kyaml/setters2/setterdefinition_test.go @@ -0,0 +1,88 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package setters2 + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +var kptfile = `apiVersion: kpt.dev/v1alpha1 +kind: Kptfile +metadata: + name: hello-world-set +upstream: + type: git + git: + commit: 5c1c019b59299a4f6c7edd1ff5ff54d720621bbe + repo: git@github.com:GoogleContainerTools/kpt + directory: /package-examples/helloworld-set + ref: v0.1.0 +packageMetadata: + shortDescription: example package using setters` + +func TestAddUpdateSetter(t *testing.T) { + path := os.TempDir() + "Kptfile" + + //write initial kptfile to temp path + err := ioutil.WriteFile(path, []byte(kptfile), 0600) + if !assert.NoError(t, err) { + t.FailNow() + } + + //add a setter definition + sd := SetterDefinition{ + Name: "no-match-1", + Value: "1", + } + + err = sd.AddSetterToFile(path) + + if !assert.NoError(t, err) { + t.FailNow() + } + + // update setter definition + sd2 := SetterDefinition{ + Name: "no-match-1", + Value: "2", + } + + err = sd2.AddSetterToFile(path) + + if !assert.NoError(t, err) { + t.FailNow() + } + + b, err := ioutil.ReadFile(path) + if err != nil { + t.FailNow() + } + + expected := `apiVersion: kpt.dev/v1alpha1 +kind: Kptfile +metadata: + name: hello-world-set +upstream: + type: git + git: + commit: 5c1c019b59299a4f6c7edd1ff5ff54d720621bbe + repo: git@github.com:GoogleContainerTools/kpt + directory: /package-examples/helloworld-set + ref: v0.1.0 +packageMetadata: + shortDescription: example package using setters +openAPI: + definitions: + io.k8s.cli.setters.no-match-1: + x-k8s-cli: + setter: + name: no-match-1 + value: 2 +` + assert.Equal(t, expected, string(b)) +} From 6b6a74af19e4071e80855dbb3fa7652b6a9a35ce Mon Sep 17 00:00:00 2001 From: Phani Teja Marupaka Date: Tue, 11 Feb 2020 16:03:22 -0800 Subject: [PATCH 2/2] Substitutions --- kyaml/setters2/setterdefinition_test.go | 24 +++--- kyaml/setters2/substitutiondefinition.go | 60 +++++++++++++ kyaml/setters2/substitutiondefinition_test.go | 86 +++++++++++++++++++ 3 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 kyaml/setters2/substitutiondefinition.go create mode 100644 kyaml/setters2/substitutiondefinition_test.go diff --git a/kyaml/setters2/setterdefinition_test.go b/kyaml/setters2/setterdefinition_test.go index 2ea8ea151..f233271e2 100644 --- a/kyaml/setters2/setterdefinition_test.go +++ b/kyaml/setters2/setterdefinition_test.go @@ -11,32 +11,31 @@ import ( "github.com/stretchr/testify/assert" ) -var kptfile = `apiVersion: kpt.dev/v1alpha1 -kind: Kptfile +var resourcefile = `apiVersion: resource.dev/v1alpha1 +kind: resourcefile metadata: name: hello-world-set upstream: type: git git: commit: 5c1c019b59299a4f6c7edd1ff5ff54d720621bbe - repo: git@github.com:GoogleContainerTools/kpt directory: /package-examples/helloworld-set ref: v0.1.0 packageMetadata: shortDescription: example package using setters` func TestAddUpdateSetter(t *testing.T) { - path := os.TempDir() + "Kptfile" + path := os.TempDir() + "/resourcefile" - //write initial kptfile to temp path - err := ioutil.WriteFile(path, []byte(kptfile), 0600) + //write initial resourcefile to temp path + err := ioutil.WriteFile(path, []byte(resourcefile), 0666) if !assert.NoError(t, err) { t.FailNow() } //add a setter definition sd := SetterDefinition{ - Name: "no-match-1", + Name: "image", Value: "1", } @@ -48,7 +47,7 @@ func TestAddUpdateSetter(t *testing.T) { // update setter definition sd2 := SetterDefinition{ - Name: "no-match-1", + Name: "image", Value: "2", } @@ -63,25 +62,24 @@ func TestAddUpdateSetter(t *testing.T) { t.FailNow() } - expected := `apiVersion: kpt.dev/v1alpha1 -kind: Kptfile + expected := `apiVersion: resource.dev/v1alpha1 +kind: resourcefile metadata: name: hello-world-set upstream: type: git git: commit: 5c1c019b59299a4f6c7edd1ff5ff54d720621bbe - repo: git@github.com:GoogleContainerTools/kpt directory: /package-examples/helloworld-set ref: v0.1.0 packageMetadata: shortDescription: example package using setters openAPI: definitions: - io.k8s.cli.setters.no-match-1: + io.k8s.cli.setters.image: x-k8s-cli: setter: - name: no-match-1 + name: image value: 2 ` assert.Equal(t, expected, string(b)) diff --git a/kyaml/setters2/substitutiondefinition.go b/kyaml/setters2/substitutiondefinition.go new file mode 100644 index 000000000..17d4ff34e --- /dev/null +++ b/kyaml/setters2/substitutiondefinition.go @@ -0,0 +1,60 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package setters2 + +import ( + "io/ioutil" + + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +type SubstitutionDefinition struct { + Name string `yaml:"name"` + Pattern string `yaml:"pattern"` + Values []Value `yaml:"value"` +} + +type Value struct { + Marker string `yaml:"marker"` + Ref string `yaml:"ref"` +} + +func (subd SubstitutionDefinition) AddSubstitutionToFile(path string) error { + b, err := ioutil.ReadFile(path) + if err != nil { + return err + } + y, err := yaml.Parse(string(b)) + if err != nil { + return err + } + if err := y.PipeE(subd); err != nil { + return err + } + out, err := y.String() + if err != nil { + return err + } + if err := ioutil.WriteFile(path, []byte(out), 0666); err != nil { + return err + } + return nil +} + +func (subd SubstitutionDefinition) Filter(object *yaml.RNode) (*yaml.RNode, error) { + key := DefinitionPrefix + subd.Name + + def, err := object.Pipe(yaml.LookupCreate( + yaml.MappingNode, "openAPI", "definitions", key, "x-k8s-cli", "substitution")) + if err != nil { + return nil, err + } + if err := def.PipeE(yaml.FieldSetter{Name: "name", StringValue: subd.Name}); err != nil { + return nil, err + } + if err := def.PipeE(yaml.FieldSetter{Name: "pattern", StringValue: subd.Pattern}); err != nil { + return nil, err + } + return object, nil +} diff --git a/kyaml/setters2/substitutiondefinition_test.go b/kyaml/setters2/substitutiondefinition_test.go new file mode 100644 index 000000000..9b239bd89 --- /dev/null +++ b/kyaml/setters2/substitutiondefinition_test.go @@ -0,0 +1,86 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package setters2 + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddUpdateSubstitution(t *testing.T) { + path := os.TempDir() + "/resourcefile" + + //write initial resourcefile to temp path + err := ioutil.WriteFile(path, []byte(resourcefile), 0666) + if !assert.NoError(t, err) { + t.FailNow() + } + + value1 := Value{ + Marker: "IMAGE_NAME", + Ref: "#/definitions/io.k8s.cli.setters.image-name", + } + + value2 := Value{ + Marker: "IMAGE_TAG", + Ref: "#/definitions/io.k8s.cli.setters.image-tag", + } + + values := []Value{value1, value2} + + //add a setter definition + subd := SubstitutionDefinition{ + Name: "image", + Pattern: "IMAGE_NAME:IMAGE_TAG", + Values: values, + } + + err = subd.AddSubstitutionToFile(path) + + if !assert.NoError(t, err) { + t.FailNow() + } + + // update setter definition + subd2 := SubstitutionDefinition{ + Name: "image", + Pattern: "IMAGE_NAME:IMAGE_TAG2", + } + + err = subd2.AddSubstitutionToFile(path) + + if !assert.NoError(t, err) { + t.FailNow() + } + + b, err := ioutil.ReadFile(path) + if err != nil { + t.FailNow() + } + + expected := `apiVersion: resource.dev/v1alpha1 +kind: resourcefile +metadata: + name: hello-world-set +upstream: + type: git + git: + commit: 5c1c019b59299a4f6c7edd1ff5ff54d720621bbe + directory: /package-examples/helloworld-set + ref: v0.1.0 +packageMetadata: + shortDescription: example package using setters +openAPI: + definitions: + io.k8s.cli.setters.image: + x-k8s-cli: + substitution: + name: image + pattern: IMAGE_NAME:IMAGE_TAG2 +` + assert.Equal(t, expected, string(b)) +}