mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #3603 from smarterclayton/expose_type_accessor
Add TypeAccessor to api/meta for objects without Object/ListMeta
This commit is contained in:
		@@ -32,17 +32,16 @@ type VersionInterfaces struct {
 | 
				
			|||||||
// internal API objects. Attempting to set or retrieve a field on an object that does
 | 
					// internal API objects. Attempting to set or retrieve a field on an object that does
 | 
				
			||||||
// not support that field (Name, UID, Namespace on lists) will be a no-op and return
 | 
					// not support that field (Name, UID, Namespace on lists) will be a no-op and return
 | 
				
			||||||
// a default value.
 | 
					// a default value.
 | 
				
			||||||
 | 
					// TODO: rename to ObjectInterface when we clear up these interfaces.
 | 
				
			||||||
type Interface interface {
 | 
					type Interface interface {
 | 
				
			||||||
 | 
						TypeInterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Namespace() string
 | 
						Namespace() string
 | 
				
			||||||
	SetNamespace(namespace string)
 | 
						SetNamespace(namespace string)
 | 
				
			||||||
	Name() string
 | 
						Name() string
 | 
				
			||||||
	SetName(name string)
 | 
						SetName(name string)
 | 
				
			||||||
	UID() types.UID
 | 
						UID() types.UID
 | 
				
			||||||
	SetUID(uid types.UID)
 | 
						SetUID(uid types.UID)
 | 
				
			||||||
	APIVersion() string
 | 
					 | 
				
			||||||
	SetAPIVersion(version string)
 | 
					 | 
				
			||||||
	Kind() string
 | 
					 | 
				
			||||||
	SetKind(kind string)
 | 
					 | 
				
			||||||
	ResourceVersion() string
 | 
						ResourceVersion() string
 | 
				
			||||||
	SetResourceVersion(version string)
 | 
						SetResourceVersion(version string)
 | 
				
			||||||
	SelfLink() string
 | 
						SelfLink() string
 | 
				
			||||||
@@ -53,6 +52,14 @@ type Interface interface {
 | 
				
			|||||||
	SetAnnotations(annotations map[string]string)
 | 
						SetAnnotations(annotations map[string]string)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TypeInterface exposes the type and APIVersion of versioned or internal API objects.
 | 
				
			||||||
 | 
					type TypeInterface interface {
 | 
				
			||||||
 | 
						APIVersion() string
 | 
				
			||||||
 | 
						SetAPIVersion(version string)
 | 
				
			||||||
 | 
						Kind() string
 | 
				
			||||||
 | 
						SetKind(kind string)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MetadataAccessor lets you work with object and list metadata from any of the versioned or
 | 
					// MetadataAccessor lets you work with object and list metadata from any of the versioned or
 | 
				
			||||||
// internal API objects. Attempting to set or retrieve a field on an object that does
 | 
					// internal API objects. Attempting to set or retrieve a field on an object that does
 | 
				
			||||||
// not support that field (Name, UID, Namespace on lists) will be a no-op and return
 | 
					// not support that field (Name, UID, Namespace on lists) will be a no-op and return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,6 +74,32 @@ func Accessor(obj interface{}) (Interface, error) {
 | 
				
			|||||||
	return a, nil
 | 
						return a, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TypeAccessor returns an interface that allows retrieving and modifying the APIVersion
 | 
				
			||||||
 | 
					// and Kind of an in-memory internal object.
 | 
				
			||||||
 | 
					// TODO: this interface is used to test code that does not have ObjectMeta or ListMeta
 | 
				
			||||||
 | 
					// in round tripping (objects which can use apiVersion/kind, but do not fit the Kube
 | 
				
			||||||
 | 
					// api conventions).
 | 
				
			||||||
 | 
					func TypeAccessor(obj interface{}) (TypeInterface, error) {
 | 
				
			||||||
 | 
						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())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typeMeta := v.FieldByName("TypeMeta")
 | 
				
			||||||
 | 
						if !typeMeta.IsValid() {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						a := &genericAccessor{}
 | 
				
			||||||
 | 
						if err := extractFromTypeMeta(typeMeta, a); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return a, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewAccessor returns a MetadataAccessor that can retrieve
 | 
					// NewAccessor returns a MetadataAccessor that can retrieve
 | 
				
			||||||
// or manipulate resource version on objects derived from core API
 | 
					// or manipulate resource version on objects derived from core API
 | 
				
			||||||
// metadata concepts.
 | 
					// metadata concepts.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,17 @@ func TestGenericTypeMeta(t *testing.T) {
 | 
				
			|||||||
		t.Errorf("expected %v, got %v", e, a)
 | 
							t.Errorf("expected %v, got %v", e, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typeAccessor, err := TypeAccessor(&j)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if e, a := "a", accessor.APIVersion(); e != a {
 | 
				
			||||||
 | 
							t.Errorf("expected %v, got %v", e, a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if e, a := "b", accessor.Kind(); e != a {
 | 
				
			||||||
 | 
							t.Errorf("expected %v, got %v", e, a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	accessor.SetNamespace("baz")
 | 
						accessor.SetNamespace("baz")
 | 
				
			||||||
	accessor.SetName("bar")
 | 
						accessor.SetName("bar")
 | 
				
			||||||
	accessor.SetUID("other")
 | 
						accessor.SetUID("other")
 | 
				
			||||||
@@ -109,6 +120,15 @@ func TestGenericTypeMeta(t *testing.T) {
 | 
				
			|||||||
	if e, a := "google.com", j.SelfLink; e != a {
 | 
						if e, a := "google.com", j.SelfLink; e != a {
 | 
				
			||||||
		t.Errorf("expected %v, got %v", e, a)
 | 
							t.Errorf("expected %v, got %v", e, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typeAccessor.SetAPIVersion("d")
 | 
				
			||||||
 | 
						typeAccessor.SetKind("e")
 | 
				
			||||||
 | 
						if e, a := "d", j.APIVersion; e != a {
 | 
				
			||||||
 | 
							t.Errorf("expected %v, got %v", e, a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if e, a := "e", j.Kind; e != a {
 | 
				
			||||||
 | 
							t.Errorf("expected %v, got %v", e, a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type InternalTypeMeta struct {
 | 
					type InternalTypeMeta struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -163,7 +163,7 @@ func fuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
 | 
				
			|||||||
func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, seed int64) runtime.Object {
 | 
					func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, seed int64) runtime.Object {
 | 
				
			||||||
	fuzzerFor(t, forVersion, rand.NewSource(seed)).Fuzz(item)
 | 
						fuzzerFor(t, forVersion, rand.NewSource(seed)).Fuzz(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	j, err := meta.Accessor(item)
 | 
						j, err := meta.TypeAccessor(item)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("Unexpected error %v for %#v", err, item)
 | 
							t.Fatalf("Unexpected error %v for %#v", err, item)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -264,7 +264,7 @@ func TestRoundTripTypes(t *testing.T) {
 | 
				
			|||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				t.Fatalf("Couldn't make a %v? %v", kind, err)
 | 
									t.Fatalf("Couldn't make a %v? %v", kind, err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if _, err := meta.Accessor(item); err != nil {
 | 
								if _, err := meta.TypeAccessor(item); err != nil {
 | 
				
			||||||
				t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err)
 | 
									t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			roundTripSame(t, item)
 | 
								roundTripSame(t, item)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -360,6 +360,9 @@ func (s *Scheme) Decode(data []byte) (Object, error) {
 | 
				
			|||||||
// pointer to an api type.
 | 
					// pointer to an api type.
 | 
				
			||||||
// If obj's APIVersion doesn't match that in data, an attempt will be made to convert
 | 
					// If obj's APIVersion doesn't match that in data, an attempt will be made to convert
 | 
				
			||||||
// data into obj's version.
 | 
					// data into obj's version.
 | 
				
			||||||
 | 
					// TODO: allow Decode/DecodeInto to take a default apiVersion and a default kind, to
 | 
				
			||||||
 | 
					// be applied if the provided object does not have either field (integrate external
 | 
				
			||||||
 | 
					// apis into the decoding scheme).
 | 
				
			||||||
func (s *Scheme) DecodeInto(data []byte, obj Object) error {
 | 
					func (s *Scheme) DecodeInto(data []byte, obj Object) error {
 | 
				
			||||||
	return s.raw.DecodeInto(data, obj)
 | 
						return s.raw.DecodeInto(data, obj)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user