diff --git a/staging/src/k8s.io/kube-apiextensions-server/pkg/apiserver/customresource_handler.go b/staging/src/k8s.io/kube-apiextensions-server/pkg/apiserver/customresource_handler.go index 4a49df3664c..d4883f7c933 100644 --- a/staging/src/k8s.io/kube-apiextensions-server/pkg/apiserver/customresource_handler.go +++ b/staging/src/k8s.io/kube-apiextensions-server/pkg/apiserver/customresource_handler.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "net/http" + "path" "sync" "sync/atomic" "time" @@ -257,14 +258,23 @@ func (r *customResourceDefinitionHandler) getServingInfoFor(customResourceDefini parameterScheme.AddGeneratedDeepCopyFuncs(metav1.GetGeneratedDeepCopyFuncs()...) parameterCodec := runtime.NewParameterCodec(parameterScheme) + selfLinkPrefix := "" + switch customResourceDefinition.Spec.Scope { + case apiextensions.ClusterScoped: + selfLinkPrefix = "/" + path.Join("apis", customResourceDefinition.Spec.Group, customResourceDefinition.Spec.Version) + "/" + case apiextensions.NamespaceScoped: + selfLinkPrefix = "/" + path.Join("apis", customResourceDefinition.Spec.Group, customResourceDefinition.Spec.Version, "namespaces") + "/" + } + requestScope := handlers.RequestScope{ Namer: handlers.ContextBasedNaming{ GetContext: func(req *http.Request) apirequest.Context { ret, _ := r.requestContextMapper.Get(req) return ret }, - SelfLinker: meta.NewAccessor(), - ClusterScoped: customResourceDefinition.Spec.Scope == apiextensions.ClusterScoped, + SelfLinker: meta.NewAccessor(), + ClusterScoped: customResourceDefinition.Spec.Scope == apiextensions.ClusterScoped, + SelfLinkPathPrefix: selfLinkPrefix, }, ContextFunc: func(req *http.Request) apirequest.Context { ret, _ := r.requestContextMapper.Get(req) diff --git a/staging/src/k8s.io/kube-apiextensions-server/test/integration/basic_test.go b/staging/src/k8s.io/kube-apiextensions-server/test/integration/basic_test.go index 6b19c459e0d..9e14fca18d9 100644 --- a/staging/src/k8s.io/kube-apiextensions-server/test/integration/basic_test.go +++ b/staging/src/k8s.io/kube-apiextensions-server/test/integration/basic_test.go @@ -167,3 +167,36 @@ func TestSimpleCRUD(t *testing.T) { t.Errorf("missing watch event") } } + +func TestSelfLink(t *testing.T) { + stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServer() + if err != nil { + t.Fatal(err) + } + defer close(stopCh) + + noxuDefinition := testserver.NewNoxuCustomResourceDefinition() + noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool) + if err != nil { + t.Fatal(err) + } + + ns := "not-the-default" + noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{ + Name: noxuDefinition.Spec.Names.Plural, + Namespaced: true, + }, ns) + + noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo") + createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate) + if err != nil { + t.Fatal(err) + } + + if e, a := "/apis/mygroup.example.com/v1alpha1/namespaces/not-the-default/noxus/foo", createdNoxuInstance.GetSelfLink(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + + // TODO add test for cluster scoped self-link when its available + +}