Add generated file
This PR adds generated files under pkg/client and vendor folder.
This commit is contained in:
309
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go
generated
vendored
Normal file
309
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go
generated
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package apiserver
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apiserver/conversion"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
|
||||
metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
)
|
||||
|
||||
func TestConvertFieldLabel(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
clusterScoped bool
|
||||
label string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "cluster scoped - name is ok",
|
||||
clusterScoped: true,
|
||||
label: "metadata.name",
|
||||
},
|
||||
{
|
||||
name: "cluster scoped - namespace is not ok",
|
||||
clusterScoped: true,
|
||||
label: "metadata.namespace",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "cluster scoped - other field is not ok",
|
||||
clusterScoped: true,
|
||||
label: "some.other.field",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "namespace scoped - name is ok",
|
||||
label: "metadata.name",
|
||||
},
|
||||
{
|
||||
name: "namespace scoped - namespace is ok",
|
||||
label: "metadata.namespace",
|
||||
},
|
||||
{
|
||||
name: "namespace scoped - other field is not ok",
|
||||
label: "some.other.field",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
|
||||
crd := apiextensions.CustomResourceDefinition{}
|
||||
|
||||
if test.clusterScoped {
|
||||
crd.Spec.Scope = apiextensions.ClusterScoped
|
||||
} else {
|
||||
crd.Spec.Scope = apiextensions.NamespaceScoped
|
||||
}
|
||||
_, c := conversion.NewCRDConverter(&crd)
|
||||
|
||||
label, value, err := c.ConvertFieldLabel(schema.GroupVersionKind{}, test.label, "value")
|
||||
if e, a := test.expectError, err != nil; e != a {
|
||||
t.Fatalf("err: expected %t, got %t", e, a)
|
||||
}
|
||||
if test.expectError {
|
||||
if e, a := "field label not supported: "+test.label, err.Error(); e != a {
|
||||
t.Errorf("err: expected %s, got %s", e, a)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if e, a := test.label, label; e != a {
|
||||
t.Errorf("label: expected %s, got %s", e, a)
|
||||
}
|
||||
if e, a := "value", value; e != a {
|
||||
t.Errorf("value: expected %s, got %s", e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundtripObjectMeta(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
codec := json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false)
|
||||
seed := rand.Int63()
|
||||
fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(seed), codecs)
|
||||
|
||||
N := 1000
|
||||
for i := 0; i < N; i++ {
|
||||
u := &unstructured.Unstructured{Object: map[string]interface{}{}}
|
||||
original := &metav1.ObjectMeta{}
|
||||
fuzzer.Fuzz(original)
|
||||
if err := setObjectMeta(u, original); err != nil {
|
||||
t.Fatalf("unexpected error setting ObjectMeta: %v", err)
|
||||
}
|
||||
o, _, err := getObjectMeta(u, false)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting the Objectmeta: %v", err)
|
||||
}
|
||||
|
||||
if !equality.Semantic.DeepEqual(original, o) {
|
||||
t.Errorf("diff: %v\nCodec: %#v", diff.ObjectReflectDiff(original, o), codec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMalformedObjectMetaFields sets a number of different random values and types for all
|
||||
// metadata fields. If json.Unmarshal accepts them, compare that getObjectMeta
|
||||
// gives the same result. Otherwise, drop malformed fields.
|
||||
func TestMalformedObjectMetaFields(t *testing.T) {
|
||||
fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(rand.Int63()), serializer.NewCodecFactory(runtime.NewScheme()))
|
||||
spuriousValues := func() []interface{} {
|
||||
return []interface{}{
|
||||
// primitives
|
||||
nil,
|
||||
int64(1),
|
||||
float64(1.5),
|
||||
true,
|
||||
"a",
|
||||
// well-formed complex values
|
||||
[]interface{}{"a", "b"},
|
||||
map[string]interface{}{"a": "1", "b": "2"},
|
||||
[]interface{}{int64(1), int64(2)},
|
||||
[]interface{}{float64(1.5), float64(2.5)},
|
||||
// known things json decoding tolerates
|
||||
map[string]interface{}{"a": "1", "b": nil},
|
||||
// malformed things
|
||||
map[string]interface{}{"a": "1", "b": []interface{}{"nested"}},
|
||||
[]interface{}{"a", int64(1), float64(1.5), true, []interface{}{"nested"}},
|
||||
}
|
||||
}
|
||||
N := 100
|
||||
for i := 0; i < N; i++ {
|
||||
fuzzedObjectMeta := &metav1.ObjectMeta{}
|
||||
fuzzer.Fuzz(fuzzedObjectMeta)
|
||||
goodMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, pth := range jsonPaths(nil, goodMetaMap) {
|
||||
for _, v := range spuriousValues() {
|
||||
// skip values of same type, because they can only cause decoding errors further insides
|
||||
orig, err := JsonPathValue(goodMetaMap, pth, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected to not find something at %v: %v", pth, err)
|
||||
}
|
||||
if reflect.TypeOf(v) == reflect.TypeOf(orig) {
|
||||
continue
|
||||
}
|
||||
|
||||
// make a spurious map
|
||||
spuriousMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := SetJsonPath(spuriousMetaMap, pth, 0, v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// See if it can unmarshal to object meta
|
||||
spuriousJSON, err := encodingjson.Marshal(spuriousMetaMap)
|
||||
if err != nil {
|
||||
t.Fatalf("error on %v=%#v: %v", pth, v, err)
|
||||
}
|
||||
expectedObjectMeta := &metav1.ObjectMeta{}
|
||||
if err := encodingjson.Unmarshal(spuriousJSON, expectedObjectMeta); err != nil {
|
||||
// if standard json unmarshal would fail decoding this field, drop the field entirely
|
||||
truncatedMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// we expect this logic for the different fields:
|
||||
switch {
|
||||
default:
|
||||
// delete complete top-level field by default
|
||||
DeleteJsonPath(truncatedMetaMap, pth[:1], 0)
|
||||
}
|
||||
|
||||
truncatedJSON, err := encodingjson.Marshal(truncatedMetaMap)
|
||||
if err != nil {
|
||||
t.Fatalf("error on %v=%#v: %v", pth, v, err)
|
||||
}
|
||||
expectedObjectMeta = &metav1.ObjectMeta{}
|
||||
if err := encodingjson.Unmarshal(truncatedJSON, expectedObjectMeta); err != nil {
|
||||
t.Fatalf("error on %v=%#v: %v", pth, v, err)
|
||||
}
|
||||
}
|
||||
|
||||
// make sure dropInvalidTypedFields+getObjectMeta matches what we expect
|
||||
u := &unstructured.Unstructured{Object: map[string]interface{}{"metadata": spuriousMetaMap}}
|
||||
actualObjectMeta, _, err := getObjectMeta(u, true)
|
||||
if err != nil {
|
||||
t.Errorf("got unexpected error after dropping invalid typed fields on %v=%#v: %v", pth, v, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !equality.Semantic.DeepEqual(expectedObjectMeta, actualObjectMeta) {
|
||||
t.Errorf("%v=%#v, diff: %v\n", pth, v, diff.ObjectReflectDiff(expectedObjectMeta, actualObjectMeta))
|
||||
t.Errorf("expectedObjectMeta %#v", expectedObjectMeta)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetObjectMetaNils(t *testing.T) {
|
||||
u := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": map[string]interface{}{
|
||||
"generateName": nil,
|
||||
"labels": map[string]interface{}{
|
||||
"foo": nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
o, _, err := getObjectMeta(u, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if o.GenerateName != "" {
|
||||
t.Errorf("expected null json value to be read as \"\" string, but got: %q", o.GenerateName)
|
||||
}
|
||||
if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got)
|
||||
}
|
||||
|
||||
// double check this what the kube JSON decode is doing
|
||||
bs, _ := encodingjson.Marshal(u.UnstructuredContent())
|
||||
kubeObj, _, err := clientgoscheme.Codecs.UniversalDecoder(corev1.SchemeGroupVersion).Decode(bs, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pod, ok := kubeObj.(*corev1.Pod)
|
||||
if !ok {
|
||||
t.Fatalf("expected v1 Pod, got: %T", pod)
|
||||
}
|
||||
if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected {
|
||||
t.Errorf("expected generatedName to be %q, got %q", expected, got)
|
||||
}
|
||||
if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("expected labels to be %v, got %v", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetObjectMeta(t *testing.T) {
|
||||
for i := 0; i < 100; i++ {
|
||||
u := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "good",
|
||||
"Name": "bad1",
|
||||
"nAme": "bad2",
|
||||
"naMe": "bad3",
|
||||
"namE": "bad4",
|
||||
|
||||
"namespace": "good",
|
||||
"Namespace": "bad1",
|
||||
"nAmespace": "bad2",
|
||||
"naMespace": "bad3",
|
||||
"namEspace": "bad4",
|
||||
|
||||
"creationTimestamp": "a",
|
||||
},
|
||||
}}
|
||||
|
||||
meta, _, err := getObjectMeta(u, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if meta.Name != "good" || meta.Namespace != "good" {
|
||||
t.Fatalf("got %#v", meta)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user