mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Add TypeAccessor to api/meta for objects without Object/ListMeta
Adding objects that have TypeMeta (use runtime.Scheme) but do not expose ObjectMeta/ListMeta (because they are not Kube API objects) and wanted to get the simpler access path for in memory objects.
This commit is contained in:
parent
eeb712d163
commit
5f6caaba2e
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user