mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-04 23:17:50 +00:00
Merge pull request #24509 from caesarxuchao/primitive-gc
Automatic merge from submit-queue Adding garbage collector controller Adding the propagator and garbage processor of the gc. Design doc is at https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/garbage-collection.md <!-- Reviewable:start --> --- This change is [<img src="http://reviewable.k8s.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](http://reviewable.k8s.io/reviews/kubernetes/kubernetes/24509) <!-- Reviewable:end -->
This commit is contained in:
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package api
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/meta/metatypes"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
@@ -89,3 +90,25 @@ func (meta *ObjectMeta) GetLabels() map[string]string { return m
|
||||
func (meta *ObjectMeta) SetLabels(labels map[string]string) { meta.Labels = labels }
|
||||
func (meta *ObjectMeta) GetAnnotations() map[string]string { return meta.Annotations }
|
||||
func (meta *ObjectMeta) SetAnnotations(annotations map[string]string) { meta.Annotations = annotations }
|
||||
|
||||
func (meta *ObjectMeta) GetOwnerReferences() []metatypes.OwnerReference {
|
||||
ret := make([]metatypes.OwnerReference, len(meta.OwnerReferences))
|
||||
for i := 0; i < len(meta.OwnerReferences); i++ {
|
||||
ret[i].Kind = meta.OwnerReferences[i].Kind
|
||||
ret[i].Name = meta.OwnerReferences[i].Name
|
||||
ret[i].UID = meta.OwnerReferences[i].UID
|
||||
ret[i].APIVersion = meta.OwnerReferences[i].APIVersion
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (meta *ObjectMeta) SetOwnerReferences(references []metatypes.OwnerReference) {
|
||||
newReferences := make([]OwnerReference, len(references))
|
||||
for i := 0; i < len(references); i++ {
|
||||
newReferences[i].Kind = references[i].Kind
|
||||
newReferences[i].Name = references[i].Name
|
||||
newReferences[i].UID = references[i].UID
|
||||
newReferences[i].APIVersion = references[i].APIVersion
|
||||
}
|
||||
meta.OwnerReferences = newReferences
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package meta
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/meta/metatypes"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
@@ -57,6 +58,14 @@ type Object interface {
|
||||
SetLabels(labels map[string]string)
|
||||
GetAnnotations() map[string]string
|
||||
SetAnnotations(annotations map[string]string)
|
||||
GetOwnerReferences() []metatypes.OwnerReference
|
||||
SetOwnerReferences([]metatypes.OwnerReference)
|
||||
}
|
||||
|
||||
var _ Object = &runtime.Unstructured{}
|
||||
|
||||
type ListMetaAccessor interface {
|
||||
GetListMeta() List
|
||||
}
|
||||
|
||||
// List lets you work with list metadata from any of the versioned or
|
||||
@@ -177,5 +186,3 @@ type RESTMapper interface {
|
||||
AliasesForResource(resource string) ([]string, bool)
|
||||
ResourceSingularizer(resource string) (singular string, err error)
|
||||
}
|
||||
|
||||
var _ Object = &runtime.Unstructured{}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/meta/metatypes"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
@@ -28,19 +29,53 @@ import (
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func ListAccessor(obj interface{}) (List, error) {
|
||||
if listMetaAccessor, ok := obj.(ListMetaAccessor); ok {
|
||||
if om := listMetaAccessor.GetListMeta(); om != nil {
|
||||
return om, nil
|
||||
}
|
||||
}
|
||||
// we may get passed an object that is directly portable to List
|
||||
if list, ok := obj.(List); ok {
|
||||
return list, nil
|
||||
}
|
||||
glog.V(4).Infof("Calling ListAccessor on non-internal object: %v", reflect.TypeOf(obj))
|
||||
// legacy path for objects that do not implement List and ListMetaAccessor via
|
||||
// reflection - very slow code path.
|
||||
v, err := conversion.EnforcePtr(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t := v.Type()
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
|
||||
}
|
||||
a := &genericAccessor{}
|
||||
listMeta := v.FieldByName("ListMeta")
|
||||
if listMeta.IsValid() {
|
||||
// look for the ListMeta fields
|
||||
if err := extractFromListMeta(listMeta, a); err != nil {
|
||||
return nil, fmt.Errorf("unable to find list fields on %#v: %v", listMeta, err)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("unable to find listMeta on %#v", v)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Accessor takes an arbitrary object pointer and returns meta.Interface.
|
||||
// obj must be a pointer to an API type. An error is returned if the minimum
|
||||
// required fields are missing. Fields that are not required return the default
|
||||
// value and are a no-op if set.
|
||||
func Accessor(obj interface{}) (Object, error) {
|
||||
if oi, ok := obj.(ObjectMetaAccessor); ok {
|
||||
if om := oi.GetObjectMeta(); om != nil {
|
||||
if objectMetaAccessor, ok := obj.(ObjectMetaAccessor); ok {
|
||||
if om := objectMetaAccessor.GetObjectMeta(); om != nil {
|
||||
return om, nil
|
||||
}
|
||||
}
|
||||
// we may get passed an object that is directly portable to Object
|
||||
if oi, ok := obj.(Object); ok {
|
||||
return oi, nil
|
||||
if object, ok := obj.(Object); ok {
|
||||
return object, nil
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Calling Accessor on non-internal object: %v", reflect.TypeOf(obj))
|
||||
@@ -310,6 +345,40 @@ func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractFromOwnerReference extracts v to o. v is the OwnerReferences field of an object.
|
||||
func extractFromOwnerReference(v reflect.Value, o *metatypes.OwnerReference) error {
|
||||
if err := runtime.Field(v, "APIVersion", &o.APIVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runtime.Field(v, "Kind", &o.Kind); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runtime.Field(v, "Name", &o.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runtime.Field(v, "UID", &o.UID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setOwnerReference sets v to o. v is the OwnerReferences field of an object.
|
||||
func setOwnerReference(v reflect.Value, o *metatypes.OwnerReference) error {
|
||||
if err := runtime.SetField(o.APIVersion, v, "APIVersion"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runtime.SetField(o.Kind, v, "Kind"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runtime.SetField(o.Name, v, "Name"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runtime.SetField(o.UID, v, "UID"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// genericAccessor contains pointers to strings that can modify an arbitrary
|
||||
// struct and implements the Accessor interface.
|
||||
type genericAccessor struct {
|
||||
@@ -325,6 +394,7 @@ type genericAccessor struct {
|
||||
deletionTimestamp **unversioned.Time
|
||||
labels *map[string]string
|
||||
annotations *map[string]string
|
||||
ownerReferences reflect.Value
|
||||
}
|
||||
|
||||
func (a genericAccessor) GetNamespace() string {
|
||||
@@ -457,6 +527,41 @@ func (a genericAccessor) SetAnnotations(annotations map[string]string) {
|
||||
*a.annotations = annotations
|
||||
}
|
||||
|
||||
func (a genericAccessor) GetOwnerReferences() []metatypes.OwnerReference {
|
||||
var ret []metatypes.OwnerReference
|
||||
s := a.ownerReferences
|
||||
if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
|
||||
glog.Errorf("expect %v to be a pointer to slice", s)
|
||||
return ret
|
||||
}
|
||||
s = s.Elem()
|
||||
// Set the capacity to one element greater to avoid copy if the caller later append an element.
|
||||
ret = make([]metatypes.OwnerReference, s.Len(), s.Len()+1)
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
if err := extractFromOwnerReference(s.Index(i), &ret[i]); err != nil {
|
||||
glog.Errorf("extractFromOwnerReference failed: %v", err)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a genericAccessor) SetOwnerReferences(references []metatypes.OwnerReference) {
|
||||
s := a.ownerReferences
|
||||
if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
|
||||
glog.Errorf("expect %v to be a pointer to slice", s)
|
||||
}
|
||||
s = s.Elem()
|
||||
newReferences := reflect.MakeSlice(s.Type(), len(references), len(references))
|
||||
for i := 0; i < len(references); i++ {
|
||||
if err := setOwnerReference(newReferences.Index(i), &references[i]); err != nil {
|
||||
glog.Errorf("setOwnerReference failed: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
s.Set(newReferences)
|
||||
}
|
||||
|
||||
// extractFromTypeMeta extracts pointers to version and kind fields from an object
|
||||
func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
|
||||
if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
|
||||
@@ -494,6 +599,14 @@ func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error {
|
||||
if err := runtime.FieldPtr(v, "Annotations", &a.annotations); err != nil {
|
||||
return err
|
||||
}
|
||||
ownerReferences := v.FieldByName("OwnerReferences")
|
||||
if !ownerReferences.IsValid() {
|
||||
return fmt.Errorf("struct %#v lacks OwnerReferences type", v)
|
||||
}
|
||||
if ownerReferences.Kind() != reflect.Slice {
|
||||
return fmt.Errorf("expect %v to be a slice", ownerReferences.Kind())
|
||||
}
|
||||
a.ownerReferences = ownerReferences.Addr()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,13 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/google/gofuzz"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/meta/metatypes"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
)
|
||||
@@ -127,17 +131,18 @@ func TestAPIObjectMeta(t *testing.T) {
|
||||
|
||||
func TestGenericTypeMeta(t *testing.T) {
|
||||
type TypeMeta struct {
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
GenerateName string `json:"generateName,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
|
||||
SelfLink string `json:"selfLink,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
GenerateName string `json:"generateName,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
|
||||
SelfLink string `json:"selfLink,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"`
|
||||
}
|
||||
type Object struct {
|
||||
TypeMeta `json:",inline"`
|
||||
@@ -236,18 +241,20 @@ func TestGenericTypeMeta(t *testing.T) {
|
||||
}
|
||||
|
||||
type InternalTypeMeta struct {
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
GenerateName string `json:"generateName,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
|
||||
SelfLink string `json:"selfLink,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
GenerateName string `json:"generateName,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
|
||||
SelfLink string `json:"selfLink,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"`
|
||||
}
|
||||
|
||||
type InternalObject struct {
|
||||
TypeMeta InternalTypeMeta `json:",inline"`
|
||||
}
|
||||
@@ -273,6 +280,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) {
|
||||
SelfLink: "some/place/only/we/know",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
Annotations: map[string]string{"x": "y"},
|
||||
// OwnerReferences are tested separately
|
||||
},
|
||||
}
|
||||
accessor := meta.NewAccessor()
|
||||
@@ -418,15 +426,16 @@ func TestGenericObjectMeta(t *testing.T) {
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
}
|
||||
type ObjectMeta struct {
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
GenerateName string `json:"generateName,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
|
||||
SelfLink string `json:"selfLink,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
GenerateName string `json:"generateName,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
|
||||
SelfLink string `json:"selfLink,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"`
|
||||
}
|
||||
type Object struct {
|
||||
TypeMeta `json:",inline"`
|
||||
@@ -722,6 +731,66 @@ func TestTypeMetaSelfLinker(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type MyAPIObject2 struct {
|
||||
unversioned.TypeMeta
|
||||
v1.ObjectMeta
|
||||
}
|
||||
|
||||
func getObjectMetaAndOwnerRefereneces() (myAPIObject2 MyAPIObject2, metaOwnerReferences []metatypes.OwnerReference) {
|
||||
fuzz.New().NilChance(.5).NumElements(1, 5).Fuzz(&myAPIObject2)
|
||||
references := myAPIObject2.ObjectMeta.OwnerReferences
|
||||
// This is necessary for the test to pass because the getter will return a
|
||||
// non-nil slice.
|
||||
metaOwnerReferences = make([]metatypes.OwnerReference, 0)
|
||||
for i := 0; i < len(references); i++ {
|
||||
metaOwnerReferences = append(metaOwnerReferences, metatypes.OwnerReference{
|
||||
Kind: references[i].Kind,
|
||||
Name: references[i].Name,
|
||||
UID: references[i].UID,
|
||||
APIVersion: references[i].APIVersion,
|
||||
})
|
||||
}
|
||||
if len(references) == 0 {
|
||||
// This is necessary for the test to pass because the setter will make a
|
||||
// non-nil slice.
|
||||
myAPIObject2.ObjectMeta.OwnerReferences = make([]v1.OwnerReference, 0)
|
||||
}
|
||||
return myAPIObject2, metaOwnerReferences
|
||||
}
|
||||
|
||||
func testGetOwnerReferences(t *testing.T) {
|
||||
obj, expected := getObjectMetaAndOwnerRefereneces()
|
||||
accessor, err := meta.Accessor(&obj)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
references := accessor.GetOwnerReferences()
|
||||
if !reflect.DeepEqual(references, expected) {
|
||||
t.Errorf("expect %#v\n got %#v", expected, references)
|
||||
}
|
||||
}
|
||||
|
||||
func testSetOwnerReferences(t *testing.T) {
|
||||
expected, references := getObjectMetaAndOwnerRefereneces()
|
||||
obj := MyAPIObject2{}
|
||||
accessor, err := meta.Accessor(&obj)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
accessor.SetOwnerReferences(references)
|
||||
if e, a := expected.ObjectMeta.OwnerReferences, obj.ObjectMeta.OwnerReferences; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expect %#v\n got %#v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccessOwnerReferences(t *testing.T) {
|
||||
fuzzIter := 5
|
||||
for i := 0; i < fuzzIter; i++ {
|
||||
testGetOwnerReferences(t)
|
||||
testSetOwnerReferences(t)
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkAccessorSetFastPath shows the interface fast path
|
||||
func BenchmarkAccessorSetFastPath(b *testing.B) {
|
||||
obj := &api.Pod{
|
||||
|
||||
33
pkg/api/meta/metatypes/deep_copy_generated.go
Normal file
33
pkg/api/meta/metatypes/deep_copy_generated.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
|
||||
package metatypes
|
||||
|
||||
import (
|
||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
func DeepCopy_metatypes_OwnerReference(in OwnerReference, out *OwnerReference, c *conversion.Cloner) error {
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Kind = in.Kind
|
||||
out.UID = in.UID
|
||||
out.Name = in.Name
|
||||
return nil
|
||||
}
|
||||
29
pkg/api/meta/metatypes/types.go
Normal file
29
pkg/api/meta/metatypes/types.go
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// The types defined in this package are used by the meta package to represent
|
||||
// the in-memory version of objects. We cannot reuse the __internal version of
|
||||
// API objects because it causes import cycle.
|
||||
package metatypes
|
||||
|
||||
import "k8s.io/kubernetes/pkg/types"
|
||||
|
||||
type OwnerReference struct {
|
||||
APIVersion string
|
||||
Kind string
|
||||
UID types.UID
|
||||
Name string
|
||||
}
|
||||
@@ -17,10 +17,14 @@ limitations under the License.
|
||||
package api_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/google/gofuzz"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/meta/metatypes"
|
||||
)
|
||||
|
||||
var _ meta.Object = &api.ObjectMeta{}
|
||||
@@ -49,3 +53,46 @@ func TestHasObjectMetaSystemFieldValues(t *testing.T) {
|
||||
t.Errorf("the resource does have all fields populated, but incorrectly reports it does not")
|
||||
}
|
||||
}
|
||||
|
||||
func getObjectMetaAndOwnerReferences() (objectMeta api.ObjectMeta, metaOwnerReferences []metatypes.OwnerReference) {
|
||||
fuzz.New().NilChance(.5).NumElements(1, 5).Fuzz(&objectMeta)
|
||||
references := objectMeta.OwnerReferences
|
||||
metaOwnerReferences = make([]metatypes.OwnerReference, 0)
|
||||
for i := 0; i < len(references); i++ {
|
||||
metaOwnerReferences = append(metaOwnerReferences, metatypes.OwnerReference{
|
||||
Kind: references[i].Kind,
|
||||
Name: references[i].Name,
|
||||
UID: references[i].UID,
|
||||
APIVersion: references[i].APIVersion,
|
||||
})
|
||||
}
|
||||
if len(references) == 0 {
|
||||
objectMeta.OwnerReferences = make([]api.OwnerReference, 0)
|
||||
}
|
||||
return objectMeta, metaOwnerReferences
|
||||
}
|
||||
|
||||
func testGetOwnerReferences(t *testing.T) {
|
||||
meta, expected := getObjectMetaAndOwnerReferences()
|
||||
refs := meta.GetOwnerReferences()
|
||||
if !reflect.DeepEqual(refs, expected) {
|
||||
t.Errorf("expect %v\n got %v", expected, refs)
|
||||
}
|
||||
}
|
||||
|
||||
func testSetOwnerReferences(t *testing.T) {
|
||||
expected, newRefs := getObjectMetaAndOwnerReferences()
|
||||
objectMeta := &api.ObjectMeta{}
|
||||
objectMeta.SetOwnerReferences(newRefs)
|
||||
if !reflect.DeepEqual(expected.OwnerReferences, objectMeta.OwnerReferences) {
|
||||
t.Errorf("expect: %#v\n got: %#v", expected.OwnerReferences, objectMeta.OwnerReferences)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccessOwnerReferences(t *testing.T) {
|
||||
fuzzIter := 5
|
||||
for i := 0; i < fuzzIter; i++ {
|
||||
testGetOwnerReferences(t)
|
||||
testSetOwnerReferences(t)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user