Browse code

API Group Version changes

Addresses comments on dc94f8dca4b2381c3a143a85af147811f746cfa5
Addresses comments on 4eba7602fea40c79c298567fd01e4493771ea3fc

Maciej Szulik authored on 2016/01/26 19:44:07
Showing 64 changed files
... ...
@@ -29,7 +29,7 @@ var (
29 29
 	inputSource   = flag.StringP("input", "i", "-", "Input source; '-' means stdin")
30 30
 	outputDest    = flag.StringP("output", "o", "-", "Output destination; '-' means stdout")
31 31
 	rewrite       = flag.StringP("rewrite", "r", "", "If nonempty, use this as both input and output.")
32
-	outputVersion = flag.StringP("out-version", "v", latest.Version, "Version to convert input to")
32
+	outputVersion = flag.StringP("out-version", "v", latest.Version.Version, "Version to convert input to")
33 33
 )
34 34
 
35 35
 // isYAML determines whether data is JSON or YAML formatted by seeing
... ...
@@ -47,12 +47,12 @@ func changeObjectsVersion(items []kruntime.Object) {
47 47
 		log.Fatalf("Unable to decode Template objects: %v", errs)
48 48
 	}
49 49
 	for i, obj := range items {
50
-		_, kind, err := api.Scheme.ObjectVersionAndKind(obj)
50
+		groupVersionKind, err := api.Scheme.ObjectKind(obj)
51 51
 		if err != nil {
52 52
 			glog.Infof("Template.Objects[%d]: Unable to determine version and kind: %v", i, err)
53 53
 			continue
54 54
 		}
55
-		mapping, err := latest.RESTMapper.RESTMapping(kind, *outputVersion)
55
+		mapping, err := latest.RESTMapper.RESTMapping(groupVersionKind.GroupKind(), *outputVersion)
56 56
 		if err != nil {
57 57
 			glog.Infof("Template.Objects[%d]: Unable to get REST mappings: %v", err)
58 58
 			continue
... ...
@@ -6,8 +6,8 @@ import (
6 6
 
7 7
 	"k8s.io/kubernetes/pkg/api"
8 8
 	kmeta "k8s.io/kubernetes/pkg/api/meta"
9
+	"k8s.io/kubernetes/pkg/api/unversioned"
9 10
 	"k8s.io/kubernetes/pkg/runtime"
10
-	"k8s.io/kubernetes/pkg/util/sets"
11 11
 
12 12
 	"github.com/golang/glog"
13 13
 
... ...
@@ -17,17 +17,17 @@ import (
17 17
 )
18 18
 
19 19
 // Version is the string that represents the current external default version.
20
-const Version = "v1"
20
+var Version = v1.SchemeGroupVersion
21 21
 
22 22
 // OldestVersion is the string that represents the oldest server version supported,
23 23
 // for client code that wants to hardcode the lowest common denominator.
24
-const OldestVersion = "v1beta3"
24
+var OldestVersion = v1beta3.SchemeGroupVersion
25 25
 
26 26
 // Versions is the list of versions that are recognized in code. The order provided
27
-// may be assumed to be least feature rich to most feature rich, and clients may
28
-// choose to prefer the latter items in the list over the former items when presented
27
+// may be assumed to be most preferred to least preferred, and clients may
28
+// choose to prefer the earlier items in the list over the latter items when presented
29 29
 // with a set of versions to choose.
30
-var Versions = []string{"v1", "v1beta3"}
30
+var Versions = []unversioned.GroupVersion{v1.SchemeGroupVersion, v1beta3.SchemeGroupVersion}
31 31
 
32 32
 // Codec is the default codec for serializing output that should use
33 33
 // the latest supported version.  Use this Codec when writing to
... ...
@@ -55,27 +55,27 @@ var RESTMapper kmeta.RESTMapper
55 55
 
56 56
 // InterfacesFor returns the default Codec and ResourceVersioner for a given version
57 57
 // string, or an error if the version is not known.
58
-func InterfacesFor(version string) (*kmeta.VersionInterfaces, error) {
58
+func InterfacesFor(version unversioned.GroupVersion) (*kmeta.VersionInterfaces, error) {
59 59
 	switch version {
60
-	case "v1beta3":
60
+	case v1beta3.SchemeGroupVersion:
61 61
 		return &kmeta.VersionInterfaces{
62 62
 			Codec:            v1beta3.Codec,
63 63
 			ObjectConvertor:  api.Scheme,
64 64
 			MetadataAccessor: accessor,
65 65
 		}, nil
66
-	case "v1":
66
+	case v1.SchemeGroupVersion:
67 67
 		return &kmeta.VersionInterfaces{
68 68
 			Codec:            v1.Codec,
69 69
 			ObjectConvertor:  api.Scheme,
70 70
 			MetadataAccessor: accessor,
71 71
 		}, nil
72 72
 	default:
73
-		return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(Versions, ", "))
73
+		return nil, fmt.Errorf("unsupported storage version: %q (valid: %v)", version, Versions)
74 74
 	}
75 75
 }
76 76
 
77 77
 // originTypes are the hardcoded types defined by the OpenShift API.
78
-var originTypes = sets.String{}
78
+var originTypes = make(map[unversioned.GroupVersionKind]bool)
79 79
 
80 80
 // UserResources are the resource names that apply to the primary, user facing resources used by
81 81
 // client tools. They are in deletion-first order - dependent resources should be last.
... ...
@@ -87,9 +87,21 @@ var UserResources = []string{
87 87
 	"pods",
88 88
 }
89 89
 
90
-// OriginKind returns true if OpenShift owns the kind described in a given apiVersion.
91
-func OriginKind(kind, apiVersion string) bool {
92
-	return originTypes.Has(kind)
90
+// OriginKind returns true if OpenShift owns the GroupVersionKind.
91
+func OriginKind(gvk unversioned.GroupVersionKind) bool {
92
+	return originTypes[gvk]
93
+}
94
+
95
+// IsKindInAnyOriginGroup returns true if OpenShift owns the kind described in any apiVersion.
96
+// TODO: this may not work once we divide builds/deployments/images into their own API groups
97
+func IsKindInAnyOriginGroup(kind string) bool {
98
+	for _, version := range Versions {
99
+		if OriginKind(version.WithKind(kind)) {
100
+			return true
101
+		}
102
+	}
103
+
104
+	return false
93 105
 }
94 106
 
95 107
 func init() {
... ...
@@ -97,13 +109,9 @@ func init() {
97 97
 	// api.RESTMapper, which is different than what you'd get from latest.
98 98
 	kubeMapper := api.RESTMapper
99 99
 
100
-	// list of versions we support on the server, in preferred order
101
-	versions := []string{"v1", "v1beta3"}
102
-
103 100
 	originMapper := kmeta.NewDefaultRESTMapper(
104
-		"",
105
-		versions,
106
-		func(version string) (*kmeta.VersionInterfaces, error) {
101
+		Versions,
102
+		func(version unversioned.GroupVersion) (*kmeta.VersionInterfaces, error) {
107 103
 			interfaces, err := InterfacesFor(version)
108 104
 			if err != nil {
109 105
 				return nil, err
... ...
@@ -143,21 +151,22 @@ func init() {
143 143
 	}
144 144
 
145 145
 	// enumerate all supported versions, get the kinds, and register with the mapper how to address our resources
146
-	for _, version := range versions {
146
+	for _, version := range Versions {
147 147
 		for kind, t := range api.Scheme.KnownTypes(version) {
148 148
 			if !strings.Contains(t.PkgPath(), "openshift/origin") {
149 149
 				if _, ok := kindToRootScope[kind]; !ok {
150 150
 					continue
151 151
 				}
152 152
 			}
153
-			originTypes.Insert(kind)
154 153
 			scope := kmeta.RESTScopeNamespace
155 154
 			_, found := kindToRootScope[kind]
156 155
 			if found || (strings.HasSuffix(kind, "List") && kindToRootScope[strings.TrimSuffix(kind, "List")]) {
157 156
 				scope = kmeta.RESTScopeRoot
158 157
 			}
159
-			glog.V(6).Infof("Registering %s %s %s", kind, version, scope.Name())
160
-			originMapper.Add(scope, kind, version, false)
158
+			gvk := version.WithKind(kind)
159
+			originTypes[gvk] = true
160
+			glog.V(6).Infof("Registering %s %s", gvk.String(), scope.Name())
161
+			originMapper.Add(gvk, scope, false)
161 162
 		}
162 163
 	}
163 164
 
... ...
@@ -3,12 +3,14 @@ package latest
3 3
 import (
4 4
 	"testing"
5 5
 
6
+	kapi "k8s.io/kubernetes/pkg/api"
7
+	klatest "k8s.io/kubernetes/pkg/api/latest"
6 8
 	"k8s.io/kubernetes/pkg/api/meta"
7 9
 )
8 10
 
9 11
 func TestRESTRootScope(t *testing.T) {
10 12
 	for _, v := range [][]string{{"v1beta3"}, {"v1"}} {
11
-		mapping, err := RESTMapper.RESTMapping("Node", v...)
13
+		mapping, err := RESTMapper.RESTMapping(kapi.Kind("Node"), v...)
12 14
 		if err != nil {
13 15
 			t.Fatal(err)
14 16
 		}
... ...
@@ -17,3 +19,27 @@ func TestRESTRootScope(t *testing.T) {
17 17
 		}
18 18
 	}
19 19
 }
20
+
21
+func TestResourceToKind(t *testing.T) {
22
+	// Ensure we resolve to latest.Version
23
+	expectedGVK := Version.WithKind("User")
24
+	gvk, err := RESTMapper.KindFor("user")
25
+	if err != nil {
26
+		t.Fatalf("Unexpected error: %v", err)
27
+	}
28
+	if gvk != expectedGVK {
29
+		t.Fatalf("Expected RESTMapper.KindFor('user') to be %#v, got %#v", expectedGVK, gvk)
30
+	}
31
+}
32
+
33
+func TestUpstreamResourceToKind(t *testing.T) {
34
+	// Ensure we resolve to klatest.ExternalVersions[0]
35
+	expectedGVK := klatest.ExternalVersions[0].WithKind("Pod")
36
+	gvk, err := klatest.GroupOrDie(kapi.SchemeGroupVersion.Group).RESTMapper.KindFor("pod")
37
+	if err != nil {
38
+		t.Fatalf("Unexpected error: %v", err)
39
+	}
40
+	if gvk != expectedGVK {
41
+		t.Fatalf("Expected RESTMapper.KindFor('pod') to be %#v, got %#v", expectedGVK, gvk)
42
+	}
43
+}
... ...
@@ -10,11 +10,13 @@ import (
10 10
 	"k8s.io/kubernetes/pkg/api/unversioned"
11 11
 	"k8s.io/kubernetes/pkg/runtime"
12 12
 	"k8s.io/kubernetes/pkg/util/sets"
13
+
14
+	"github.com/openshift/origin/pkg/api"
13 15
 )
14 16
 
15 17
 func TestDescriptions(t *testing.T) {
16 18
 	for _, version := range Versions {
17
-		if version == "v1beta3" {
19
+		if version == OldestVersion {
18 20
 			// we don't care about descriptions here
19 21
 			continue
20 22
 		}
... ...
@@ -63,7 +65,7 @@ func checkDescriptions(objType reflect.Type, seen *map[reflect.Type]bool, t *tes
63 63
 func TestInternalJsonTags(t *testing.T) {
64 64
 	seen := map[reflect.Type]bool{}
65 65
 
66
-	for _, apiType := range kapi.Scheme.KnownTypes("") {
66
+	for _, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) {
67 67
 		checkJsonTags(apiType, &seen, t)
68 68
 	}
69 69
 }
... ...
@@ -3,6 +3,7 @@ package api
3 3
 import (
4 4
 	"k8s.io/kubernetes/pkg/api"
5 5
 	"k8s.io/kubernetes/pkg/api/unversioned"
6
+	"k8s.io/kubernetes/pkg/runtime"
6 7
 
7 8
 	_ "github.com/openshift/origin/pkg/authorization/api"
8 9
 	_ "github.com/openshift/origin/pkg/build/api"
... ...
@@ -19,6 +20,10 @@ import (
19 19
 // SchemeGroupVersion is group version used to register these objects
20 20
 var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: ""}
21 21
 
22
+// Codec is the identity codec for this package - it can only convert itself
23
+// to itself.
24
+var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String())
25
+
22 26
 // Kind takes an unqualified kind and returns back a Group qualified GroupKind
23 27
 func Kind(kind string) unversioned.GroupKind {
24 28
 	return SchemeGroupVersion.WithKind(kind).GroupKind()
... ...
@@ -9,7 +9,7 @@ import (
9 9
 	"time"
10 10
 
11 11
 	"github.com/google/gofuzz"
12
-	"k8s.io/kubernetes/pkg/api"
12
+	kapi "k8s.io/kubernetes/pkg/api"
13 13
 	"k8s.io/kubernetes/pkg/api/meta"
14 14
 	apitesting "k8s.io/kubernetes/pkg/api/testing"
15 15
 	"k8s.io/kubernetes/pkg/api/validation"
... ...
@@ -147,7 +147,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
147 147
 			c.FuzzNoCustom(j)
148 148
 			if j.To == nil {
149 149
 				// To is defaulted to be not nil
150
-				j.To = &api.LocalObjectReference{}
150
+				j.To = &kapi.LocalObjectReference{}
151 151
 			}
152 152
 		},
153 153
 		func(j *image.ImageStreamImage, c fuzz.Continue) {
... ...
@@ -221,7 +221,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
221 221
 		},
222 222
 		func(j *route.RouteSpec, c fuzz.Continue) {
223 223
 			c.FuzzNoCustom(j)
224
-			j.To = api.ObjectReference{
224
+			j.To = kapi.ObjectReference{
225 225
 				Kind: "Service",
226 226
 				Name: j.To.Name,
227 227
 			}
... ...
@@ -299,7 +299,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
299 299
 			j.From.Kind = "DockerImage"
300 300
 			j.From.Name = specs[c.Intn(len(specs))]
301 301
 		},
302
-		func(j *api.PodSecurityContext, c fuzz.Continue) {
302
+		func(j *kapi.PodSecurityContext, c fuzz.Continue) {
303 303
 			c.FuzzNoCustom(j)
304 304
 			if forVersion == "v1beta3" {
305 305
 				// v1beta3 does not contain the PodSecurityContext type.  For this API version, only fuzz
... ...
@@ -312,7 +312,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
312 312
 				j.FSGroup = nil
313 313
 			}
314 314
 		},
315
-		func(j *api.GitRepoVolumeSource, c fuzz.Continue) {
315
+		func(j *kapi.GitRepoVolumeSource, c fuzz.Continue) {
316 316
 			c.FuzzNoCustom(j)
317 317
 			if forVersion == "v1beta3" {
318 318
 				// these fields are set to their empty state when testing v1beta3
... ...
@@ -320,7 +320,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
320 320
 				j.Directory = ""
321 321
 			}
322 322
 		},
323
-		func(j *api.ISCSIVolumeSource, c fuzz.Continue) {
323
+		func(j *kapi.ISCSIVolumeSource, c fuzz.Continue) {
324 324
 			c.FuzzNoCustom(j)
325 325
 			if forVersion == "v1beta3" {
326 326
 				// these fields are set to their empty state when testing v1beta3
... ...
@@ -331,7 +331,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
331 331
 				j.ISCSIInterface = "default"
332 332
 			}
333 333
 		},
334
-		func(j *api.Event, c fuzz.Continue) {
334
+		func(j *kapi.Event, c fuzz.Continue) {
335 335
 			c.FuzzNoCustom(j)
336 336
 			if forVersion == "v1beta3" {
337 337
 				// these fields are set to their empty state when testing v1beta3
... ...
@@ -339,7 +339,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
339 339
 				j.Type = ""
340 340
 			}
341 341
 		},
342
-		func(j *api.Probe, c fuzz.Continue) {
342
+		func(j *kapi.Probe, c fuzz.Continue) {
343 343
 			c.FuzzNoCustom(j)
344 344
 			if forVersion == "v1beta3" {
345 345
 				// these fields are set to their empty state when testing v1beta3
... ...
@@ -381,7 +381,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se
381 381
 func roundTrip(t *testing.T, codec runtime.Codec, originalItem runtime.Object) {
382 382
 	// Make a copy of the originalItem to give to conversion functions
383 383
 	// This lets us know if conversion messed with the input object
384
-	deepCopy, err := api.Scheme.DeepCopy(originalItem)
384
+	deepCopy, err := kapi.Scheme.DeepCopy(originalItem)
385 385
 	if err != nil {
386 386
 		t.Errorf("Could not copy object: %v", err)
387 387
 		return
... ...
@@ -406,13 +406,13 @@ func roundTrip(t *testing.T, codec runtime.Codec, originalItem runtime.Object) {
406 406
 	}
407 407
 	if reflect.TypeOf(item) != reflect.TypeOf(obj2) {
408 408
 		obj2conv := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object)
409
-		if err := api.Scheme.Convert(obj2, obj2conv); err != nil {
409
+		if err := kapi.Scheme.Convert(obj2, obj2conv); err != nil {
410 410
 			t.Errorf("0X: no conversion from %v to %v: %v", reflect.TypeOf(item), reflect.TypeOf(obj2), err)
411 411
 			return
412 412
 		}
413 413
 		obj2 = obj2conv
414 414
 	}
415
-	if !api.Semantic.DeepEqual(originalItem, obj2) {
415
+	if !kapi.Semantic.DeepEqual(originalItem, obj2) {
416 416
 		t.Errorf("1: %v: diff: %v\nCodec: %v\nData: %s\nSource: %s", name, util.ObjectDiff(originalItem, obj2), codec, string(data), util.ObjectGoPrintSideBySide(originalItem, obj2))
417 417
 		return
418 418
 	}
... ...
@@ -423,7 +423,7 @@ func roundTrip(t *testing.T, codec runtime.Codec, originalItem runtime.Object) {
423 423
 		t.Errorf("2: %v: %v", name, err)
424 424
 		return
425 425
 	}
426
-	if !api.Semantic.DeepEqual(originalItem, obj3) {
426
+	if !kapi.Semantic.DeepEqual(originalItem, obj3) {
427 427
 		t.Errorf("3: %v: diff: %v\nCodec: %v", name, util.ObjectDiff(originalItem, obj3), codec)
428 428
 		return
429 429
 	}
... ...
@@ -440,11 +440,11 @@ const fuzzIters = 20
440 440
 
441 441
 // For debugging problems
442 442
 func TestSpecificKind(t *testing.T) {
443
-	api.Scheme.Log(t)
444
-	defer api.Scheme.Log(nil)
443
+	kapi.Scheme.Log(t)
444
+	defer kapi.Scheme.Log(nil)
445 445
 
446 446
 	kind := "DeploymentConfig"
447
-	item, err := api.Scheme.New("", kind)
447
+	item, err := kapi.Scheme.New(osapi.SchemeGroupVersion.WithKind(kind))
448 448
 	if err != nil {
449 449
 		t.Errorf("Couldn't make a %v? %v", kind, err)
450 450
 		return
... ...
@@ -468,7 +468,7 @@ var nonInternalRoundTrippableTypes = sets.NewString("List", "ListOptions", "PodE
468 468
 
469 469
 // TestTypes will try to roundtrip all OpenShift and Kubernetes stable api types
470 470
 func TestTypes(t *testing.T) {
471
-	for kind, reflectType := range api.Scheme.KnownTypes("") {
471
+	for kind, reflectType := range kapi.Scheme.KnownTypes(osapi.SchemeGroupVersion) {
472 472
 		if !strings.Contains(reflectType.PkgPath(), "/origin/") && reflectType.PkgPath() != "k8s.io/kubernetes/pkg/api" {
473 473
 			continue
474 474
 		}
... ...
@@ -477,7 +477,7 @@ func TestTypes(t *testing.T) {
477 477
 		}
478 478
 		// Try a few times, since runTest uses random values.
479 479
 		for i := 0; i < fuzzIters; i++ {
480
-			item, err := api.Scheme.New("", kind)
480
+			item, err := kapi.Scheme.New(osapi.SchemeGroupVersion.WithKind(kind))
481 481
 			if err != nil {
482 482
 				t.Errorf("Couldn't make a %v? %v", kind, err)
483 483
 				continue
... ...
@@ -491,7 +491,7 @@ func TestTypes(t *testing.T) {
491 491
 				for _, v := range versions {
492 492
 					t.Logf("About to test %v with %q", kind, v)
493 493
 					fuzzInternalObject(t, v, item, seed)
494
-					roundTrip(t, runtime.CodecFor(api.Scheme, v), item)
494
+					roundTrip(t, runtime.CodecFor(kapi.Scheme, v), item)
495 495
 				}
496 496
 				continue
497 497
 			}
... ...
@@ -7,6 +7,7 @@ import (
7 7
 
8 8
 	kapi "k8s.io/kubernetes/pkg/api"
9 9
 
10
+	"github.com/openshift/origin/pkg/api"
10 11
 	authorizationapi "github.com/openshift/origin/pkg/authorization/api"
11 12
 	buildapi "github.com/openshift/origin/pkg/build/api"
12 13
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
... ...
@@ -35,7 +36,7 @@ var MissingValidationExceptions = []reflect.Type{
35 35
 }
36 36
 
37 37
 func TestCoverage(t *testing.T) {
38
-	for kind, apiType := range kapi.Scheme.KnownTypes("") {
38
+	for kind, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) {
39 39
 		if !strings.Contains(apiType.PkgPath(), "openshift/origin") {
40 40
 			continue
41 41
 		}
... ...
@@ -118,12 +118,12 @@ func (v *RuntimeObjectsValidator) getSpecificValidationInfo(obj runtime.Object)
118 118
 }
119 119
 
120 120
 func GetRequiresNamespace(obj runtime.Object) (bool, error) {
121
-	version, kind, err := kapi.Scheme.ObjectVersionAndKind(obj)
121
+	groupVersionKind, err := kapi.Scheme.ObjectKind(obj)
122 122
 	if err != nil {
123 123
 		return false, err
124 124
 	}
125 125
 
126
-	restMapping, err := latest.RESTMapper.RESTMapping(kind, version)
126
+	restMapping, err := latest.RESTMapper.RESTMapping(groupVersionKind.GroupKind())
127 127
 	if err != nil {
128 128
 		return false, err
129 129
 	}
... ...
@@ -38,9 +38,9 @@ func NewBuildByStrategy() admission.Interface {
38 38
 	}
39 39
 }
40 40
 
41
-const (
42
-	buildsResource       = "builds"
43
-	buildConfigsResource = "buildconfigs"
41
+var (
42
+	buildsResource       = buildapi.Resource("builds")
43
+	buildConfigsResource = buildapi.Resource("buildconfigs")
44 44
 )
45 45
 
46 46
 func (a *buildByStrategy) Admit(attr admission.Attributes) error {
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"k8s.io/kubernetes/pkg/admission"
8 8
 	kapi "k8s.io/kubernetes/pkg/api"
9 9
 	apierrors "k8s.io/kubernetes/pkg/api/errors"
10
+	"k8s.io/kubernetes/pkg/api/unversioned"
10 11
 	"k8s.io/kubernetes/pkg/auth/user"
11 12
 	ktestclient "k8s.io/kubernetes/pkg/client/unversioned/testclient"
12 13
 	"k8s.io/kubernetes/pkg/runtime"
... ...
@@ -21,8 +22,8 @@ import (
21 21
 func TestBuildAdmission(t *testing.T) {
22 22
 	tests := []struct {
23 23
 		name             string
24
-		kind             string
25
-		resource         string
24
+		kind             unversioned.GroupKind
25
+		resource         unversioned.GroupResource
26 26
 		subResource      string
27 27
 		object           runtime.Object
28 28
 		responseObject   runtime.Object
... ...
@@ -34,7 +35,7 @@ func TestBuildAdmission(t *testing.T) {
34 34
 		{
35 35
 			name:             "allowed source build",
36 36
 			object:           testBuild(buildapi.BuildStrategy{SourceStrategy: &buildapi.SourceBuildStrategy{}}),
37
-			kind:             "Build",
37
+			kind:             buildapi.Kind("Build"),
38 38
 			resource:         buildsResource,
39 39
 			reviewResponse:   reviewResponse(true, ""),
40 40
 			expectedResource: authorizationapi.SourceBuildResource,
... ...
@@ -44,7 +45,7 @@ func TestBuildAdmission(t *testing.T) {
44 44
 			name:             "allowed source build clone",
45 45
 			object:           testBuildRequest("buildname"),
46 46
 			responseObject:   testBuild(buildapi.BuildStrategy{SourceStrategy: &buildapi.SourceBuildStrategy{}}),
47
-			kind:             "Build",
47
+			kind:             buildapi.Kind("Build"),
48 48
 			resource:         buildsResource,
49 49
 			subResource:      "clone",
50 50
 			reviewResponse:   reviewResponse(true, ""),
... ...
@@ -54,7 +55,7 @@ func TestBuildAdmission(t *testing.T) {
54 54
 		{
55 55
 			name:             "denied docker build",
56 56
 			object:           testBuild(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}),
57
-			kind:             "Build",
57
+			kind:             buildapi.Kind("Build"),
58 58
 			resource:         buildsResource,
59 59
 			reviewResponse:   reviewResponse(false, "cannot create build of type docker build"),
60 60
 			expectAccept:     false,
... ...
@@ -64,7 +65,7 @@ func TestBuildAdmission(t *testing.T) {
64 64
 			name:             "denied docker build clone",
65 65
 			object:           testBuildRequest("buildname"),
66 66
 			responseObject:   testBuild(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}),
67
-			kind:             "Build",
67
+			kind:             buildapi.Kind("Build"),
68 68
 			resource:         buildsResource,
69 69
 			subResource:      "clone",
70 70
 			reviewResponse:   reviewResponse(false, "cannot create build of type docker build"),
... ...
@@ -74,7 +75,7 @@ func TestBuildAdmission(t *testing.T) {
74 74
 		{
75 75
 			name:             "allowed custom build",
76 76
 			object:           testBuild(buildapi.BuildStrategy{CustomStrategy: &buildapi.CustomBuildStrategy{}}),
77
-			kind:             "Build",
77
+			kind:             buildapi.Kind("Build"),
78 78
 			resource:         buildsResource,
79 79
 			reviewResponse:   reviewResponse(true, ""),
80 80
 			expectedResource: authorizationapi.CustomBuildResource,
... ...
@@ -83,7 +84,7 @@ func TestBuildAdmission(t *testing.T) {
83 83
 		{
84 84
 			name:             "allowed build config",
85 85
 			object:           testBuildConfig(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}),
86
-			kind:             "BuildConfig",
86
+			kind:             buildapi.Kind("BuildConfig"),
87 87
 			resource:         buildConfigsResource,
88 88
 			reviewResponse:   reviewResponse(true, ""),
89 89
 			expectAccept:     true,
... ...
@@ -93,7 +94,7 @@ func TestBuildAdmission(t *testing.T) {
93 93
 			name:             "allowed build config instantiate",
94 94
 			responseObject:   testBuildConfig(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}),
95 95
 			object:           testBuildRequest("buildname"),
96
-			kind:             "BuildConfig",
96
+			kind:             buildapi.Kind("Build"),
97 97
 			resource:         buildConfigsResource,
98 98
 			subResource:      "instantiate",
99 99
 			reviewResponse:   reviewResponse(true, ""),
... ...
@@ -103,7 +104,7 @@ func TestBuildAdmission(t *testing.T) {
103 103
 		{
104 104
 			name:             "forbidden build config",
105 105
 			object:           testBuildConfig(buildapi.BuildStrategy{CustomStrategy: &buildapi.CustomBuildStrategy{}}),
106
-			kind:             "BuildConfig",
106
+			kind:             buildapi.Kind("Build"),
107 107
 			resource:         buildConfigsResource,
108 108
 			reviewResponse:   reviewResponse(false, ""),
109 109
 			expectAccept:     false,
... ...
@@ -113,7 +114,7 @@ func TestBuildAdmission(t *testing.T) {
113 113
 			name:             "forbidden build config instantiate",
114 114
 			responseObject:   testBuildConfig(buildapi.BuildStrategy{CustomStrategy: &buildapi.CustomBuildStrategy{}}),
115 115
 			object:           testBuildRequest("buildname"),
116
-			kind:             "BuildConfig",
116
+			kind:             buildapi.Kind("Build"),
117 117
 			resource:         buildConfigsResource,
118 118
 			subResource:      "instantiate",
119 119
 			reviewResponse:   reviewResponse(false, ""),
... ...
@@ -123,7 +124,7 @@ func TestBuildAdmission(t *testing.T) {
123 123
 		{
124 124
 			name:           "unrecognized request object",
125 125
 			object:         &fakeObject{},
126
-			kind:           "BuildConfig",
126
+			kind:           buildapi.Kind("BuildConfig"),
127 127
 			resource:       buildConfigsResource,
128 128
 			reviewResponse: reviewResponse(true, ""),
129 129
 			expectAccept:   false,
... ...
@@ -132,7 +133,7 @@ func TestBuildAdmission(t *testing.T) {
132 132
 		{
133 133
 			name:           "details on forbidden docker build",
134 134
 			object:         testBuild(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}),
135
-			kind:           "Build",
135
+			kind:           buildapi.Kind("Build"),
136 136
 			resource:       buildsResource,
137 137
 			subResource:    "details",
138 138
 			reviewResponse: reviewResponse(false, "cannot create build of type docker build"),
... ...
@@ -128,7 +128,7 @@ func (bs *SourceBuildStrategy) canRunAsRoot(build *buildapi.Build) bool {
128 128
 		},
129 129
 	}
130 130
 	userInfo := serviceaccount.UserInfo(build.Namespace, build.Spec.ServiceAccount, "")
131
-	attrs := admission.NewAttributesRecord(pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, userInfo)
131
+	attrs := admission.NewAttributesRecord(pod, kapi.Kind("Pod"), pod.Namespace, pod.Name, kapi.Resource("pods"), "", admission.Create, userInfo)
132 132
 	err := bs.AdmissionControl.Admit(attrs)
133 133
 	if err != nil {
134 134
 		glog.V(2).Infof("Admit for root user returned error: %v", err)
... ...
@@ -268,17 +268,18 @@ func SetOpenShiftDefaults(config *kclient.Config) error {
268 268
 	if len(config.UserAgent) == 0 {
269 269
 		config.UserAgent = DefaultOpenShiftUserAgent()
270 270
 	}
271
-	if config.Version == "" {
271
+	if config.GroupVersion == nil {
272 272
 		// Clients default to the preferred code API version
273
-		config.Version = latest.Version
273
+		groupVersionCopy := latest.Version
274
+		config.GroupVersion = &groupVersionCopy
274 275
 	}
275 276
 	if config.Prefix == "" {
276 277
 		config.Prefix = "/oapi"
277 278
 	}
278
-	version := config.Version
279
-	versionInterfaces, err := latest.InterfacesFor(version)
279
+	version := config.GroupVersion
280
+	versionInterfaces, err := latest.InterfacesFor(*version)
280 281
 	if err != nil {
281
-		return fmt.Errorf("API version '%s' is not recognized (valid values: %s)", version, strings.Join(latest.Versions, ", "))
282
+		return fmt.Errorf("API version %q is not recognized (valid values: %v)", version, latest.Versions)
282 283
 	}
283 284
 	if config.Codec == nil {
284 285
 		config.Codec = versionInterfaces.Codec
... ...
@@ -3,10 +3,11 @@ package client
3 3
 import (
4 4
 	"fmt"
5 5
 
6
-	"github.com/openshift/origin/pkg/api/latest"
7 6
 	"k8s.io/kubernetes/pkg/api/errors"
8 7
 	"k8s.io/kubernetes/pkg/apis/extensions"
9 8
 	kclient "k8s.io/kubernetes/pkg/client/unversioned"
9
+
10
+	"github.com/openshift/origin/pkg/api/latest"
10 11
 )
11 12
 
12 13
 type delegatingScaleInterface struct {
... ...
@@ -38,7 +39,8 @@ func (c *delegatingScaleInterface) Get(kind string, name string) (result *extens
38 38
 	switch {
39 39
 	case kind == "DeploymentConfig":
40 40
 		return c.dcs.GetScale(name)
41
-	case latest.OriginKind(kind, ""):
41
+	// TODO: This is borked because the interface for Get is broken. Kind is insufficient.
42
+	case latest.IsKindInAnyOriginGroup(kind):
42 43
 		return nil, errors.NewBadRequest(fmt.Sprintf("Kind %s has no Scale subresource", kind))
43 44
 	default:
44 45
 		return c.scales.Get(kind, name)
... ...
@@ -51,7 +53,8 @@ func (c *delegatingScaleInterface) Update(kind string, scale *extensions.Scale)
51 51
 	switch {
52 52
 	case kind == "DeploymentConfig":
53 53
 		return c.dcs.UpdateScale(scale)
54
-	case latest.OriginKind(kind, ""):
54
+	// TODO: This is borked because the interface for Update is broken. Kind is insufficient.
55
+	case latest.IsKindInAnyOriginGroup(kind):
55 56
 		return nil, errors.NewBadRequest(fmt.Sprintf("Kind %s has no Scale subresource", kind))
56 57
 	default:
57 58
 		return c.scales.Update(kind, scale)
... ...
@@ -11,6 +11,7 @@ import (
11 11
 
12 12
 	kapi "k8s.io/kubernetes/pkg/api"
13 13
 	"k8s.io/kubernetes/pkg/api/meta"
14
+	"k8s.io/kubernetes/pkg/api/unversioned"
14 15
 	client "k8s.io/kubernetes/pkg/client/unversioned"
15 16
 	"k8s.io/kubernetes/pkg/kubectl"
16 17
 	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
... ...
@@ -155,23 +156,23 @@ func (n *NodeOptions) GetNodes() ([]*kapi.Node, error) {
155 155
 }
156 156
 
157 157
 func (n *NodeOptions) GetPrintersByObject(obj runtime.Object) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) {
158
-	version, kind, err := kapi.Scheme.ObjectVersionAndKind(obj)
158
+	gvk, err := kapi.Scheme.ObjectKind(obj)
159 159
 	if err != nil {
160 160
 		return nil, nil, err
161 161
 	}
162
-	return n.GetPrinters(kind, version)
162
+	return n.GetPrinters(gvk)
163 163
 }
164 164
 
165 165
 func (n *NodeOptions) GetPrintersByResource(resource string) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) {
166
-	version, kind, err := n.Mapper.VersionAndKindForResource(resource)
166
+	gvk, err := n.Mapper.KindFor(resource)
167 167
 	if err != nil {
168 168
 		return nil, nil, err
169 169
 	}
170
-	return n.GetPrinters(kind, version)
170
+	return n.GetPrinters(gvk)
171 171
 }
172 172
 
173
-func (n *NodeOptions) GetPrinters(kind, version string) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) {
174
-	mapping, err := n.Mapper.RESTMapping(kind, version)
173
+func (n *NodeOptions) GetPrinters(gvk unversioned.GroupVersionKind) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) {
174
+	mapping, err := n.Mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
175 175
 	if err != nil {
176 176
 		return nil, nil, err
177 177
 	}
... ...
@@ -37,7 +37,7 @@ type EditOptions struct {
37 37
 
38 38
 	ext       string
39 39
 	filenames []string
40
-	version   string
40
+	version   unversioned.GroupVersion
41 41
 	fullName  string
42 42
 }
43 43
 
... ...
@@ -145,8 +145,8 @@ func (o *EditOptions) Complete(fullName string, f *clientcmd.Factory, out io.Wri
145 145
 		return err
146 146
 	}
147 147
 
148
-	o.version = cmdutil.OutputVersion(cmd, clientConfig.Version)
149
-	return nil
148
+	o.version, err = cmdutil.OutputVersion(cmd, clientConfig.GroupVersion)
149
+	return err
150 150
 }
151 151
 
152 152
 // RunEdit contains all the necessary functionality for the OpenShift cli edit command.
... ...
@@ -158,7 +158,7 @@ func (o *EditOptions) RunEdit() error {
158 158
 		return err
159 159
 	}
160 160
 	for {
161
-		obj, err := resource.AsVersionedObject(infos, false, o.version)
161
+		obj, err := resource.AsVersionedObject(infos, false, o.version.String())
162 162
 		if err != nil {
163 163
 			return preservedFile(err, results.file, o.out)
164 164
 		}
... ...
@@ -332,7 +332,7 @@ type editResults struct {
332 332
 	file      string
333 333
 
334 334
 	delta   *jsonmerge.Delta
335
-	version string
335
+	version unversioned.GroupVersion
336 336
 }
337 337
 
338 338
 func (r *editResults) AddError(err error, info *resource.Info) string {
... ...
@@ -340,7 +340,7 @@ func (r *editResults) AddError(err error, info *resource.Info) string {
340 340
 	case errors.IsInvalid(err):
341 341
 		r.edit = append(r.edit, info)
342 342
 		reason := editReason{
343
-			head: fmt.Sprintf("%s %s was not valid", info.Mapping.Kind, info.Name),
343
+			head: fmt.Sprintf("%s %s was not valid", info.Mapping.GroupVersionKind.Kind, info.Name),
344 344
 		}
345 345
 		if err, ok := err.(errors.APIStatus); ok {
346 346
 			if details := err.Status().Details; details != nil {
... ...
@@ -350,15 +350,15 @@ func (r *editResults) AddError(err error, info *resource.Info) string {
350 350
 			}
351 351
 		}
352 352
 		r.header.reasons = append(r.header.reasons, reason)
353
-		return fmt.Sprintf("Error: the %s %s is invalid", info.Mapping.Kind, info.Name)
353
+		return fmt.Sprintf("Error: the %s %s is invalid", info.Mapping.GroupVersionKind.Kind, info.Name)
354 354
 	case errors.IsNotFound(err):
355 355
 		r.notfound++
356
-		return fmt.Sprintf("Error: the %s %s has been deleted on the server", info.Mapping.Kind, info.Name)
356
+		return fmt.Sprintf("Error: the %s %s has been deleted on the server", info.Mapping.GroupVersionKind.Kind, info.Name)
357 357
 
358 358
 	case errors.IsConflict(err):
359 359
 		if r.delta != nil {
360 360
 			v1 := info.ResourceVersion
361
-			if perr := applyPatch(r.delta, info, r.version); perr != nil {
361
+			if perr := applyPatch(r.delta, info, r.version.String()); perr != nil {
362 362
 				// the error was related to the patching process
363 363
 				if nerr, ok := perr.(patchError); ok {
364 364
 					r.conflict++
... ...
@@ -368,7 +368,7 @@ func (r *editResults) AddError(err error, info *resource.Info) string {
368 368
 					// the patch is in conflict, report to user and exit
369 369
 					if jsonmerge.IsConflicting(nerr.error) {
370 370
 						// TODO: read message
371
-						return fmt.Sprintf("Error: a conflicting change was made to the %s %s on the server", info.Mapping.Kind, info.Name)
371
+						return fmt.Sprintf("Error: a conflicting change was made to the %s %s on the server", info.Mapping.GroupVersionKind.Kind, info.Name)
372 372
 					}
373 373
 					glog.V(4).Infof("Attempted to patch the resource, but failed: %v", perr)
374 374
 					return fmt.Sprintf("Error: %v", err)
... ...
@@ -384,7 +384,7 @@ func (r *editResults) AddError(err error, info *resource.Info) string {
384 384
 		return fmt.Sprintf("Error: %v", err)
385 385
 	default:
386 386
 		r.retryable++
387
-		return fmt.Sprintf("Error: the %s %s could not be updated: %v", info.Mapping.Kind, info.Name, err)
387
+		return fmt.Sprintf("Error: the %s %s could not be updated: %v", info.Mapping.GroupVersionKind.Kind, info.Name, err)
388 388
 	}
389 389
 }
390 390
 
... ...
@@ -235,12 +235,12 @@ func RunEnv(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Comman
235 235
 	}
236 236
 	// Keep a copy of the original objects prior to updating their environment.
237 237
 	// Used in constructing the patch(es) that will be applied in the server.
238
-	oldObjects, err := resource.AsVersionedObjects(infos, clientConfig.Version)
238
+	oldObjects, err := resource.AsVersionedObjects(infos, clientConfig.GroupVersion.String())
239 239
 	if err != nil {
240 240
 		return err
241 241
 	}
242 242
 	if len(oldObjects) != len(infos) {
243
-		return fmt.Errorf("could not convert all objects to API version %q", clientConfig.Version)
243
+		return fmt.Errorf("could not convert all objects to API version %q", clientConfig.GroupVersion)
244 244
 	}
245 245
 	oldData := make([][]byte, len(infos))
246 246
 	for i := range oldObjects {
... ...
@@ -294,8 +294,11 @@ func RunEnv(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Comman
294 294
 	}
295 295
 
296 296
 	if len(outputFormat) != 0 {
297
-		outputVersion := cmdutil.OutputVersion(cmd, clientConfig.Version)
298
-		objects, err := resource.AsVersionedObjects(infos, outputVersion)
297
+		outputVersion, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion)
298
+		if err != nil {
299
+			return err
300
+		}
301
+		objects, err := resource.AsVersionedObjects(infos, outputVersion.String())
299 302
 		if err != nil {
300 303
 			return err
301 304
 		}
... ...
@@ -314,12 +317,12 @@ func RunEnv(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Comman
314 314
 		return nil
315 315
 	}
316 316
 
317
-	objects, err := resource.AsVersionedObjects(infos, clientConfig.Version)
317
+	objects, err := resource.AsVersionedObjects(infos, clientConfig.GroupVersion.String())
318 318
 	if err != nil {
319 319
 		return err
320 320
 	}
321 321
 	if len(objects) != len(infos) {
322
-		return fmt.Errorf("could not convert all objects to API version %q", clientConfig.Version)
322
+		return fmt.Errorf("could not convert all objects to API version %q", clientConfig.GroupVersion)
323 323
 	}
324 324
 
325 325
 	failed := false
... ...
@@ -92,7 +92,10 @@ func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Wri
92 92
 	if err != nil {
93 93
 		return err
94 94
 	}
95
-	outputVersion := cmdutil.OutputVersion(cmd, clientConfig.Version)
95
+	outputVersion, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion)
96
+	if err != nil {
97
+		return err
98
+	}
96 99
 
97 100
 	cmdNamespace, explicit, err := f.DefaultNamespace()
98 101
 	if err != nil {
... ...
@@ -137,7 +140,7 @@ func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Wri
137 137
 
138 138
 	var result runtime.Object
139 139
 	if len(asTemplate) > 0 {
140
-		objects, err := resource.AsVersionedObjects(infos, outputVersion)
140
+		objects, err := resource.AsVersionedObjects(infos, outputVersion.String())
141 141
 		if err != nil {
142 142
 			return err
143 143
 		}
... ...
@@ -145,12 +148,12 @@ func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Wri
145 145
 			Objects: objects,
146 146
 		}
147 147
 		template.Name = asTemplate
148
-		result, err = kapi.Scheme.ConvertToVersion(template, outputVersion)
148
+		result, err = kapi.Scheme.ConvertToVersion(template, outputVersion.String())
149 149
 		if err != nil {
150 150
 			return err
151 151
 		}
152 152
 	} else {
153
-		object, err := resource.AsVersionedObject(infos, !one, outputVersion)
153
+		object, err := resource.AsVersionedObject(infos, !one, outputVersion.String())
154 154
 		if err != nil {
155 155
 			return err
156 156
 		}
... ...
@@ -92,8 +92,8 @@ func validate(cmd *cobra.Command, f *clientcmd.Factory, args []string) error {
92 92
 	mapping := info.ResourceMapping()
93 93
 
94 94
 	generator := cmdutil.GetFlagString(cmd, "generator")
95
-	switch mapping.Kind {
96
-	case "Service":
95
+	switch mapping.GroupVersionKind.GroupKind() {
96
+	case kapi.Kind("Service"):
97 97
 		switch generator {
98 98
 		case "service/v1", "service/v2":
99 99
 			// Set default protocol back for generating services
... ...
@@ -135,7 +135,7 @@ func validate(cmd *cobra.Command, f *clientcmd.Factory, args []string) error {
135 135
 	default:
136 136
 		switch generator {
137 137
 		case "route/v1":
138
-			return fmt.Errorf("cannot expose a %s as a route", mapping.Kind)
138
+			return fmt.Errorf("cannot expose a %s as a route", mapping.GroupVersionKind.Kind)
139 139
 		case "":
140 140
 			// Default exposing everything except services as a service
141 141
 			generator = "service/v2"
... ...
@@ -38,7 +38,7 @@ type LoginOptions struct {
38 38
 	Server      string
39 39
 	CAFile      string
40 40
 	InsecureTLS bool
41
-	APIVersion  string
41
+	APIVersion  unversioned.GroupVersion
42 42
 
43 43
 	// flags and printing helpers
44 44
 	Username string
... ...
@@ -166,8 +166,8 @@ func (o *LoginOptions) getClientConfig() (*kclient.Config, error) {
166 166
 	}
167 167
 
168 168
 	// check for matching api version
169
-	if len(o.APIVersion) > 0 {
170
-		clientConfig.Version = o.APIVersion
169
+	if !o.APIVersion.IsEmpty() {
170
+		clientConfig.GroupVersion = &o.APIVersion
171 171
 	}
172 172
 
173 173
 	o.Config = clientConfig
... ...
@@ -109,7 +109,7 @@ func (o *OpenShiftLogsOptions) Complete(f *clientcmd.Factory, out io.Writer, cmd
109 109
 	}
110 110
 
111 111
 	version := cmdutil.GetFlagInt64(cmd, "version")
112
-	_, resource := meta.KindToResource(infos[0].Mapping.Kind, false)
112
+	_, resource := meta.KindToResource(infos[0].Mapping.GroupVersionKind.Kind, false)
113 113
 
114 114
 	// TODO: podLogOptions should be included in our own logOptions objects.
115 115
 	switch resource {
... ...
@@ -510,7 +510,7 @@ func retryBuildConfig(info *resource.Info, err error) runtime.Object {
510 510
 		buildapi.GenericWebHookBuildTriggerType: {},
511 511
 		buildapi.ImageChangeBuildTriggerType:    {},
512 512
 	}
513
-	if info.Mapping.Kind == "BuildConfig" && isInvalidTriggerError(err) {
513
+	if info.Mapping.GroupVersionKind.GroupKind() == buildapi.Kind("BuildConfig") && isInvalidTriggerError(err) {
514 514
 		bc, ok := info.Object.(*buildapi.BuildConfig)
515 515
 		if !ok {
516 516
 			return nil
... ...
@@ -117,8 +117,8 @@ func RunProcess(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []
117 117
 		mapping *meta.RESTMapping
118 118
 	)
119 119
 
120
-	version, kind, err := mapper.VersionAndKindForResource("template")
121
-	if mapping, err = mapper.RESTMapping(kind, version); err != nil {
120
+	gvk, err := mapper.KindFor("template")
121
+	if mapping, err = mapper.RESTMapping(gvk.GroupKind(), gvk.Version); err != nil {
122 122
 		return err
123 123
 	}
124 124
 
... ...
@@ -238,7 +238,12 @@ func RunProcess(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []
238 238
 	if err != nil {
239 239
 		return err
240 240
 	}
241
-	p = kubectl.NewVersionedPrinter(p, kapi.Scheme, kcmdutil.OutputVersion(cmd, mapping.APIVersion))
241
+	gv := mapping.GroupVersionKind.GroupVersion()
242
+	version, err := kcmdutil.OutputVersion(cmd, &gv)
243
+	if err != nil {
244
+		return err
245
+	}
246
+	p = kubectl.NewVersionedPrinter(p, kapi.Scheme, version)
242 247
 
243 248
 	// use generic output
244 249
 	if kcmdutil.GetFlagBool(cmd, "raw") {
... ...
@@ -540,7 +540,7 @@ func RunStartBuildWebHook(f *clientcmd.Factory, out io.Writer, webhook string, p
540 540
 	if hook.Scheme == "https" {
541 541
 		config, err := f.OpenShiftClientConfig.ClientConfig()
542 542
 		if err == nil {
543
-			if url, err := client.DefaultServerURL(config.Host, "", "test", true); err == nil {
543
+			if url, err := client.DefaultServerURL(config.Host, "", unversioned.GroupVersion{}, true); err == nil {
544 544
 				if url.Host == hook.Host && url.Scheme == hook.Scheme {
545 545
 					if rt, err := client.TransportFor(config); err == nil {
546 546
 						httpClient = &http.Client{Transport: rt}
... ...
@@ -104,9 +104,9 @@ func parseStreamName(defaultNamespace, name string) (string, string, error) {
104 104
 
105 105
 func determineSourceKind(f *clientcmd.Factory, input string) string {
106 106
 	mapper, _ := f.Object()
107
-	_, kind, err := mapper.VersionAndKindForResource(input)
107
+	gvk, err := mapper.KindFor(input)
108 108
 	if err == nil {
109
-		return kind
109
+		return gvk.Kind
110 110
 	}
111 111
 
112 112
 	// DockerImage isn't in RESTMapper
... ...
@@ -15,6 +15,7 @@ import (
15 15
 	apierrs "k8s.io/kubernetes/pkg/api/errors"
16 16
 	"k8s.io/kubernetes/pkg/api/meta"
17 17
 	kresource "k8s.io/kubernetes/pkg/api/resource"
18
+	"k8s.io/kubernetes/pkg/api/unversioned"
18 19
 	kclient "k8s.io/kubernetes/pkg/client/unversioned"
19 20
 	"k8s.io/kubernetes/pkg/kubectl"
20 21
 	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
... ...
@@ -111,7 +112,7 @@ type VolumeOptions struct {
111 111
 	Containers    string
112 112
 	Confirm       bool
113 113
 	Output        string
114
-	OutputVersion string
114
+	OutputVersion unversioned.GroupVersion
115 115
 
116 116
 	// Add op params
117 117
 	AddOpts *AddVolumeOptions
... ...
@@ -299,7 +300,10 @@ func (v *VolumeOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, out,
299 299
 	if err != nil {
300 300
 		return err
301 301
 	}
302
-	v.OutputVersion = kcmdutil.OutputVersion(cmd, clientConfig.Version)
302
+	v.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion)
303
+	if err != nil {
304
+		return err
305
+	}
303 306
 	_, kc, err := f.Clients()
304 307
 	if err != nil {
305 308
 		return err
... ...
@@ -370,7 +374,7 @@ func (v *VolumeOptions) RunVolume(args []string) error {
370 370
 	// if a claim should be created, generate the info we'll add to the flow
371 371
 	if v.Add && v.AddOpts.CreateClaim {
372 372
 		claim := v.AddOpts.createClaim()
373
-		m, err := v.Mapper.RESTMapping("PersistentVolumeClaim")
373
+		m, err := v.Mapper.RESTMapping(kapi.Kind("PersistentVolumeClaim"))
374 374
 		if err != nil {
375 375
 			return err
376 376
 		}
... ...
@@ -424,7 +428,7 @@ func (v *VolumeOptions) RunVolume(args []string) error {
424 424
 		return nil
425 425
 	}
426 426
 
427
-	objects, err := resource.AsVersionedObject(infos, false, v.OutputVersion)
427
+	objects, err := resource.AsVersionedObject(infos, false, v.OutputVersion.String())
428 428
 	if err != nil {
429 429
 		return err
430 430
 	}
... ...
@@ -124,7 +124,9 @@ func CreateConfig(namespace string, clientCfg *client.Config) (*clientcmdapi.Con
124 124
 		cluster.CertificateAuthorityData = clientCfg.CAData
125 125
 	}
126 126
 	cluster.InsecureSkipTLSVerify = clientCfg.Insecure
127
-	cluster.APIVersion = clientCfg.Version
127
+	if clientCfg.GroupVersion != nil {
128
+		cluster.APIVersion = clientCfg.GroupVersion.String()
129
+	}
128 130
 	config.Clusters[clusterNick] = cluster
129 131
 
130 132
 	context := clientcmdapi.NewContext()
... ...
@@ -26,35 +26,38 @@ import (
26 26
 	buildapi "github.com/openshift/origin/pkg/build/api"
27 27
 	buildutil "github.com/openshift/origin/pkg/build/util"
28 28
 	"github.com/openshift/origin/pkg/client"
29
+	deployapi "github.com/openshift/origin/pkg/deploy/api"
29 30
 	imageapi "github.com/openshift/origin/pkg/image/api"
30 31
 	projectapi "github.com/openshift/origin/pkg/project/api"
32
+	routeapi "github.com/openshift/origin/pkg/route/api"
31 33
 	templateapi "github.com/openshift/origin/pkg/template/api"
34
+	userapi "github.com/openshift/origin/pkg/user/api"
32 35
 )
33 36
 
34
-func describerMap(c *client.Client, kclient kclient.Interface, host string) map[string]kctl.Describer {
35
-	m := map[string]kctl.Describer{
36
-		"Build":                &BuildDescriber{c, kclient},
37
-		"BuildConfig":          &BuildConfigDescriber{c, host},
38
-		"DeploymentConfig":     NewDeploymentConfigDescriber(c, kclient),
39
-		"Identity":             &IdentityDescriber{c},
40
-		"Image":                &ImageDescriber{c},
41
-		"ImageStream":          &ImageStreamDescriber{c},
42
-		"ImageStreamTag":       &ImageStreamTagDescriber{c},
43
-		"ImageStreamImage":     &ImageStreamImageDescriber{c},
44
-		"Route":                &RouteDescriber{c, kclient},
45
-		"Project":              &ProjectDescriber{c, kclient},
46
-		"Template":             &TemplateDescriber{c, meta.NewAccessor(), kapi.Scheme, nil},
47
-		"Policy":               &PolicyDescriber{c},
48
-		"PolicyBinding":        &PolicyBindingDescriber{c},
49
-		"RoleBinding":          &RoleBindingDescriber{c},
50
-		"Role":                 &RoleDescriber{c},
51
-		"ClusterPolicy":        &ClusterPolicyDescriber{c},
52
-		"ClusterPolicyBinding": &ClusterPolicyBindingDescriber{c},
53
-		"ClusterRoleBinding":   &ClusterRoleBindingDescriber{c},
54
-		"ClusterRole":          &ClusterRoleDescriber{c},
55
-		"User":                 &UserDescriber{c},
56
-		"Group":                &GroupDescriber{c.Groups()},
57
-		"UserIdentityMapping":  &UserIdentityMappingDescriber{c},
37
+func describerMap(c *client.Client, kclient kclient.Interface, host string) map[unversioned.GroupKind]kctl.Describer {
38
+	m := map[unversioned.GroupKind]kctl.Describer{
39
+		buildapi.Kind("Build"):                        &BuildDescriber{c, kclient},
40
+		buildapi.Kind("BuildConfig"):                  &BuildConfigDescriber{c, host},
41
+		deployapi.Kind("DeploymentConfig"):            NewDeploymentConfigDescriber(c, kclient),
42
+		authorizationapi.Kind("Identity"):             &IdentityDescriber{c},
43
+		imageapi.Kind("Image"):                        &ImageDescriber{c},
44
+		imageapi.Kind("ImageStream"):                  &ImageStreamDescriber{c},
45
+		imageapi.Kind("ImageStreamTag"):               &ImageStreamTagDescriber{c},
46
+		imageapi.Kind("ImageStreamImage"):             &ImageStreamImageDescriber{c},
47
+		routeapi.Kind("Route"):                        &RouteDescriber{c, kclient},
48
+		projectapi.Kind("Project"):                    &ProjectDescriber{c, kclient},
49
+		templateapi.Kind("Template"):                  &TemplateDescriber{c, meta.NewAccessor(), kapi.Scheme, nil},
50
+		authorizationapi.Kind("Policy"):               &PolicyDescriber{c},
51
+		authorizationapi.Kind("PolicyBinding"):        &PolicyBindingDescriber{c},
52
+		authorizationapi.Kind("RoleBinding"):          &RoleBindingDescriber{c},
53
+		authorizationapi.Kind("Role"):                 &RoleDescriber{c},
54
+		authorizationapi.Kind("ClusterPolicy"):        &ClusterPolicyDescriber{c},
55
+		authorizationapi.Kind("ClusterPolicyBinding"): &ClusterPolicyBindingDescriber{c},
56
+		authorizationapi.Kind("ClusterRoleBinding"):   &ClusterRoleBindingDescriber{c},
57
+		authorizationapi.Kind("ClusterRole"):          &ClusterRoleDescriber{c},
58
+		userapi.Kind("User"):                          &UserDescriber{c},
59
+		userapi.Kind("Group"):                         &GroupDescriber{c.Groups()},
60
+		userapi.Kind("UserIdentityMapping"):           &UserIdentityMappingDescriber{c},
58 61
 	}
59 62
 	return m
60 63
 }
... ...
@@ -65,14 +68,14 @@ func DescribableResources() []string {
65 65
 	keys := kctl.DescribableResources()
66 66
 
67 67
 	for k := range describerMap(nil, nil, "") {
68
-		resource := strings.ToLower(k)
68
+		resource := strings.ToLower(k.Kind)
69 69
 		keys = append(keys, resource)
70 70
 	}
71 71
 	return keys
72 72
 }
73 73
 
74 74
 // DescriberFor returns a describer for a given kind of resource
75
-func DescriberFor(kind string, c *client.Client, kclient kclient.Interface, host string) (kctl.Describer, bool) {
75
+func DescriberFor(kind unversioned.GroupKind, c *client.Client, kclient kclient.Interface, host string) (kctl.Describer, bool) {
76 76
 	f, ok := describerMap(c, kclient, host)[kind]
77 77
 	if ok {
78 78
 		return f, true
... ...
@@ -807,10 +810,10 @@ func (d *TemplateDescriber) describeObjects(objects []runtime.Object, out *tabwr
807 807
 			continue
808 808
 		}
809 809
 
810
-		_, kind, _ := d.ObjectTyper.ObjectVersionAndKind(obj)
810
+		gvk, _ := d.ObjectTyper.ObjectKind(obj)
811 811
 		meta := kapi.ObjectMeta{}
812 812
 		meta.Name, _ = d.MetadataAccessor.Name(obj)
813
-		fmt.Fprintf(out, fmt.Sprintf("%s%s\t%s\n", indent, kind, meta.Name))
813
+		fmt.Fprintf(out, fmt.Sprintf("%s%s\t%s\n", indent, gvk.Kind, meta.Name))
814 814
 		//meta.Annotations, _ = d.MetadataAccessor.Annotations(obj)
815 815
 		//meta.Labels, _ = d.MetadataAccessor.Labels(obj)
816 816
 		/*if len(meta.Labels) > 0 {
... ...
@@ -1043,7 +1046,7 @@ func describePolicyRule(out *tabwriter.Writer, rule authorizationapi.PolicyRule,
1043 1043
 		extensionString = fmt.Sprintf("%#v", rule.AttributeRestrictions.Object)
1044 1044
 
1045 1045
 		buffer := new(bytes.Buffer)
1046
-		printer := NewHumanReadablePrinter(true, false, false, false, []string{})
1046
+		printer := NewHumanReadablePrinter(true, false, false, false, false, []string{})
1047 1047
 		if err := printer.PrintObj(rule.AttributeRestrictions.Object, buffer); err == nil {
1048 1048
 			extensionString = strings.TrimSpace(buffer.String())
1049 1049
 		}
... ...
@@ -12,6 +12,7 @@ import (
12 12
 	"k8s.io/kubernetes/pkg/kubectl"
13 13
 	"k8s.io/kubernetes/pkg/labels"
14 14
 
15
+	api "github.com/openshift/origin/pkg/api"
15 16
 	authorizationapi "github.com/openshift/origin/pkg/authorization/api"
16 17
 	buildapi "github.com/openshift/origin/pkg/build/api"
17 18
 	"github.com/openshift/origin/pkg/client"
... ...
@@ -75,7 +76,7 @@ func TestDescriberCoverage(t *testing.T) {
75 75
 	c := &client.Client{}
76 76
 
77 77
 main:
78
-	for _, apiType := range kapi.Scheme.KnownTypes("") {
78
+	for _, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) {
79 79
 		if !strings.Contains(apiType.PkgPath(), "openshift/origin") {
80 80
 			continue
81 81
 		}
... ...
@@ -96,7 +97,7 @@ main:
96 96
 			}
97 97
 		}
98 98
 
99
-		_, ok := DescriberFor(apiType.Name(), c, &ktestclient.Fake{}, "")
99
+		_, ok := DescriberFor(api.SchemeGroupVersion.WithKind(apiType.Name()).GroupKind(), c, &ktestclient.Fake{}, "")
100 100
 		if !ok {
101 101
 			t.Errorf("missing printer for %v.  Check pkg/cmd/cli/describe/describer.go", apiType)
102 102
 		}
... ...
@@ -10,8 +10,10 @@ import (
10 10
 
11 11
 	kapi "k8s.io/kubernetes/pkg/api"
12 12
 	"k8s.io/kubernetes/pkg/api/unversioned"
13
+	kctl "k8s.io/kubernetes/pkg/kubectl"
13 14
 	"k8s.io/kubernetes/pkg/runtime"
14 15
 
16
+	"github.com/openshift/origin/pkg/api"
15 17
 	authorizationapi "github.com/openshift/origin/pkg/authorization/api"
16 18
 	buildapi "github.com/openshift/origin/pkg/build/api"
17 19
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
... ...
@@ -57,7 +59,7 @@ func TestPrinterCoverage(t *testing.T) {
57 57
 	printer := NewHumanReadablePrinter(false, false, false, false, false, []string{})
58 58
 
59 59
 main:
60
-	for _, apiType := range kapi.Scheme.KnownTypes("") {
60
+	for _, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) {
61 61
 		if !strings.Contains(apiType.PkgPath(), "openshift/origin") {
62 62
 			continue
63 63
 		}
... ...
@@ -88,11 +90,10 @@ func TestPrintImageStream(t *testing.T) {
88 88
 	streams := mockStreams()
89 89
 
90 90
 	tests := []struct {
91
-		name          string
92
-		stream        *imageapi.ImageStream
93
-		withNamespace bool
94
-		expectedOut   string
95
-		expectedErr   error
91
+		name        string
92
+		stream      *imageapi.ImageStream
93
+		expectedOut string
94
+		expectedErr error
96 95
 	}{
97 96
 		{
98 97
 			name:        "less than three tags",
... ...
@@ -78,7 +78,7 @@ func NewCommandDeployer(name string) *cobra.Command {
78 78
 
79 79
 // NewDeployer makes a new Deployer from a kube client.
80 80
 func NewDeployer(client kclient.Interface) *Deployer {
81
-	scaler, _ := kubectl.ScalerFor("ReplicationController", client)
81
+	scaler, _ := kubectl.ScalerFor(kapi.Kind("ReplicationController"), client)
82 82
 	return &Deployer{
83 83
 		getDeployment: func(namespace, name string) (*kapi.ReplicationController, error) {
84 84
 			return client.ReplicationControllers(namespace).Get(name)
... ...
@@ -100,7 +100,7 @@ func (o CreateBootstrapPolicyFileOptions) CreateBootstrapPolicyFile() error {
100 100
 		policyTemplate.Objects = append(policyTemplate.Objects, &openshiftRoleBindings[i])
101 101
 	}
102 102
 
103
-	versionedPolicyTemplate, err := kapi.Scheme.ConvertToVersion(policyTemplate, latest.Version)
103
+	versionedPolicyTemplate, err := kapi.Scheme.ConvertToVersion(policyTemplate, latest.Version.String())
104 104
 	if err != nil {
105 105
 		return err
106 106
 	}
... ...
@@ -431,7 +431,7 @@ func (o CreateNodeConfigOptions) MakeNodeJSON(nodeJSONFile string) error {
431 431
 	node := &kapi.Node{}
432 432
 	node.Name = o.NodeName
433 433
 
434
-	json, err := klatest.CodecForLegacyGroup().Encode(node)
434
+	json, err := klatest.GroupOrDie("").Codec.Encode(node)
435 435
 	if err != nil {
436 436
 		return err
437 437
 	}
... ...
@@ -10,6 +10,7 @@ import (
10 10
 
11 11
 	kapi "k8s.io/kubernetes/pkg/api"
12 12
 	"k8s.io/kubernetes/pkg/api/meta"
13
+	"k8s.io/kubernetes/pkg/api/unversioned"
13 14
 	"k8s.io/kubernetes/pkg/kubectl"
14 15
 	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
15 16
 	"k8s.io/kubernetes/pkg/kubectl/resource"
... ...
@@ -228,7 +229,8 @@ func OverwriteBootstrapPolicy(storage storage.Interface, policyFile, createBoots
228 228
 
229 229
 // newStorage returns an EtcdHelper for the provided storage version.
230 230
 func newStorage(client *etcdclient.Client, version, prefix string) (oshelper storage.Interface, err error) {
231
-	interfaces, err := latest.InterfacesFor(version)
231
+	// TODO: this will need more care after the rebase
232
+	interfaces, err := latest.InterfacesFor(unversioned.GroupVersion{Group: "", Version: version})
232 233
 	if err != nil {
233 234
 		return nil, err
234 235
 	}
... ...
@@ -4,8 +4,6 @@ import (
4 4
 	"k8s.io/kubernetes/pkg/api/unversioned"
5 5
 	"k8s.io/kubernetes/pkg/runtime"
6 6
 	"k8s.io/kubernetes/pkg/util/sets"
7
-
8
-	"github.com/openshift/origin/pkg/api/latest"
9 7
 )
10 8
 
11 9
 // A new entry shall be added to FeatureAliases for every change to following values.
... ...
@@ -29,10 +27,10 @@ var (
29 29
 	KnownKubernetesStorageVersionLevels = []string{"v1", "v1beta3"}
30 30
 	// KnownOpenShiftStorageVersionLevels are storage versions that can be dealt
31 31
 	// with internally
32
-	KnownOpenShiftStorageVersionLevels = latest.Versions
32
+	KnownOpenShiftStorageVersionLevels = []string{"v1", "v1beta3"}
33 33
 	// DefaultOpenShiftStorageVersionLevel is the default storage version for
34 34
 	// resources.
35
-	DefaultOpenShiftStorageVersionLevel = latest.Versions[0]
35
+	DefaultOpenShiftStorageVersionLevel = "v1"
36 36
 	// DeadKubernetesStorageVersionLevels are storage versions which shouldn't
37 37
 	// be exposed externally.
38 38
 	DeadKubernetesStorageVersionLevels = []string{"v1beta3"}
... ...
@@ -354,8 +354,8 @@ type AdmissionPluginTestConfig struct {
354 354
 func (*AdmissionPluginTestConfig) IsAnAPIObject() {}
355 355
 
356 356
 func TestMasterConfig(t *testing.T) {
357
-	internal.Scheme.AddKnownTypes("v1", &AdmissionPluginTestConfig{})
358
-	internal.Scheme.AddKnownTypes("", &AdmissionPluginTestConfig{})
357
+	internal.Scheme.AddKnownTypes(SchemeGroupVersion, &AdmissionPluginTestConfig{})
358
+	internal.Scheme.AddKnownTypes(internal.SchemeGroupVersion, &AdmissionPluginTestConfig{})
359 359
 	config := &internal.MasterConfig{
360 360
 		ServingInfo: internal.HTTPServingInfo{
361 361
 			ServingInfo: internal.ServingInfo{
... ...
@@ -7,6 +7,7 @@ import (
7 7
 
8 8
 	"github.com/pborman/uuid"
9 9
 
10
+	"k8s.io/kubernetes/pkg/api/unversioned"
10 11
 	"k8s.io/kubernetes/pkg/storage"
11 12
 
12 13
 	"github.com/openshift/origin/pkg/auth/server/session"
... ...
@@ -44,7 +45,8 @@ func BuildAuthConfig(options configapi.MasterConfig) (*AuthConfig, error) {
44 44
 	if err != nil {
45 45
 		return nil, err
46 46
 	}
47
-	etcdHelper, err := NewEtcdStorage(client, options.EtcdStorageConfig.OpenShiftStorageVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix)
47
+	groupVersion := unversioned.GroupVersion{Group: "", Version: options.EtcdStorageConfig.OpenShiftStorageVersion}
48
+	etcdHelper, err := NewEtcdStorage(client, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix)
48 49
 	if err != nil {
49 50
 		return nil, fmt.Errorf("Error setting up server storage: %v", err)
50 51
 	}
... ...
@@ -58,7 +60,7 @@ func BuildAuthConfig(options configapi.MasterConfig) (*AuthConfig, error) {
58 58
 		if err != nil {
59 59
 			return nil, err
60 60
 		}
61
-		backendEtcdHelper, err := NewEtcdStorage(backendClient, options.EtcdStorageConfig.OpenShiftStorageVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix)
61
+		backendEtcdHelper, err := NewEtcdStorage(backendClient, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix)
62 62
 		if err != nil {
63 63
 			return nil, fmt.Errorf("Error setting up server storage: %v", err)
64 64
 		}
... ...
@@ -95,13 +95,13 @@ func (c *MasterConfig) authorizationFilter(handler http.Handler) http.Handler {
95 95
 func forbidden(reason string, attributes authorizer.AuthorizationAttributes, w http.ResponseWriter, req *http.Request) {
96 96
 	kind := ""
97 97
 	name := ""
98
-	apiVersion := klatest.DefaultVersionForLegacyGroup()
98
+	apiVersion := klatest.ExternalVersions[0]
99 99
 	// the attributes can be empty for two basic reasons:
100 100
 	// 1. malformed API request
101 101
 	// 2. not an API request at all
102 102
 	// In these cases, just assume default that will work better than nothing
103 103
 	if attributes != nil {
104
-		apiVersion = attributes.GetAPIVersion()
104
+		apiVersion = unversioned.GroupVersion{Group: attributes.GetAPIGroup(), Version: attributes.GetAPIVersion()}
105 105
 		kind = attributes.GetResource()
106 106
 		if len(attributes.GetAPIGroup()) > 0 {
107 107
 			kind = attributes.GetAPIGroup() + "." + kind
... ...
@@ -118,9 +118,11 @@ func forbidden(reason string, attributes authorizer.AuthorizationAttributes, w h
118 118
 
119 119
 	// Not all API versions in valid API requests will have a matching codec in kubernetes.  If we can't find one,
120 120
 	// just default to the latest kube codec.
121
-	codec := klatest.CodecForLegacyGroup()
122
-	if requestedCodec, err := klatest.InterfacesForLegacyGroup(apiVersion); err == nil {
123
-		codec = requestedCodec
121
+	codec := klatest.GroupOrDie(kapi.SchemeGroupVersion.Group).Codec
122
+	if requestedGroup, err := klatest.Group(apiVersion.Group); err == nil {
123
+		if requestedCodec, err := requestedGroup.InterfacesFor(apiVersion); err == nil {
124
+			codec = requestedCodec
125
+		}
124 126
 	}
125 127
 
126 128
 	formatted := &bytes.Buffer{}
... ...
@@ -16,6 +16,8 @@ import (
16 16
 
17 17
 	kapi "k8s.io/kubernetes/pkg/api"
18 18
 	"k8s.io/kubernetes/pkg/api/rest"
19
+	"k8s.io/kubernetes/pkg/api/unversioned"
20
+	v1beta1extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
19 21
 	"k8s.io/kubernetes/pkg/apiserver"
20 22
 	kclient "k8s.io/kubernetes/pkg/client/unversioned"
21 23
 	kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
... ...
@@ -579,9 +581,9 @@ func (c *MasterConfig) defaultAPIGroupVersion() *apiserver.APIGroupVersion {
579 579
 		Convertor: kapi.Scheme,
580 580
 		Linker:    latest.SelfLinker,
581 581
 
582
-		Admit:                   c.AdmissionControl,
583
-		Context:                 c.getRequestContextMapper(),
584
-		NonDefaultGroupVersions: map[string]string{},
582
+		Admit:                       c.AdmissionControl,
583
+		Context:                     c.getRequestContextMapper(),
584
+		NonDefaultGroupVersionKinds: map[string]unversioned.GroupVersionKind{},
585 585
 	}
586 586
 }
587 587
 
... ...
@@ -597,9 +599,9 @@ func (c *MasterConfig) api_v1beta3(all map[string]rest.Storage) *apiserver.APIGr
597 597
 	version := c.defaultAPIGroupVersion()
598 598
 	version.Root = LegacyOpenShiftAPIPrefix
599 599
 	version.Storage = storage
600
-	version.Version = OpenShiftAPIV1Beta3
600
+	version.GroupVersion = v1beta3.SchemeGroupVersion
601 601
 	version.Codec = v1beta3.Codec
602
-	version.NonDefaultGroupVersions["deploymentconfigs/scale"] = "extensions/v1beta1"
602
+	version.NonDefaultGroupVersionKinds["deploymentconfigs/scale"] = v1beta1extensions.SchemeGroupVersion.WithKind("Scale")
603 603
 	return version
604 604
 }
605 605
 
... ...
@@ -614,9 +616,9 @@ func (c *MasterConfig) api_v1(all map[string]rest.Storage) *apiserver.APIGroupVe
614 614
 	}
615 615
 	version := c.defaultAPIGroupVersion()
616 616
 	version.Storage = storage
617
-	version.Version = OpenShiftAPIV1
617
+	version.GroupVersion = v1.SchemeGroupVersion
618 618
 	version.Codec = v1.Codec
619
-	version.NonDefaultGroupVersions["deploymentconfigs/scale"] = "extensions/v1beta1"
619
+	version.NonDefaultGroupVersionKinds["deploymentconfigs/scale"] = v1beta1extensions.SchemeGroupVersion.WithKind("Scale")
620 620
 	return version
621 621
 }
622 622
 
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"k8s.io/kubernetes/pkg/admission"
14 14
 	kapi "k8s.io/kubernetes/pkg/api"
15 15
 	kapilatest "k8s.io/kubernetes/pkg/api/latest"
16
+	"k8s.io/kubernetes/pkg/api/unversioned"
16 17
 	"k8s.io/kubernetes/pkg/apiserver"
17 18
 	kclient "k8s.io/kubernetes/pkg/client/unversioned"
18 19
 	"k8s.io/kubernetes/pkg/controller/serviceaccount"
... ...
@@ -131,7 +132,8 @@ func BuildMasterConfig(options configapi.MasterConfig) (*MasterConfig, error) {
131 131
 	if err != nil {
132 132
 		return nil, err
133 133
 	}
134
-	etcdHelper, err := NewEtcdStorage(client, options.EtcdStorageConfig.OpenShiftStorageVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix)
134
+	groupVersion := unversioned.GroupVersion{Group: "", Version: options.EtcdStorageConfig.OpenShiftStorageVersion}
135
+	etcdHelper, err := NewEtcdStorage(client, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix)
135 136
 	if err != nil {
136 137
 		return nil, fmt.Errorf("Error setting up server storage: %v", err)
137 138
 	}
... ...
@@ -273,10 +275,15 @@ func newServiceAccountTokenGetter(options configapi.MasterConfig, client *etcdcl
273 273
 		tokenGetter = serviceaccount.NewGetterFromClient(kubeClient)
274 274
 	} else {
275 275
 		// When we're running in-process, go straight to etcd (using the KubernetesStorageVersion/KubernetesStoragePrefix, since service accounts are kubernetes objects)
276
-		ketcdHelper, err := master.NewEtcdStorage(client, kapilatest.InterfacesForLegacyGroup, options.EtcdStorageConfig.KubernetesStorageVersion, options.EtcdStorageConfig.KubernetesStoragePrefix)
276
+		legacyGroup, err := kapilatest.Group(kapi.SchemeGroupVersion.Group)
277 277
 		if err != nil {
278 278
 			return nil, fmt.Errorf("Error setting up Kubernetes server storage: %v", err)
279 279
 		}
280
+		versionedInterface, err := legacyGroup.InterfacesFor(unversioned.GroupVersion{Group: kapi.SchemeGroupVersion.Group, Version: options.EtcdStorageConfig.KubernetesStorageVersion})
281
+		if err != nil {
282
+			return nil, fmt.Errorf("Error setting up Kubernetes server storage: %v", err)
283
+		}
284
+		ketcdHelper := etcdstorage.NewEtcdStorage(client, versionedInterface.Codec, options.EtcdStorageConfig.KubernetesStoragePrefix)
280 285
 		tokenGetter = serviceaccount.NewGetterFromStorageInterface(ketcdHelper)
281 286
 	}
282 287
 	return tokenGetter, nil
... ...
@@ -545,7 +552,7 @@ func (c *MasterConfig) OriginNamespaceControllerClients() (*osclient.Client, *kc
545 545
 }
546 546
 
547 547
 // NewEtcdHelper returns an EtcdHelper for the provided storage version.
548
-func NewEtcdStorage(client *etcdclient.Client, version, prefix string) (oshelper storage.Interface, err error) {
548
+func NewEtcdStorage(client *etcdclient.Client, version unversioned.GroupVersion, prefix string) (oshelper storage.Interface, err error) {
549 549
 	interfaces, err := latest.InterfacesFor(version)
550 550
 	if err != nil {
551 551
 		return nil, err
... ...
@@ -10,6 +10,7 @@ import (
10 10
 
11 11
 	"k8s.io/kubernetes/pkg/admission"
12 12
 	kapi "k8s.io/kubernetes/pkg/api"
13
+	"k8s.io/kubernetes/pkg/api/unversioned"
13 14
 	"k8s.io/kubernetes/pkg/controller/serviceaccount"
14 15
 	"k8s.io/kubernetes/pkg/registry/service/allocator"
15 16
 	etcdallocator "k8s.io/kubernetes/pkg/registry/service/allocator/etcd"
... ...
@@ -188,7 +189,8 @@ func (c *MasterConfig) RunBuildController() {
188 188
 	stiImage := c.ImageFor("sti-builder")
189 189
 
190 190
 	storageVersion := c.Options.EtcdStorageConfig.OpenShiftStorageVersion
191
-	interfaces, err := latest.InterfacesFor(storageVersion)
191
+	groupVersion := unversioned.GroupVersion{Group: "", Version: storageVersion}
192
+	interfaces, err := latest.InterfacesFor(groupVersion)
192 193
 	if err != nil {
193 194
 		glog.Fatalf("Unable to load storage version %s: %v", storageVersion, err)
194 195
 	}
... ...
@@ -25,6 +25,7 @@ import (
25 25
 	"k8s.io/kubernetes/pkg/runtime"
26 26
 
27 27
 	"github.com/openshift/origin/pkg/api/latest"
28
+	authorizationapi "github.com/openshift/origin/pkg/authorization/api"
28 29
 	authorizationreaper "github.com/openshift/origin/pkg/authorization/reaper"
29 30
 	buildapi "github.com/openshift/origin/pkg/build/api"
30 31
 	buildreaper "github.com/openshift/origin/pkg/build/reaper"
... ...
@@ -37,6 +38,7 @@ import (
37 37
 	deployscaler "github.com/openshift/origin/pkg/deploy/scaler"
38 38
 	deployutil "github.com/openshift/origin/pkg/deploy/util"
39 39
 	routegen "github.com/openshift/origin/pkg/route/generator"
40
+	userapi "github.com/openshift/origin/pkg/user/api"
40 41
 	authenticationreaper "github.com/openshift/origin/pkg/user/reaper"
41 42
 )
42 43
 
... ...
@@ -146,16 +148,21 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
146 146
 	w.Object = func() (meta.RESTMapper, runtime.ObjectTyper) {
147 147
 		// Output using whatever version was negotiated in the client cache. The
148 148
 		// version we decode with may not be the same as what the server requires.
149
-		if cfg, err := clients.ClientConfigForVersion(""); err == nil {
150
-			return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersion: cfg.Version}, api.Scheme
149
+		if cfg, err := clients.ClientConfigForVersion(nil); err == nil {
150
+			cmdApiVersion := unversioned.GroupVersion{}
151
+			if cfg.GroupVersion != nil {
152
+				cmdApiVersion = *cfg.GroupVersion
153
+			}
154
+			return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}, api.Scheme
151 155
 		}
152 156
 		return mapper, api.Scheme
153 157
 	}
154 158
 
155 159
 	kRESTClient := w.Factory.RESTClient
156 160
 	w.RESTClient = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
157
-		if latest.OriginKind(mapping.Kind, mapping.APIVersion) {
158
-			client, err := clients.ClientForVersion(mapping.APIVersion)
161
+		if latest.OriginKind(mapping.GroupVersionKind) {
162
+			mappingVersion := mapping.GroupVersionKind.GroupVersion()
163
+			client, err := clients.ClientForVersion(&mappingVersion)
159 164
 			if err != nil {
160 165
 				return nil, err
161 166
 			}
... ...
@@ -167,20 +174,21 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
167 167
 	// Save original Describer function
168 168
 	kDescriberFunc := w.Factory.Describer
169 169
 	w.Describer = func(mapping *meta.RESTMapping) (kubectl.Describer, error) {
170
-		if latest.OriginKind(mapping.Kind, mapping.APIVersion) {
170
+		if latest.OriginKind(mapping.GroupVersionKind) {
171 171
 			oClient, kClient, err := w.Clients()
172 172
 			if err != nil {
173
-				return nil, fmt.Errorf("unable to create client %s: %v", mapping.Kind, err)
173
+				return nil, fmt.Errorf("unable to create client %s: %v", mapping.GroupVersionKind.Kind, err)
174 174
 			}
175 175
 
176
-			cfg, err := clients.ClientConfigForVersion(mapping.APIVersion)
176
+			mappingVersion := mapping.GroupVersionKind.GroupVersion()
177
+			cfg, err := clients.ClientConfigForVersion(&mappingVersion)
177 178
 			if err != nil {
178
-				return nil, fmt.Errorf("unable to load a client %s: %v", mapping.Kind, err)
179
+				return nil, fmt.Errorf("unable to load a client %s: %v", mapping.GroupVersionKind.Kind, err)
179 180
 			}
180 181
 
181
-			describer, ok := describe.DescriberFor(mapping.Kind, oClient, kClient, cfg.Host)
182
+			describer, ok := describe.DescriberFor(mapping.GroupVersionKind.GroupKind(), oClient, kClient, cfg.Host)
182 183
 			if !ok {
183
-				return nil, fmt.Errorf("no description has been implemented for %q", mapping.Kind)
184
+				return nil, fmt.Errorf("no description has been implemented for %q", mapping.GroupVersionKind.Kind)
184 185
 			}
185 186
 			return describer, nil
186 187
 		}
... ...
@@ -193,7 +201,7 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
193 193
 			return nil, err
194 194
 		}
195 195
 
196
-		if mapping.Kind == "DeploymentConfig" {
196
+		if mapping.GroupVersionKind.GroupKind() == deployapi.Kind("DeploymentConfig") {
197 197
 			return deployscaler.NewDeploymentConfigScaler(oc, kc), nil
198 198
 		}
199 199
 		return kScalerFunc(mapping)
... ...
@@ -205,14 +213,14 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
205 205
 			return nil, err
206 206
 		}
207 207
 
208
-		switch mapping.Kind {
209
-		case "DeploymentConfig":
208
+		switch mapping.GroupVersionKind.GroupKind() {
209
+		case deployapi.Kind("DeploymentConfig"):
210 210
 			return deployreaper.NewDeploymentConfigReaper(oc, kc), nil
211
-		case "Role":
211
+		case authorizationapi.Kind("Role"):
212 212
 			return authorizationreaper.NewRoleReaper(oc, oc), nil
213
-		case "ClusterRole":
213
+		case authorizationapi.Kind("ClusterRole"):
214 214
 			return authorizationreaper.NewClusterRoleReaper(oc, oc, oc), nil
215
-		case "User":
215
+		case userapi.Kind("User"):
216 216
 			return authenticationreaper.NewUserReaper(
217 217
 				client.UsersInterface(oc),
218 218
 				client.GroupsInterface(oc),
... ...
@@ -220,14 +228,14 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
220 220
 				client.RoleBindingsNamespacer(oc),
221 221
 				kclient.SecurityContextConstraintsInterface(kc),
222 222
 			), nil
223
-		case "Group":
223
+		case userapi.Kind("Group"):
224 224
 			return authenticationreaper.NewGroupReaper(
225 225
 				client.GroupsInterface(oc),
226 226
 				client.ClusterRoleBindingsInterface(oc),
227 227
 				client.RoleBindingsNamespacer(oc),
228 228
 				kclient.SecurityContextConstraintsInterface(kc),
229 229
 			), nil
230
-		case "BuildConfig":
230
+		case buildapi.Kind("BuildConfig"):
231 231
 			return buildreaper.NewBuildConfigReaper(oc), nil
232 232
 		}
233 233
 		return kReaperFunc(mapping)
... ...
@@ -305,12 +313,12 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory {
305 305
 			return kLogsForObjectFunc(object, options)
306 306
 		}
307 307
 	}
308
-	w.Printer = func(mapping *meta.RESTMapping, noHeaders, withNamespace, wide bool, showAll bool, columnLabels []string) (kubectl.ResourcePrinter, error) {
309
-		return describe.NewHumanReadablePrinter(noHeaders, withNamespace, wide, showAll, columnLabels), nil
308
+	w.Printer = func(mapping *meta.RESTMapping, noHeaders, withNamespace, wide bool, showAll bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error) {
309
+		return describe.NewHumanReadablePrinter(noHeaders, withNamespace, wide, showAll, absoluteTimestamps, columnLabels), nil
310 310
 	}
311 311
 	kCanBeExposed := w.Factory.CanBeExposed
312
-	w.CanBeExposed = func(kind string) error {
313
-		if kind == "DeploymentConfig" {
312
+	w.CanBeExposed = func(kind unversioned.GroupKind) error {
313
+		if kind == deployapi.Kind("DeploymentConfig") {
314 314
 			return nil
315 315
 		}
316 316
 		return kCanBeExposed(kind)
... ...
@@ -404,7 +412,7 @@ func (f *Factory) Clients() (*client.Client, *kclient.Client, error) {
404 404
 	if err != nil {
405 405
 		return nil, nil, err
406 406
 	}
407
-	osClient, err := f.clients.ClientForVersion("")
407
+	osClient, err := f.clients.ClientForVersion(nil)
408 408
 	if err != nil {
409 409
 		return nil, nil, err
410 410
 	}
... ...
@@ -416,11 +424,11 @@ type ShortcutExpander struct {
416 416
 	meta.RESTMapper
417 417
 }
418 418
 
419
-// VersionAndKindForResource implements meta.RESTMapper. It expands the resource first, then invokes the wrapped
419
+// KindFor implements meta.RESTMapper. It expands the resource first, then invokes the wrapped
420 420
 // mapper.
421
-func (e ShortcutExpander) VersionAndKindForResource(resource string) (defaultVersion, kind string, err error) {
421
+func (e ShortcutExpander) KindFor(resource string) (unversioned.GroupVersionKind, error) {
422 422
 	resource = expandResourceShortcut(resource)
423
-	return e.RESTMapper.VersionAndKindForResource(resource)
423
+	return e.RESTMapper.KindFor(resource)
424 424
 }
425 425
 
426 426
 // AliasesForResource returns whether a resource has an alias or not
... ...
@@ -474,7 +482,7 @@ type clientCache struct {
474 474
 }
475 475
 
476 476
 // ClientConfigForVersion returns the correct config for a server
477
-func (c *clientCache) ClientConfigForVersion(version string) (*kclient.Config, error) {
477
+func (c *clientCache) ClientConfigForVersion(version *unversioned.GroupVersion) (*kclient.Config, error) {
478 478
 	if c.defaultConfig == nil {
479 479
 		config, err := c.loader.ClientConfig()
480 480
 		if err != nil {
... ...
@@ -483,7 +491,11 @@ func (c *clientCache) ClientConfigForVersion(version string) (*kclient.Config, e
483 483
 		c.defaultConfig = config
484 484
 	}
485 485
 	// TODO: have a better config copy method
486
-	if config, ok := c.configs[version]; ok {
486
+	cacheKey := ""
487
+	if version != nil {
488
+		cacheKey = version.String()
489
+	}
490
+	if config, ok := c.configs[cacheKey]; ok {
487 491
 		return config, nil
488 492
 	}
489 493
 	if c.negotiatingClient == nil {
... ...
@@ -510,22 +522,26 @@ func (c *clientCache) ClientConfigForVersion(version string) (*kclient.Config, e
510 510
 	if err != nil {
511 511
 		return nil, err
512 512
 	}
513
-	config.Version = negotiatedVersion
513
+	config.GroupVersion = negotiatedVersion
514 514
 	client.SetOpenShiftDefaults(&config)
515
-	c.configs[version] = &config
515
+	c.configs[cacheKey] = &config
516 516
 
517 517
 	// `version` does not necessarily equal `config.Version`.  However, we know that we call this method again with
518 518
 	// `config.Version`, we should get the the config we've just built.
519 519
 	configCopy := config
520
-	c.configs[config.Version] = &configCopy
520
+	c.configs[config.GroupVersion.String()] = &configCopy
521 521
 
522 522
 	return &config, nil
523 523
 }
524 524
 
525 525
 // ClientForVersion initializes or reuses a client for the specified version, or returns an
526 526
 // error if that is not possible
527
-func (c *clientCache) ClientForVersion(version string) (*client.Client, error) {
528
-	if client, ok := c.clients[version]; ok {
527
+func (c *clientCache) ClientForVersion(version *unversioned.GroupVersion) (*client.Client, error) {
528
+	cacheKey := ""
529
+	if version != nil {
530
+		cacheKey = version.String()
531
+	}
532
+	if client, ok := c.clients[cacheKey]; ok {
529 533
 		return client, nil
530 534
 	}
531 535
 	config, err := c.ClientConfigForVersion(version)
... ...
@@ -537,6 +553,6 @@ func (c *clientCache) ClientForVersion(version string) (*client.Client, error) {
537 537
 		return nil, err
538 538
 	}
539 539
 
540
-	c.clients[config.Version] = client
540
+	c.clients[config.GroupVersion.String()] = client
541 541
 	return client, nil
542 542
 }
... ...
@@ -7,6 +7,8 @@ import (
7 7
 
8 8
 	kclient "k8s.io/kubernetes/pkg/client/unversioned"
9 9
 
10
+	"github.com/openshift/origin/pkg/api/v1"
11
+	"github.com/openshift/origin/pkg/api/v1beta3"
10 12
 	"github.com/openshift/origin/pkg/client"
11 13
 )
12 14
 
... ...
@@ -14,7 +16,8 @@ func TestClientConfigForVersion(t *testing.T) {
14 14
 	called := 0
15 15
 	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
16 16
 		if req.URL.Path != "/oapi" {
17
-			t.Fatalf("Unexpected path called during negotiation: %s", req.URL.Path)
17
+			t.Errorf("Unexpected path called during negotiation: %s", req.URL.Path)
18
+			return
18 19
 		}
19 20
 		called++
20 21
 		w.Write([]byte(`{"versions":["v1"]}`))
... ...
@@ -32,12 +35,12 @@ func TestClientConfigForVersion(t *testing.T) {
32 32
 
33 33
 	// First call, negotiate
34 34
 	called = 0
35
-	v1Config, err := clients.ClientConfigForVersion("")
35
+	v1Config, err := clients.ClientConfigForVersion(nil)
36 36
 	if err != nil {
37 37
 		t.Fatalf("Unexpected error: %v", err)
38 38
 	}
39
-	if v1Config.Version != "v1" {
40
-		t.Fatalf("Expected v1, got %v", v1Config.Version)
39
+	if v1Config.GroupVersion.String() != "v1" {
40
+		t.Fatalf("Expected v1, got %v", v1Config.GroupVersion.String())
41 41
 	}
42 42
 	if called != 1 {
43 43
 		t.Fatalf("Expected to be called 1 time during negotiation, was called %d times", called)
... ...
@@ -45,12 +48,12 @@ func TestClientConfigForVersion(t *testing.T) {
45 45
 
46 46
 	// Second call, cache
47 47
 	called = 0
48
-	v1Config, err = clients.ClientConfigForVersion("")
48
+	v1Config, err = clients.ClientConfigForVersion(nil)
49 49
 	if err != nil {
50 50
 		t.Fatalf("Unexpected error: %v", err)
51 51
 	}
52
-	if v1Config.Version != "v1" {
53
-		t.Fatalf("Expected v1, got %v", v1Config.Version)
52
+	if v1Config.GroupVersion.String() != "v1" {
53
+		t.Fatalf("Expected v1, got %v", v1Config.GroupVersion.String())
54 54
 	}
55 55
 	if called != 0 {
56 56
 		t.Fatalf("Expected not be called again getting a config from cache, was called %d additional times", called)
... ...
@@ -58,12 +61,12 @@ func TestClientConfigForVersion(t *testing.T) {
58 58
 
59 59
 	// Third call, cached under exactly matching version
60 60
 	called = 0
61
-	v1Config, err = clients.ClientConfigForVersion("v1")
61
+	v1Config, err = clients.ClientConfigForVersion(&v1.SchemeGroupVersion)
62 62
 	if err != nil {
63 63
 		t.Fatalf("Unexpected error: %v", err)
64 64
 	}
65
-	if v1Config.Version != "v1" {
66
-		t.Fatalf("Expected v1, got %v", v1Config.Version)
65
+	if v1Config.GroupVersion.String() != "v1" {
66
+		t.Fatalf("Expected v1, got %v", v1Config.GroupVersion.String())
67 67
 	}
68 68
 	if called != 0 {
69 69
 		t.Fatalf("Expected not be called again getting a config from cache, was called %d additional times", called)
... ...
@@ -71,12 +74,12 @@ func TestClientConfigForVersion(t *testing.T) {
71 71
 
72 72
 	// Call for unsupported version, negotiate to supported version
73 73
 	called = 0
74
-	v1beta3Config, err := clients.ClientConfigForVersion("v1beta3")
74
+	v1beta3Config, err := clients.ClientConfigForVersion(&v1beta3.SchemeGroupVersion)
75 75
 	if err != nil {
76 76
 		t.Fatalf("Unexpected error: %v", err)
77 77
 	}
78
-	if v1beta3Config.Version != "v1" {
79
-		t.Fatalf("Expected to negotiate v1 for v1beta3 config, got %v", v1beta3Config.Version)
78
+	if v1beta3Config.GroupVersion.String() != "v1" {
79
+		t.Fatalf("Expected to negotiate v1 for v1beta3 config, got %v", v1beta3Config.GroupVersion.String())
80 80
 	}
81 81
 	if called != 1 {
82 82
 		t.Fatalf("Expected to be called once getting a config for a new version, was called %d times", called)
... ...
@@ -47,12 +47,12 @@ func ResolveResource(defaultResource, resourceString string, mapper meta.RESTMap
47 47
 	case 1:
48 48
 		name = parts[0]
49 49
 	case 2:
50
-		_, kind, err := mapper.VersionAndKindForResource(parts[0])
50
+		gvk, err := mapper.KindFor(parts[0])
51 51
 		if err != nil {
52 52
 			return "", "", err
53 53
 		}
54 54
 		name = parts[1]
55
-		resource, _ := meta.KindToResource(kind, false)
55
+		resource, _ := meta.KindToResource(gvk.Kind, false)
56 56
 		return resource, name, nil
57 57
 	default:
58 58
 		return "", "", fmt.Errorf("invalid resource format: %s", resourceString)
... ...
@@ -7,6 +7,8 @@ import (
7 7
 	"k8s.io/kubernetes/pkg/api/unversioned"
8 8
 	"k8s.io/kubernetes/pkg/runtime"
9 9
 
10
+	oapi "github.com/openshift/origin/pkg/api"
11
+	"github.com/openshift/origin/pkg/api/v1"
10 12
 	"github.com/openshift/origin/pkg/cmd/server/api"
11 13
 	"github.com/openshift/origin/pkg/cmd/server/api/latest"
12 14
 )
... ...
@@ -20,8 +22,8 @@ type TestConfig struct {
20 20
 func (*TestConfig) IsAnAPIObject() {}
21 21
 
22 22
 func TestGetPluginConfig(t *testing.T) {
23
-	api.Scheme.AddKnownTypes("", &TestConfig{})
24
-	api.Scheme.AddKnownTypes("v1", &TestConfig{})
23
+	api.Scheme.AddKnownTypes(oapi.SchemeGroupVersion, &TestConfig{})
24
+	api.Scheme.AddKnownTypes(v1.SchemeGroupVersion, &TestConfig{})
25 25
 
26 26
 	testConfig := &TestConfig{
27 27
 		Item1: "item1value",
... ...
@@ -44,7 +44,7 @@ type RecreateDeploymentStrategy struct {
44 44
 // NewRecreateDeploymentStrategy makes a RecreateDeploymentStrategy backed by
45 45
 // a real HookExecutor and client.
46 46
 func NewRecreateDeploymentStrategy(client kclient.Interface, codec runtime.Codec) *RecreateDeploymentStrategy {
47
-	scaler, _ := kubectl.ScalerFor("ReplicationController", client)
47
+	scaler, _ := kubectl.ScalerFor(kapi.Kind("ReplicationController"), client)
48 48
 	return &RecreateDeploymentStrategy{
49 49
 		getReplicationController: func(namespace, name string) (*kapi.ReplicationController, error) {
50 50
 			return client.ReplicationControllers(namespace).Get(name)
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"k8s.io/kubernetes/pkg/util/intstr"
14 14
 	kuval "k8s.io/kubernetes/pkg/util/validation"
15 15
 
16
+	build "github.com/openshift/origin/pkg/build/api"
16 17
 	deploy "github.com/openshift/origin/pkg/deploy/api"
17 18
 	image "github.com/openshift/origin/pkg/image/api"
18 19
 	route "github.com/openshift/origin/pkg/route/api"
... ...
@@ -428,11 +429,11 @@ func (a *acceptUnique) Accept(from interface{}) bool {
428 428
 	if err != nil {
429 429
 		return false
430 430
 	}
431
-	_, kind, err := a.typer.ObjectVersionAndKind(obj)
431
+	gvk, err := a.typer.ObjectKind(obj)
432 432
 	if err != nil {
433 433
 		return false
434 434
 	}
435
-	key := fmt.Sprintf("%s/%s/%s", kind, meta.Namespace, meta.Name)
435
+	key := fmt.Sprintf("%s/%s/%s", gvk.Kind, meta.Namespace, meta.Name)
436 436
 	_, exists := a.objects[key]
437 437
 	if exists {
438 438
 		return false
... ...
@@ -472,11 +473,11 @@ func (a *acceptBuildConfigs) Accept(from interface{}) bool {
472 472
 	if err != nil {
473 473
 		return false
474 474
 	}
475
-	_, kind, err := a.typer.ObjectVersionAndKind(obj)
475
+	gvk, err := a.typer.ObjectKind(obj)
476 476
 	if err != nil {
477 477
 		return false
478 478
 	}
479
-	return kind == "BuildConfig" || kind == "ImageStream"
479
+	return gvk.GroupKind() == build.Kind("BuildConfig") || gvk.GroupKind() == image.Kind("ImageStream")
480 480
 }
481 481
 
482 482
 // NewAcceptBuildConfigs creates an acceptor accepting BuildConfig objects
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"sort"
5 5
 
6 6
 	kapi "k8s.io/kubernetes/pkg/api"
7
+	"k8s.io/kubernetes/pkg/api/unversioned"
7 8
 	v1 "k8s.io/kubernetes/pkg/api/v1"
8 9
 	"k8s.io/kubernetes/pkg/conversion"
9 10
 
... ...
@@ -59,7 +60,7 @@ func convert_v1_Image_To_api_Image(in *Image, out *newer.Image, s conversion.Sco
59 59
 	}
60 60
 	if len(in.DockerImageMetadata.RawJSON) > 0 {
61 61
 		// TODO: add a way to default the expected kind and version of an object if not set
62
-		obj, err := kapi.Scheme.New(version, "DockerImage")
62
+		obj, err := kapi.Scheme.New(unversioned.GroupVersionKind{Version: version, Kind: "DockerImage"})
63 63
 		if err != nil {
64 64
 			return err
65 65
 		}
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"sort"
6 6
 
7 7
 	kapi "k8s.io/kubernetes/pkg/api"
8
+	"k8s.io/kubernetes/pkg/api/unversioned"
8 9
 	"k8s.io/kubernetes/pkg/conversion"
9 10
 
10 11
 	newer "github.com/openshift/origin/pkg/image/api"
... ...
@@ -47,7 +48,7 @@ func convert_v1beta3_Image_To_api_Image(in *Image, out *newer.Image, s conversio
47 47
 	}
48 48
 	if len(in.DockerImageMetadata.RawJSON) > 0 {
49 49
 		// TODO: add a way to default the expected kind and version of an object if not set
50
-		obj, err := kapi.Scheme.New(version, "DockerImage")
50
+		obj, err := kapi.Scheme.New(unversioned.GroupVersionKind{Version: version, Kind: "DockerImage"})
51 51
 		if err != nil {
52 52
 			return err
53 53
 		}
... ...
@@ -32,6 +32,7 @@ import (
32 32
 	client "k8s.io/kubernetes/pkg/client/unversioned"
33 33
 	"k8s.io/kubernetes/pkg/util/sets"
34 34
 
35
+	"github.com/openshift/origin/pkg/api"
35 36
 	"github.com/openshift/origin/pkg/api/latest"
36 37
 	oadmission "github.com/openshift/origin/pkg/cmd/server/admission"
37 38
 	"github.com/openshift/origin/pkg/project/cache"
... ...
@@ -69,15 +70,13 @@ func (e *lifecycle) Admit(a admission.Attributes) (err error) {
69 69
 	if isSubjectAccessReview(a) {
70 70
 		return nil
71 71
 	}
72
-	defaultVersion, kind, err := latest.RESTMapper.VersionAndKindForResource(a.GetResource())
72
+	fmt.Println(a.GetKind())
73
+	mapping, err := latest.RESTMapper.RESTMapping(a.GetKind())
73 74
 	if err != nil {
74 75
 		glog.V(4).Infof("Ignoring life-cycle enforcement for resource %v; no associated default version and kind could be found.", a.GetResource())
75 76
 		return nil
76 77
 	}
77
-	mapping, err := latest.RESTMapper.RESTMapping(kind, defaultVersion)
78
-	if err != nil {
79
-		return admission.NewForbidden(a, err)
80
-	}
78
+	fmt.Println(mapping)
81 79
 	if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
82 80
 		return nil
83 81
 	}
... ...
@@ -106,8 +105,8 @@ func (e *lifecycle) Admit(a admission.Attributes) (err error) {
106 106
 		return nil
107 107
 	}
108 108
 
109
-	if namespace.Status.Phase == kapi.NamespaceTerminating && !e.creatableResources.Has(strings.ToLower(a.GetResource())) {
110
-		return apierrors.NewForbidden(kind, name, fmt.Errorf("Namespace %s is terminating", a.GetNamespace()))
109
+	if namespace.Status.Phase == kapi.NamespaceTerminating && !e.creatableResources.Has(strings.ToLower(a.GetResource().Resource)) {
110
+		return apierrors.NewForbidden(a.GetKind().Kind, name, fmt.Errorf("Namespace %s is terminating", a.GetNamespace()))
111 111
 	}
112 112
 
113 113
 	// in case of concurrency issues, we will retry this logic
... ...
@@ -160,7 +159,11 @@ func NewLifecycle(client client.Interface, creatableResources sets.String) (admi
160 160
 	}, nil
161 161
 }
162 162
 
163
+var (
164
+	sar  = api.Kind("SubjectAccessReview")
165
+	lsar = api.Kind("LocalSubjectAccessReview")
166
+)
167
+
163 168
 func isSubjectAccessReview(a admission.Attributes) bool {
164
-	return a.GetResource() == "subjectaccessreviews" ||
165
-		a.GetResource() == "localsubjectaccessreviews"
169
+	return a.GetKind() == sar || a.GetKind() == lsar
166 170
 }
... ...
@@ -28,7 +28,7 @@ func TestIgnoreThatWhichCannotBeKnown(t *testing.T) {
28 28
 	handler := &lifecycle{}
29 29
 	unknown := &UnknownObject{}
30 30
 
31
-	err := handler.Admit(admission.NewAttributesRecord(unknown, "kind", "namespace", "name", "resource", "subresource", "CREATE", nil))
31
+	err := handler.Admit(admission.NewAttributesRecord(unknown, kapi.Kind("kind"), "namespace", "name", kapi.Resource("resource"), "subresource", "CREATE", nil))
32 32
 	if err != nil {
33 33
 		t.Errorf("Admission control should not error if it finds an object it knows nothing about %v", err)
34 34
 	}
... ...
@@ -67,7 +67,7 @@ func TestAdmissionExists(t *testing.T) {
67 67
 			Phase: buildapi.BuildPhaseNew,
68 68
 		},
69 69
 	}
70
-	err := handler.Admit(admission.NewAttributesRecord(build, "Build", "namespace", "name", "builds", "", "CREATE", nil))
70
+	err := handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), "namespace", "name", kapi.Resource("builds"), "", "CREATE", nil))
71 71
 	if err == nil {
72 72
 		t.Errorf("Expected an error because namespace does not exist")
73 73
 	}
... ...
@@ -113,7 +113,7 @@ func TestAdmissionLifecycle(t *testing.T) {
113 113
 			Phase: buildapi.BuildPhaseNew,
114 114
 		},
115 115
 	}
116
-	err := handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "name", "builds", "", "CREATE", nil))
116
+	err := handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "CREATE", nil))
117 117
 	if err != nil {
118 118
 		t.Errorf("Unexpected error returned from admission handler: %v", err)
119 119
 	}
... ...
@@ -123,19 +123,19 @@ func TestAdmissionLifecycle(t *testing.T) {
123 123
 	store.Add(namespaceObj)
124 124
 
125 125
 	// verify create operations in the namespace cause an error
126
-	err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "name", "builds", "", "CREATE", nil))
126
+	err = handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "CREATE", nil))
127 127
 	if err == nil {
128 128
 		t.Errorf("Expected error rejecting creates in a namespace when it is terminating")
129 129
 	}
130 130
 
131 131
 	// verify update operations in the namespace can proceed
132
-	err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "name", "builds", "", "UPDATE", nil))
132
+	err = handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "UPDATE", nil))
133 133
 	if err != nil {
134 134
 		t.Errorf("Unexpected error returned from admission handler: %v", err)
135 135
 	}
136 136
 
137 137
 	// verify delete operations in the namespace can proceed
138
-	err = handler.Admit(admission.NewAttributesRecord(nil, "Build", build.Namespace, "name", "builds", "", "DELETE", nil))
138
+	err = handler.Admit(admission.NewAttributesRecord(nil, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "DELETE", nil))
139 139
 	if err != nil {
140 140
 		t.Errorf("Unexpected error returned from admission handler: %v", err)
141 141
 	}
... ...
@@ -187,7 +187,7 @@ func TestSAR(t *testing.T) {
187 187
 	}
188 188
 
189 189
 	for k, v := range tests {
190
-		err := handler.Admit(admission.NewAttributesRecord(nil, v.kind, "foo", "name", v.resource, "", "CREATE", nil))
190
+		err := handler.Admit(admission.NewAttributesRecord(nil, kapi.Kind(v.kind), "foo", "name", kapi.Resource(v.resource), "", "CREATE", nil))
191 191
 		if err != nil {
192 192
 			t.Errorf("Unexpected error for %s returned from admission handler: %v", k, err)
193 193
 		}
... ...
@@ -33,7 +33,7 @@ var _ = oadmission.Validator(&podNodeEnvironment{})
33 33
 // Admit enforces that pod and its project node label selectors matches at least a node in the cluster.
34 34
 func (p *podNodeEnvironment) Admit(a admission.Attributes) (err error) {
35 35
 	resource := a.GetResource()
36
-	if resource != "pods" {
36
+	if resource != kapi.Resource("pods") {
37 37
 		return nil
38 38
 	}
39 39
 	if a.GetSubresource() != "" {
... ...
@@ -54,7 +54,7 @@ func (p *podNodeEnvironment) Admit(a admission.Attributes) (err error) {
54 54
 	}
55 55
 	namespace, err := p.cache.GetNamespace(a.GetNamespace())
56 56
 	if err != nil {
57
-		return apierrors.NewForbidden(resource, name, err)
57
+		return apierrors.NewForbidden(resource.Resource, name, err)
58 58
 	}
59 59
 	projectNodeSelector, err := p.cache.GetNodeSelectorMap(namespace)
60 60
 	if err != nil {
... ...
@@ -62,7 +62,7 @@ func (p *podNodeEnvironment) Admit(a admission.Attributes) (err error) {
62 62
 	}
63 63
 
64 64
 	if labelselector.Conflicts(projectNodeSelector, pod.Spec.NodeSelector) {
65
-		return apierrors.NewForbidden(resource, name, fmt.Errorf("pod node label selector conflicts with its project node label selector"))
65
+		return apierrors.NewForbidden(resource.Resource, name, fmt.Errorf("pod node label selector conflicts with its project node label selector"))
66 66
 	}
67 67
 
68 68
 	// modify pod node selector = project node selector + current pod node selector
... ...
@@ -111,7 +111,7 @@ func TestPodAdmission(t *testing.T) {
111 111
 		}
112 112
 		pod.Spec = kapi.PodSpec{NodeSelector: test.podNodeSelector}
113 113
 
114
-		err := handler.Admit(admission.NewAttributesRecord(pod, "Pod", "namespace", project.ObjectMeta.Name, "pods", "", admission.Create, nil))
114
+		err := handler.Admit(admission.NewAttributesRecord(pod, kapi.Kind("Pod"), "namespace", project.ObjectMeta.Name, kapi.Resource("pods"), "", admission.Create, nil))
115 115
 		if test.admit && err != nil {
116 116
 			t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
117 117
 		} else if !test.admit && err == nil {
... ...
@@ -129,7 +129,7 @@ func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err
129 129
 		Mapper: latest.RESTMapper,
130 130
 		Typer:  kapi.Scheme,
131 131
 		RESTClientFactory: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
132
-			if latest.OriginKind(mapping.Kind, mapping.APIVersion) {
132
+			if latest.OriginKind(mapping.GroupVersionKind) {
133 133
 				return r.openshiftClient, nil
134 134
 			}
135 135
 			return r.kubeClient, nil
... ...
@@ -95,7 +95,7 @@ func (a *constraint) Stop() {
95 95
 //     with the validated SCC.  If we don't find any reject the pod and give all errors from the
96 96
 //     failed attempts.
97 97
 func (c *constraint) Admit(a kadmission.Attributes) error {
98
-	if a.GetResource() != string(kapi.ResourcePods) {
98
+	if a.GetResource().Resource != string(kapi.ResourcePods) {
99 99
 		return nil
100 100
 	}
101 101
 
... ...
@@ -14,9 +14,10 @@ import (
14 14
 	kscc "k8s.io/kubernetes/pkg/securitycontextconstraints"
15 15
 	"k8s.io/kubernetes/pkg/util"
16 16
 
17
+	"sort"
18
+
17 19
 	allocator "github.com/openshift/origin/pkg/security"
18 20
 	"github.com/openshift/origin/pkg/security/uid"
19
-	"sort"
20 21
 )
21 22
 
22 23
 func NewTestAdmission(store cache.Store, kclient client.Interface) kadmission.Interface {
... ...
@@ -132,7 +133,7 @@ func testSCCAdmit(testCaseName string, sccs []*kapi.SecurityContextConstraints,
132 132
 
133 133
 	plugin := NewTestAdmission(store, tc)
134 134
 
135
-	attrs := kadmission.NewAttributesRecord(pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{})
135
+	attrs := kadmission.NewAttributesRecord(pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{})
136 136
 	err := plugin.Admit(attrs)
137 137
 
138 138
 	if shouldPass && err != nil {
... ...
@@ -373,7 +374,7 @@ func TestAdmit(t *testing.T) {
373 373
 	}
374 374
 
375 375
 	for k, v := range testCases {
376
-		attrs := kadmission.NewAttributesRecord(v.pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{})
376
+		attrs := kadmission.NewAttributesRecord(v.pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{})
377 377
 		err := p.Admit(attrs)
378 378
 
379 379
 		if v.shouldAdmit && err != nil {
... ...
@@ -447,7 +448,7 @@ func TestAdmit(t *testing.T) {
447 447
 
448 448
 	for k, v := range testCases {
449 449
 		if !v.shouldAdmit {
450
-			attrs := kadmission.NewAttributesRecord(v.pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{})
450
+			attrs := kadmission.NewAttributesRecord(v.pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{})
451 451
 			err := p.Admit(attrs)
452 452
 			if err != nil {
453 453
 				t.Errorf("Expected %s to pass with escalated scc but got error %v", k, err)
... ...
@@ -553,7 +554,7 @@ func TestAssignSecurityContext(t *testing.T) {
553 553
 	}
554 554
 
555 555
 	for k, v := range testCases {
556
-		errs := assignSecurityContext(provider, v.pod)
556
+		errs := assignSecurityContext(provider, v.pod, nil)
557 557
 		if v.shouldValidate && len(errs) > 0 {
558 558
 			t.Errorf("%s expected to validate but received errors %v", k, errs)
559 559
 			continue
... ...
@@ -822,7 +823,7 @@ func TestCreateProvidersFromConstraints(t *testing.T) {
822 822
 		scc := v.scc()
823 823
 
824 824
 		// create the providers, this method only needs the namespace
825
-		attributes := kadmission.NewAttributesRecord(nil, "", v.namespace.Name, "", "", "", kadmission.Create, nil)
825
+		attributes := kadmission.NewAttributesRecord(nil, kapi.Kind("Pod"), v.namespace.Name, "", kapi.Resource("pods"), "", kadmission.Create, nil)
826 826
 		_, errs := admit.createProvidersFromConstraints(attributes.GetNamespace(), []*kapi.SecurityContextConstraints{scc})
827 827
 
828 828
 		if !reflect.DeepEqual(scc, v.scc()) {
... ...
@@ -1464,7 +1465,7 @@ func TestAdmitWithPrioritizedSCC(t *testing.T) {
1464 1464
 // testSCCAdmission is a helper to admit the pod and ensure it was validated against the expected
1465 1465
 // SCC.
1466 1466
 func testSCCAdmission(pod *kapi.Pod, plugin kadmission.Interface, expectedSCC string, t *testing.T) {
1467
-	attrs := kadmission.NewAttributesRecord(pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{})
1467
+	attrs := kadmission.NewAttributesRecord(pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{})
1468 1468
 	err := plugin.Admit(attrs)
1469 1469
 	if err != nil {
1470 1470
 		t.Errorf("error admitting pod: %v", err)
... ...
@@ -20,6 +20,7 @@ import (
20 20
 	"io"
21 21
 
22 22
 	"k8s.io/kubernetes/pkg/admission"
23
+	kapi "k8s.io/kubernetes/pkg/api"
23 24
 	client "k8s.io/kubernetes/pkg/client/unversioned"
24 25
 )
25 26
 
... ...
@@ -43,7 +44,7 @@ func (d *sccExecRestrictions) Admit(a admission.Attributes) (err error) {
43 43
 	if a.GetOperation() != admission.Connect {
44 44
 		return nil
45 45
 	}
46
-	if a.GetResource() != "pods" {
46
+	if a.GetResource() != kapi.Resource("pods") {
47 47
 		return nil
48 48
 	}
49 49
 	if a.GetSubresource() != "attach" && a.GetSubresource() != "exec" {
... ...
@@ -58,7 +59,7 @@ func (d *sccExecRestrictions) Admit(a admission.Attributes) (err error) {
58 58
 	// create a synthentic admission attribute to check SCC admission status for this pod
59 59
 	// clear the SA name, so that any permissions MUST be based on your user's power, not the SAs power.
60 60
 	pod.Spec.ServiceAccountName = ""
61
-	createAttributes := admission.NewAttributesRecord(pod, "pods", a.GetNamespace(), a.GetName(), a.GetResource(), a.GetSubresource(), admission.Create, a.GetUserInfo())
61
+	createAttributes := admission.NewAttributesRecord(pod, kapi.Kind("Pod"), a.GetNamespace(), a.GetName(), a.GetResource(), a.GetSubresource(), admission.Create, a.GetUserInfo())
62 62
 	if err := d.constraintAdmission.Admit(createAttributes); err != nil {
63 63
 		return admission.NewForbidden(a, err)
64 64
 	}
... ...
@@ -89,7 +89,7 @@ func TestExecAdmit(t *testing.T) {
89 89
 		// create the admission plugin
90 90
 		p := NewSCCExecRestrictions(tc)
91 91
 
92
-		attrs := kadmission.NewAttributesRecord(v.pod, "Pod", "namespace", "pod-name", v.resource, v.subresource, v.operation, &user.DefaultInfo{})
92
+		attrs := kadmission.NewAttributesRecord(v.pod, kapi.Kind("Pod"), "namespace", "pod-name", kapi.Resource(v.resource), v.subresource, v.operation, &user.DefaultInfo{})
93 93
 		err := p.Admit(attrs)
94 94
 
95 95
 		if v.shouldAdmit && err != nil {
... ...
@@ -17,7 +17,7 @@ func TestNewRESTInvalidType(t *testing.T) {
17 17
 		t.Errorf("Expected type error.")
18 18
 	}
19 19
 
20
-	if _, _, err := latest.RESTMapper.VersionAndKindForResource("processedtemplates"); err != nil {
20
+	if _, err := latest.RESTMapper.KindFor("processedtemplates"); err != nil {
21 21
 		t.Errorf("no processed templates: %v", err)
22 22
 	}
23 23
 }
... ...
@@ -17,6 +17,8 @@ import (
17 17
 	"k8s.io/kubernetes/pkg/runtime"
18 18
 	kyaml "k8s.io/kubernetes/pkg/util/yaml"
19 19
 
20
+	"github.com/openshift/origin/pkg/api"
21
+	"github.com/openshift/origin/pkg/api/v1"
20 22
 	buildapi "github.com/openshift/origin/pkg/build/api"
21 23
 	"github.com/openshift/origin/pkg/client"
22 24
 	configapi "github.com/openshift/origin/pkg/cmd/server/api"
... ...
@@ -159,8 +161,8 @@ func checkAdmissionObjectLabelValues(labels, expected map[string]string) error {
159 159
 }
160 160
 
161 161
 func registerAdmissionPluginTestConfigType() {
162
-	configapi.Scheme.AddKnownTypes("", &TestPluginConfig{})
163
-	configapi.Scheme.AddKnownTypes("v1", &TestPluginConfig{})
162
+	configapi.Scheme.AddKnownTypes(api.SchemeGroupVersion, &TestPluginConfig{})
163
+	configapi.Scheme.AddKnownTypes(v1.SchemeGroupVersion, &TestPluginConfig{})
164 164
 }
165 165
 
166 166
 func setupAdmissionPluginTestConfig(t *testing.T, value string) string {
... ...
@@ -5,6 +5,7 @@ package integration
5 5
 import (
6 6
 	"testing"
7 7
 
8
+	"k8s.io/kubernetes/pkg/api/unversioned"
8 9
 	"k8s.io/kubernetes/pkg/api/v1"
9 10
 	"k8s.io/kubernetes/pkg/runtime"
10 11
 
... ...
@@ -22,12 +23,12 @@ func TestTemplate(t *testing.T) {
22 22
 	if err != nil {
23 23
 		t.Fatalf("unexpected error: %v", err)
24 24
 	}
25
-	for _, version := range []string{"v1"} {
25
+	for _, version := range []unversioned.GroupVersion{v1.SchemeGroupVersion} {
26 26
 		config, err := testutil.GetClusterAdminClientConfig(path)
27 27
 		if err != nil {
28 28
 			t.Fatalf("unexpected error: %v", err)
29 29
 		}
30
-		config.Version = version
30
+		config.GroupVersion = &version
31 31
 		config.Prefix = ""
32 32
 		c, err := client.New(config)
33 33
 		if err != nil {
... ...
@@ -53,7 +53,7 @@ func TestTemplateTransformationFromConfig(t *testing.T) {
53 53
 	server := httptest.NewServer(osMux)
54 54
 	defer server.Close()
55 55
 
56
-	osClient := osclient.NewOrDie(&kclient.Config{Host: server.URL, Version: latest.Version})
56
+	osClient := osclient.NewOrDie(&kclient.Config{Host: server.URL, GroupVersion: &latest.Version})
57 57
 
58 58
 	storage := map[string]rest.Storage{
59 59
 		"processedTemplates": templateregistry.NewREST(),
... ...
@@ -66,8 +66,8 @@ func TestTemplateTransformationFromConfig(t *testing.T) {
66 66
 	interfaces, _ := latest.InterfacesFor(latest.Version)
67 67
 	handlerContainer := master.NewHandlerContainer(osMux)
68 68
 	version := apiserver.APIGroupVersion{
69
-		Root:    "/oapi",
70
-		Version: latest.Version,
69
+		Root:         "/oapi",
70
+		GroupVersion: latest.Version,
71 71
 
72 72
 		Mapper: latest.RESTMapper,
73 73
 
... ...
@@ -5,9 +5,9 @@ import (
5 5
 	"io/ioutil"
6 6
 
7 7
 	kapi "k8s.io/kubernetes/pkg/api"
8
-	"k8s.io/kubernetes/pkg/api/latest"
9 8
 	kyaml "k8s.io/kubernetes/pkg/util/yaml"
10 9
 
10
+	oapi "github.com/openshift/origin/pkg/api"
11 11
 	buildapi "github.com/openshift/origin/pkg/build/api"
12 12
 	imageapi "github.com/openshift/origin/pkg/image/api"
13 13
 	templateapi "github.com/openshift/origin/pkg/template/api"
... ...
@@ -21,7 +21,7 @@ func CreateSampleImageStream(namespace string) *imageapi.ImageStream {
21 21
 		fmt.Printf("ERROR: Unable to read: %v", err)
22 22
 		return nil
23 23
 	}
24
-	latest.CodecForLegacyGroup().DecodeInto(jsonData, &stream)
24
+	oapi.Codec.DecodeInto(jsonData, &stream)
25 25
 
26 26
 	client, _ := GetClusterAdminClient(KubeConfigPath())
27 27
 	result, err := client.ImageStreams(namespace).Create(&stream)
... ...
@@ -47,7 +47,7 @@ func GetBuildFixture(filename string) *buildapi.Build {
47 47
 		fmt.Printf("ERROR: Unable to read %s: %v", filename, err)
48 48
 		return nil
49 49
 	}
50
-	latest.CodecForLegacyGroup().DecodeInto(jsonData, &build)
50
+	oapi.Codec.DecodeInto(jsonData, &build)
51 51
 	return &build
52 52
 }
53 53
 
... ...
@@ -58,7 +58,7 @@ func GetSecretFixture(filename string) *kapi.Secret {
58 58
 		fmt.Printf("ERROR: Unable to read %s: %v", filename, err)
59 59
 		return nil
60 60
 	}
61
-	latest.CodecForLegacyGroup().DecodeInto(jsonData, &secret)
61
+	kapi.Codec.DecodeInto(jsonData, &secret)
62 62
 	return &secret
63 63
 }
64 64
 
... ...
@@ -71,7 +71,7 @@ func GetTemplateFixture(filename string) (*templateapi.Template, error) {
71 71
 	if err != nil {
72 72
 		return nil, err
73 73
 	}
74
-	obj, err := latest.CodecForLegacyGroup().Decode(jsonData)
74
+	obj, err := oapi.Codec.Decode(jsonData)
75 75
 	if err != nil {
76 76
 		return nil, err
77 77
 	}
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"strings"
9 9
 
10 10
 	"k8s.io/kubernetes/pkg/api"
11
+	"k8s.io/kubernetes/pkg/api/unversioned"
11 12
 	pkg_runtime "k8s.io/kubernetes/pkg/runtime"
12 13
 	"k8s.io/kubernetes/pkg/util/sets"
13 14
 
... ...
@@ -21,6 +22,7 @@ import (
21 21
 
22 22
 var (
23 23
 	functionDest = flag.StringP("funcDest", "f", "-", "Output for conversion functions; '-' means stdout")
24
+	group        = flag.StringP("group", "g", "", "Group for conversion.")
24 25
 	version      = flag.StringP("version", "v", "v1beta3", "Version for conversion.")
25 26
 )
26 27
 
... ...
@@ -46,11 +48,12 @@ func main() {
46 46
 	generator.AssumePrivateConversions()
47 47
 	// TODO(wojtek-t): Change the overwrites to a flag.
48 48
 	generator.OverwritePackage(*version, "")
49
-	for _, knownType := range api.Scheme.KnownTypes(*version) {
49
+	gv := unversioned.GroupVersion{Group: *group, Version: *version}
50
+	for _, knownType := range api.Scheme.KnownTypes(gv) {
50 51
 		if !strings.Contains(knownType.PkgPath(), "openshift/origin") {
51 52
 			continue
52 53
 		}
53
-		if err := generator.GenerateConversionsForType(*version, knownType); err != nil {
54
+		if err := generator.GenerateConversionsForType(gv, knownType); err != nil {
54 55
 			glog.Errorf("error while generating conversion functions for %v: %v", knownType, err)
55 56
 		}
56 57
 	}
... ...
@@ -24,6 +24,7 @@ import (
24 24
 	"strings"
25 25
 
26 26
 	"k8s.io/kubernetes/pkg/api"
27
+	"k8s.io/kubernetes/pkg/api/unversioned"
27 28
 	pkg_runtime "k8s.io/kubernetes/pkg/runtime"
28 29
 	"k8s.io/kubernetes/pkg/util/sets"
29 30
 
... ...
@@ -37,6 +38,7 @@ import (
37 37
 
38 38
 var (
39 39
 	functionDest = flag.StringP("func-dest", "f", "-", "Output for deep copy functions; '-' means stdout")
40
+	group        = flag.StringP("group", "g", "", "Group for deep copies.")
40 41
 	version      = flag.StringP("version", "v", "v1beta3", "Version for deep copies.")
41 42
 	overwrites   = flag.StringP("overwrites", "o", "", "Comma-separated overwrites for package names")
42 43
 )
... ...
@@ -57,9 +59,9 @@ func main() {
57 57
 		funcOut = file
58 58
 	}
59 59
 
60
-	knownVersion := *version
61
-	if knownVersion == "api" {
62
-		knownVersion = api.Scheme.Raw().InternalVersion
60
+	knownGroupVersion := unversioned.GroupVersion{Group: *group, Version: *version}
61
+	if knownGroupVersion.Version == "api" {
62
+		knownGroupVersion = api.Scheme.Raw().InternalVersions[knownGroupVersion.Group]
63 63
 	}
64 64
 	generator := pkg_runtime.NewDeepCopyGenerator(api.Scheme.Raw(), "github.com/openshift/origin/pkg/api", sets.NewString("github.com/openshift/origin"))
65 65
 	apiShort := generator.AddImport("k8s.io/kubernetes/pkg/api")
... ...
@@ -69,7 +71,7 @@ func main() {
69 69
 		vals := strings.Split(overwrite, "=")
70 70
 		generator.OverwritePackage(vals[0], vals[1])
71 71
 	}
72
-	for _, knownType := range api.Scheme.KnownTypes(knownVersion) {
72
+	for _, knownType := range api.Scheme.KnownTypes(knownGroupVersion) {
73 73
 		if !strings.Contains(knownType.PkgPath(), "openshift/origin") {
74 74
 			continue
75 75
 		}