mirror of
https://github.com/yannh/kubeconform.git
synced 2026-04-15 16:59:51 +00:00
Forbid duplicate keys in strict mode (#121)
* Forbid duplicate keys in strict mode Prevents specifying duplicate keys using UnmarshallStrict: https://pkg.go.dev/gopkg.in/yaml.v2#UnmarshalStrict * Add acceptance tests for duplicated properties
This commit is contained in:
parent
7bf1e01dec
commit
9a6fff13cb
8 changed files with 109 additions and 8 deletions
|
|
@ -112,7 +112,12 @@ func (val *v) ValidateResource(res resource.Resource) Result {
|
|||
}
|
||||
|
||||
var r map[string]interface{}
|
||||
if err := yaml.Unmarshal(res.Bytes, &r); err != nil {
|
||||
unmarshaller := yaml.Unmarshal
|
||||
if val.opts.Strict {
|
||||
unmarshaller = yaml.UnmarshalStrict
|
||||
}
|
||||
|
||||
if err := unmarshaller(res.Bytes, &r); err != nil {
|
||||
return Result{Resource: res, Status: Error, Err: fmt.Errorf("error unmarshalling resource: %s", err)}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ func TestValidate(t *testing.T) {
|
|||
rawResource, schemaRegistry1 []byte
|
||||
schemaRegistry2 []byte
|
||||
ignoreMissingSchema bool
|
||||
strict bool
|
||||
expect Status
|
||||
}{
|
||||
{
|
||||
|
|
@ -60,6 +61,7 @@ lastName: bar
|
|||
}`),
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
Valid,
|
||||
},
|
||||
{
|
||||
|
|
@ -93,6 +95,7 @@ lastName: bar
|
|||
}`),
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
Invalid,
|
||||
},
|
||||
{
|
||||
|
|
@ -125,8 +128,61 @@ firstName: foo
|
|||
}`),
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
Invalid,
|
||||
},
|
||||
{
|
||||
"key \"firstName\" already set in map",
|
||||
[]byte(`
|
||||
kind: name
|
||||
apiVersion: v1
|
||||
firstName: foo
|
||||
firstName: bar
|
||||
`),
|
||||
[]byte(`{
|
||||
"title": "Example Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["firstName"]
|
||||
}`),
|
||||
nil,
|
||||
false,
|
||||
true,
|
||||
Error,
|
||||
},
|
||||
{
|
||||
"key firstname already set in map in non-strict mode",
|
||||
[]byte(`
|
||||
kind: name
|
||||
apiVersion: v1
|
||||
firstName: foo
|
||||
firstName: bar
|
||||
`),
|
||||
[]byte(`{
|
||||
"title": "Example Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["firstName"]
|
||||
}`),
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
Valid,
|
||||
},
|
||||
{
|
||||
"resource has invalid yaml",
|
||||
[]byte(`
|
||||
|
|
@ -161,6 +217,7 @@ lastName: bar
|
|||
}`),
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
Error,
|
||||
},
|
||||
{
|
||||
|
|
@ -196,6 +253,7 @@ lastName: bar
|
|||
},
|
||||
"required": ["firstName", "lastName"]
|
||||
}`),
|
||||
false,
|
||||
false,
|
||||
Valid,
|
||||
},
|
||||
|
|
@ -232,6 +290,7 @@ lastName: bar
|
|||
},
|
||||
"required": ["firstName", "lastName"]
|
||||
}`),
|
||||
false,
|
||||
false,
|
||||
Valid,
|
||||
},
|
||||
|
|
@ -246,6 +305,7 @@ lastName: bar
|
|||
nil,
|
||||
nil,
|
||||
true,
|
||||
false,
|
||||
Skipped,
|
||||
},
|
||||
{
|
||||
|
|
@ -259,6 +319,7 @@ lastName: bar
|
|||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
Error,
|
||||
},
|
||||
{
|
||||
|
|
@ -272,6 +333,7 @@ lastName: bar
|
|||
[]byte(`<html>error page</html>`),
|
||||
[]byte(`<html>error page</html>`),
|
||||
true,
|
||||
false,
|
||||
Skipped,
|
||||
},
|
||||
{
|
||||
|
|
@ -285,6 +347,7 @@ lastName: bar
|
|||
[]byte(`<html>error page</html>`),
|
||||
[]byte(`<html>error page</html>`),
|
||||
false,
|
||||
false,
|
||||
Error,
|
||||
},
|
||||
} {
|
||||
|
|
@ -293,6 +356,7 @@ lastName: bar
|
|||
SkipKinds: map[string]struct{}{},
|
||||
RejectKinds: map[string]struct{}{},
|
||||
IgnoreMissingSchemas: testCase.ignoreMissingSchema,
|
||||
Strict: testCase.strict,
|
||||
},
|
||||
schemaCache: nil,
|
||||
schemaDownload: downloadSchema,
|
||||
|
|
@ -306,7 +370,11 @@ lastName: bar
|
|||
},
|
||||
}
|
||||
if got := val.ValidateResource(resource.Resource{Bytes: testCase.rawResource}); got.Status != testCase.expect {
|
||||
t.Errorf("%d - expected %d, got %d: %s", i, testCase.expect, got.Status, got.Err.Error())
|
||||
if got.Err != nil {
|
||||
t.Errorf("%d - expected %d, got %d: %s", i, testCase.expect, got.Status, got.Err.Error())
|
||||
} else {
|
||||
t.Errorf("%d - expected %d, got %d", i, testCase.expect, got.Status)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue