Fix GetReference function

Kubernetes-commit: 399d09ce4ad1728fcecdce09503a07cf1bfecef6
This commit is contained in:
wojtekt 2019-08-05 08:37:55 +02:00 committed by Kubernetes Publisher
parent 4fd06e1074
commit 6dbe622bff
2 changed files with 27 additions and 42 deletions

View File

@ -19,8 +19,6 @@ package reference
import ( import (
"errors" "errors"
"fmt" "fmt"
"net/url"
"strings"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
@ -30,8 +28,7 @@ import (
var ( var (
// Errors that could be returned by GetReference. // Errors that could be returned by GetReference.
ErrNilObject = errors.New("can't reference a nil object") ErrNilObject = errors.New("can't reference a nil object")
ErrNoSelfLink = errors.New("selfLink was empty, can't make reference")
) )
// GetReference returns an ObjectReference which refers to the given // GetReference returns an ObjectReference which refers to the given
@ -47,20 +44,6 @@ func GetReference(scheme *runtime.Scheme, obj runtime.Object) (*v1.ObjectReferen
return ref, nil return ref, nil
} }
gvk := obj.GetObjectKind().GroupVersionKind()
// if the object referenced is actually persisted, we can just get kind from meta
// if we are building an object reference to something not yet persisted, we should fallback to scheme
kind := gvk.Kind
if len(kind) == 0 {
// TODO: this is wrong
gvks, _, err := scheme.ObjectKinds(obj)
if err != nil {
return nil, err
}
kind = gvks[0].Kind
}
// An object that implements only List has enough metadata to build a reference // An object that implements only List has enough metadata to build a reference
var listMeta metav1.Common var listMeta metav1.Common
objectMeta, err := meta.Accessor(obj) objectMeta, err := meta.Accessor(obj)
@ -73,29 +56,29 @@ func GetReference(scheme *runtime.Scheme, obj runtime.Object) (*v1.ObjectReferen
listMeta = objectMeta listMeta = objectMeta
} }
// if the object referenced is actually persisted, we can also get version from meta gvk := obj.GetObjectKind().GroupVersionKind()
version := gvk.GroupVersion().String()
if len(version) == 0 { // If object meta doesn't contain data about kind and/or version,
selfLink := listMeta.GetSelfLink() // we are falling back to scheme.
if len(selfLink) == 0 { //
return nil, ErrNoSelfLink // TODO: This doesn't work for CRDs, which are not registered in scheme.
} if gvk.Empty() {
selfLinkUrl, err := url.Parse(selfLink) gvks, _, err := scheme.ObjectKinds(obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// example paths: /<prefix>/<version>/* if len(gvks) == 0 || gvks[0].Empty() {
parts := strings.Split(selfLinkUrl.Path, "/") return nil, fmt.Errorf("unexpected gvks registered for object %T: %v", obj, gvks)
if len(parts) < 4 {
return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version)
}
if parts[1] == "api" {
version = parts[2]
} else {
version = parts[2] + "/" + parts[3]
} }
// TODO: The same object can be registered for multiple group versions
// (although in practise this doesn't seem to be used).
// In such case, the version set may not be correct.
gvk = gvks[0]
} }
kind := gvk.Kind
version := gvk.GroupVersion().String()
// only has list metadata // only has list metadata
if objectMeta == nil { if objectMeta == nil {
return &v1.ObjectReference{ return &v1.ObjectReference{

View File

@ -37,29 +37,31 @@ func TestGetReferenceRefVersion(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
input *TestRuntimeObj input *TestRuntimeObj
groupVersion schema.GroupVersion
expectedRefVersion string expectedRefVersion string
}{ }{
{ {
name: "api from selflink", name: "v1 GV from scheme",
input: &TestRuntimeObj{ input: &TestRuntimeObj{
ObjectMeta: metav1.ObjectMeta{SelfLink: "/api/v1/namespaces"}, ObjectMeta: metav1.ObjectMeta{SelfLink: "/bad-selflink/unused"},
}, },
groupVersion: schema.GroupVersion{Group: "", Version: "v1"},
expectedRefVersion: "v1", expectedRefVersion: "v1",
}, },
{ {
name: "foo.group/v3 from selflink", name: "foo.group/v3 GV from scheme",
input: &TestRuntimeObj{ input: &TestRuntimeObj{
ObjectMeta: metav1.ObjectMeta{SelfLink: "/apis/foo.group/v3/namespaces"}, ObjectMeta: metav1.ObjectMeta{SelfLink: "/bad-selflink/unused"},
}, },
groupVersion: schema.GroupVersion{Group: "foo.group", Version: "v3"},
expectedRefVersion: "foo.group/v3", expectedRefVersion: "foo.group/v3",
}, },
} }
scheme := runtime.NewScheme()
scheme.AddKnownTypes(schema.GroupVersion{Group: "this", Version: "is ignored"}, &TestRuntimeObj{})
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(test.groupVersion, &TestRuntimeObj{})
ref, err := GetReference(scheme, test.input) ref, err := GetReference(scheme, test.input)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)