mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
Add unknown metadata field validation tests (#109316)
* add unknown metadata validation e2e tests * Address PR Feedback * explicitly check for unexpected nil errors or namespace errors
This commit is contained in:
parent
4bd396115d
commit
91c016e4d5
@ -104,6 +104,10 @@ const (
|
|||||||
metaPattern = `"kind":"%s","apiVersion":"%s/%s","metadata":{"name":"%s"}`
|
metaPattern = `"kind":"%s","apiVersion":"%s/%s","metadata":{"name":"%s"}`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func unknownFieldMetadataJSON(gvk schema.GroupVersionKind, name string) string {
|
||||||
|
return fmt.Sprintf(`"kind":"%s","apiVersion":"%s/%s","metadata":{"unknownMeta": "foo", "name":"%s"}`, gvk.Kind, gvk.Group, gvk.Version, name)
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
nautilusImage = imageutils.GetE2EImage(imageutils.Nautilus)
|
nautilusImage = imageutils.GetE2EImage(imageutils.Nautilus)
|
||||||
httpdImage = imageutils.GetE2EImage(imageutils.Httpd)
|
httpdImage = imageutils.GetE2EImage(imageutils.Httpd)
|
||||||
@ -163,6 +167,29 @@ properties:
|
|||||||
pattern: in-tree|out-of-tree
|
pattern: in-tree|out-of-tree
|
||||||
type: string`)
|
type: string`)
|
||||||
|
|
||||||
|
var schemaFooEmbedded = []byte(`description: Foo CRD with an embedded resource
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
spec:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
template:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-embedded-resource: true
|
||||||
|
properties:
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
spec:
|
||||||
|
type: object
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string`)
|
||||||
|
|
||||||
// Stops everything from filePath from namespace ns and checks if everything matching selectors from the given namespace is correctly stopped.
|
// Stops everything from filePath from namespace ns and checks if everything matching selectors from the given namespace is correctly stopped.
|
||||||
// Aware of the kubectl example files map.
|
// Aware of the kubectl example files map.
|
||||||
func cleanupKubectlInputs(fileContents string, ns string, selectors ...string) {
|
func cleanupKubectlInputs(fileContents string, ns string, selectors ...string) {
|
||||||
@ -1079,6 +1106,129 @@ metadata:
|
|||||||
err = createApplyCustomResource(validArbitraryCR, f.Namespace.Name, "test-cr", crd)
|
err = createApplyCustomResource(validArbitraryCR, f.Namespace.Name, "test-cr", crd)
|
||||||
framework.ExpectNoError(err, "creating custom resource")
|
framework.ExpectNoError(err, "creating custom resource")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should detect unknown metadata fields in both the root and embedded object of a CR", func() {
|
||||||
|
ginkgo.By("prepare CRD with x-kubernetes-embedded-resource: true")
|
||||||
|
opt := func(crd *apiextensionsv1.CustomResourceDefinition) {
|
||||||
|
props := &apiextensionsv1.JSONSchemaProps{}
|
||||||
|
if err := yaml.Unmarshal(schemaFooEmbedded, props); err != nil {
|
||||||
|
framework.Failf("failed to unmarshal schema: %v", err)
|
||||||
|
}
|
||||||
|
crd.Spec.Versions = []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: props,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group := fmt.Sprintf("%s.example.com", f.BaseName)
|
||||||
|
testCRD, err := crd.CreateMultiVersionTestCRD(f, group, opt)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("failed to create test CRD: %v", err)
|
||||||
|
}
|
||||||
|
defer testCRD.CleanUp()
|
||||||
|
|
||||||
|
ginkgo.By("sleep for 10s to wait for potential crd openapi publishing alpha feature")
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
|
||||||
|
ginkgo.By("attempting to create a CR with unknown metadata fields at the root level")
|
||||||
|
gvk := schema.GroupVersionKind{Group: testCRD.Crd.Spec.Group, Version: testCRD.Crd.Spec.Versions[0].Name, Kind: testCRD.Crd.Spec.Names.Kind}
|
||||||
|
schema := schemaForGVK(gvk)
|
||||||
|
framework.ExpectNotEqual(schema, nil, "retrieving a schema for the crd")
|
||||||
|
embeddedCRPattern := `
|
||||||
|
|
||||||
|
{%s,
|
||||||
|
"spec": {
|
||||||
|
"template": {
|
||||||
|
"apiVersion": "foo/v1",
|
||||||
|
"kind": "Sub",
|
||||||
|
"metadata": {
|
||||||
|
%s
|
||||||
|
"name": "subobject",
|
||||||
|
"namespace": "my-ns"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
meta := unknownFieldMetadataJSON(gvk, "test-cr")
|
||||||
|
unknownRootMetaCR := fmt.Sprintf(embeddedCRPattern, meta, "")
|
||||||
|
_, err = framework.RunKubectlInput(ns, unknownRootMetaCR, "create", "--validate=true", "-f", "-")
|
||||||
|
if err == nil {
|
||||||
|
framework.Failf("unexpected nil error when creating CR with unknown root metadata field")
|
||||||
|
}
|
||||||
|
if !(strings.Contains(err.Error(), `unknown field "unknownMeta"`) || strings.Contains(err.Error(), `unknown field "metadata.unknownMeta"`)) {
|
||||||
|
framework.Failf("error missing root unknown metadata field, got: %v", err)
|
||||||
|
}
|
||||||
|
if strings.Contains(err.Error(), `unknown field "namespace"`) || strings.Contains(err.Error(), `unknown field "metadata.namespace"`) {
|
||||||
|
framework.Failf("unexpected error, CR's root metadata namespace field unrecognized: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ginkgo.By("attempting to create a CR with unknown metadata fields in the embedded object")
|
||||||
|
metaEmbedded := fmt.Sprintf(metaPattern, testCRD.Crd.Spec.Names.Kind, testCRD.Crd.Spec.Group, testCRD.Crd.Spec.Versions[0].Name, "test-cr-embedded")
|
||||||
|
unknownEmbeddedMetaCR := fmt.Sprintf(embeddedCRPattern, metaEmbedded, `"unknownMetaEmbedded": "bar",`)
|
||||||
|
_, err = framework.RunKubectlInput(ns, unknownEmbeddedMetaCR, "create", "--validate=true", "-f", "-")
|
||||||
|
if err == nil {
|
||||||
|
framework.Failf("unexpected nil error when creating CR with unknown embedded metadata field")
|
||||||
|
}
|
||||||
|
if !(strings.Contains(err.Error(), `unknown field "unknownMetaEmbedded"`) || strings.Contains(err.Error(), `unknown field "spec.template.metadata.unknownMetaEmbedded"`)) {
|
||||||
|
framework.Failf("error missing embedded unknown metadata field, got: %v", err)
|
||||||
|
}
|
||||||
|
if strings.Contains(err.Error(), `unknown field "namespace"`) || strings.Contains(err.Error(), `unknown field "spec.template.metadata.namespace"`) {
|
||||||
|
framework.Failf("unexpected error, CR's embedded metadata namespace field unrecognized: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should detect unknown metadata fields of a typed object", func() {
|
||||||
|
ginkgo.By("calling kubectl create deployment")
|
||||||
|
invalidMetaDeployment := `
|
||||||
|
{
|
||||||
|
"apiVersion": "apps/v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": {
|
||||||
|
"name": "my-dep",
|
||||||
|
"namespace": "my-ns",
|
||||||
|
"unknownMeta": "foo",
|
||||||
|
"labels": {"app": "nginx"}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"selector": {
|
||||||
|
"matchLabels": {
|
||||||
|
"app": "nginx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"metadata": {
|
||||||
|
"labels": {
|
||||||
|
"app": "nginx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"containers": [{
|
||||||
|
"name": "nginx",
|
||||||
|
"image": "nginx:latest"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
_, err := framework.RunKubectlInput(ns, invalidMetaDeployment, "create", "-f", "-")
|
||||||
|
if err == nil {
|
||||||
|
framework.Failf("unexpected nil error when creating deployment with unknown metadata field")
|
||||||
|
}
|
||||||
|
if !(strings.Contains(err.Error(), `unknown field "unknownMeta"`) || strings.Contains(err.Error(), `unknown field "metadata.unknownMeta"`)) {
|
||||||
|
framework.Failf("error missing unknown metadata field, got: %v", err)
|
||||||
|
}
|
||||||
|
if strings.Contains(err.Error(), `unknown field "namespace"`) || strings.Contains(err.Error(), `unknown field "metadata.namespace"`) {
|
||||||
|
framework.Failf("unexpected error, deployment's metadata namespace field unrecognized: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.Describe("Kubectl cluster-info", func() {
|
ginkgo.Describe("Kubectl cluster-info", func() {
|
||||||
|
Loading…
Reference in New Issue
Block a user