Define a mapping between REST resource name and kind/apiVersion

Allows clients to abstractly map user input to generic resource
paths as per docs/api-conventions.md
This commit is contained in:
Clayton Coleman
2014-10-29 12:33:46 -04:00
parent f44bb9d673
commit 191c1b975c
6 changed files with 538 additions and 53 deletions

View File

@@ -20,6 +20,7 @@ import (
"fmt"
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
@@ -59,23 +60,21 @@ var ResourceVersioner runtime.ResourceVersioner = accessor
// to go through the InterfacesFor method below.
var SelfLinker runtime.SelfLinker = accessor
// VersionInterfaces contains the interfaces one should use for dealing with types of a particular version.
type VersionInterfaces struct {
runtime.Codec
meta.MetadataAccessor
}
// RESTMapper provides the default mapping between REST paths and the objects declared in api.Scheme and all known
// Kubernetes versions.
var RESTMapper meta.RESTMapper
// InterfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
func InterfacesFor(version string) (*VersionInterfaces, error) {
func InterfacesFor(version string) (*meta.VersionInterfaces, error) {
switch version {
case "v1beta1":
return &VersionInterfaces{
return &meta.VersionInterfaces{
Codec: v1beta1.Codec,
MetadataAccessor: accessor,
}, nil
case "v1beta2":
return &VersionInterfaces{
return &meta.VersionInterfaces{
Codec: v1beta2.Codec,
MetadataAccessor: accessor,
}, nil
@@ -83,3 +82,19 @@ func InterfacesFor(version string) (*VersionInterfaces, error) {
return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(Versions, ", "))
}
}
func init() {
mapper := meta.NewDefaultRESTMapper(
Versions,
func(version string) (*meta.VersionInterfaces, bool) {
interfaces, err := InterfacesFor(version)
if err != nil {
return nil, false
}
return interfaces, true
},
)
mapper.Add(api.Scheme, true, Versions...)
// TODO: when v1beta3 is added it will not use mixed case.
RESTMapper = mapper
}

View File

@@ -186,3 +186,40 @@ func TestInterfacesFor(t *testing.T) {
}
}
}
func TestRESTMapper(t *testing.T) {
if v, k, err := RESTMapper.VersionAndKindForResource("replicationControllers"); err != nil || v != Version || k != "ReplicationController" {
t.Errorf("unexpected version mapping: %s %s %v", v, k, err)
}
if v, k, err := RESTMapper.VersionAndKindForResource("replicationcontrollers"); err != nil || v != Version || k != "ReplicationController" {
t.Errorf("unexpected version mapping: %s %s %v", v, k, err)
}
for _, version := range Versions {
mapping, err := RESTMapper.RESTMapping(version, "ReplicationController")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if mapping.Resource != "replicationControllers" && mapping.Resource != "replicationcontrollers" {
t.Errorf("incorrect resource name: %#v", mapping)
}
if mapping.APIVersion != version {
t.Errorf("incorrect version: %v", mapping)
}
interfaces, _ := InterfacesFor(version)
if mapping.Codec != interfaces.Codec {
t.Errorf("unexpected codec: %#v", mapping)
}
rc := &internal.ReplicationController{ObjectMeta: internal.ObjectMeta{Name: "foo"}}
name, err := mapping.MetadataAccessor.Name(rc)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if name != "foo" {
t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor)
}
}
}