mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Validate list values against openAPI
This commit is contained in:
@@ -403,6 +403,58 @@ spec:
|
|||||||
`,
|
`,
|
||||||
errMsg: "tag in body should be at least 6 chars long",
|
errMsg: "tag in body should be at least 6 chars long",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "validate openAPI list values",
|
||||||
|
args: []string{"list", "10", "hi", "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`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for i := range tests {
|
for i := range tests {
|
||||||
test := tests[i]
|
test := tests[i]
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ func (s *Set) visitSequence(object *yaml.RNode, p string, schema *openapi.Resour
|
|||||||
|
|
||||||
// set the values on the sequences
|
// set the values on the sequences
|
||||||
var elements []*yaml.Node
|
var elements []*yaml.Node
|
||||||
|
if len(ext.Setter.ListValues) > 0 {
|
||||||
|
if err := validateAgainstSchema(ext, schema.Schema); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
for i := range ext.Setter.ListValues {
|
for i := range ext.Setter.ListValues {
|
||||||
v := ext.Setter.ListValues[i]
|
v := ext.Setter.ListValues[i]
|
||||||
n := yaml.NewScalarRNode(v).YNode()
|
n := yaml.NewScalarRNode(v).YNode()
|
||||||
@@ -200,15 +205,22 @@ func validateAgainstSchema(ext *cliExtension, sch *spec.Schema) error {
|
|||||||
sc.Properties[ext.Setter.Name] = *sch
|
sc.Properties[ext.Setter.Name] = *sch
|
||||||
|
|
||||||
input := map[string]interface{}{}
|
input := map[string]interface{}{}
|
||||||
format := `{"%s" : "%s"}`
|
var inputJSON string
|
||||||
if yaml.IsValueNonString(ext.Setter.Value) {
|
|
||||||
format = `{"%s" : %s}`
|
if len(ext.Setter.ListValues) > 0 {
|
||||||
|
format := `{"%s" : [%s]}`
|
||||||
|
inputJSON = fmt.Sprintf(format, ext.Setter.Name, JoinCompositeStrings(ext.Setter.ListValues))
|
||||||
|
} else {
|
||||||
|
format := `{"%s" : "%s"}`
|
||||||
|
if yaml.IsValueNonString(ext.Setter.Value) {
|
||||||
|
format = `{"%s" : %s}`
|
||||||
|
}
|
||||||
|
inputJSON = fmt.Sprintf(format, ext.Setter.Name, ext.Setter.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// leverage json.Unmarshal to parse the value type
|
// leverage json.Unmarshal to parse the value type
|
||||||
// Ex: `{"setter" : "true"}` parses the value as string whereas
|
// Ex: `{"setter" : "true"}` parses the value as string whereas
|
||||||
// `{"setter" : true}` parses as boolean
|
// `{"setter" : true}` parses as boolean
|
||||||
inputJSON := fmt.Sprintf(format, ext.Setter.Name, ext.Setter.Value)
|
|
||||||
err := json.Unmarshal([]byte(inputJSON), &input)
|
err := json.Unmarshal([]byte(inputJSON), &input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -220,6 +232,21 @@ func validateAgainstSchema(ext *cliExtension, sch *spec.Schema) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JoinCompositeStrings takes in strings whose values can be of different types and returns
|
||||||
|
// joined string with quotes for only string type values
|
||||||
|
// ex: ["10", "true", "hi", "1.1"] returns 10,true,"hi",1.1
|
||||||
|
func JoinCompositeStrings(listValues []string) string {
|
||||||
|
res := ""
|
||||||
|
for _, val := range listValues {
|
||||||
|
if yaml.IsValueNonString(val) {
|
||||||
|
res += fmt.Sprintf(`%s,`, val)
|
||||||
|
} else {
|
||||||
|
res += fmt.Sprintf(`"%s",`, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.TrimSuffix(res, ",")
|
||||||
|
}
|
||||||
|
|
||||||
// SetOpenAPI updates a setter value
|
// SetOpenAPI updates a setter value
|
||||||
type SetOpenAPI struct {
|
type SetOpenAPI struct {
|
||||||
// Name is the name of the setter to add
|
// Name is the name of the setter to add
|
||||||
|
|||||||
@@ -1293,3 +1293,8 @@ openAPI:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJoinCompositeStrings(t *testing.T) {
|
||||||
|
input := []string{"10", "true", "hi", "1.1", "1.8.1"}
|
||||||
|
assert.Equal(t, `10,true,"hi",1.1,"1.8.1"`, JoinCompositeStrings(input))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package testutil_test
|
package testutil_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
Reference in New Issue
Block a user