Browse code

Rebase code onto latest

* Register types with api.Scheme and declare IsAnAPIObject()
* Update REST method signatures
* Handle Client version and Codec changes

Clayton Coleman authored on 2014/09/23 10:24:21
Showing 44 changed files
... ...
@@ -1,3 +1,6 @@
1 1
 // Package api includes all OpenShift-specific types used to communicate
2 2
 // between the various parts of the OpenShift and the Kubernetes systems.
3
+//
4
+// Unlike the upstream Kubernetes, API objects in OpenShift are separated
5
+// into individual packages.
3 6
 package api
4 7
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+// Package latest defines the default output serializations that code should
1
+// use and imports the required schemas.  It also ensures all previously known
2
+// and supported API versions are available for conversion. Consumers may
3
+// import this package in lieu of importing individual versions.
4
+package latest
0 5
new file mode 100644
... ...
@@ -0,0 +1,46 @@
0
+package latest
1
+
2
+import (
3
+	"fmt"
4
+	"strings"
5
+
6
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
7
+
8
+	"github.com/openshift/origin/pkg/api/v1beta1"
9
+)
10
+
11
+// Version is the string that represents the current external default version.
12
+const Version = "v1beta1"
13
+
14
+// OldestVersion is the string that represents the oldest server version supported,
15
+// for client code that wants to hardcode the lowest common denominator.
16
+const OldestVersion = "v1beta1"
17
+
18
+// Versions is the list of versions that are recognized in code. The order provided
19
+// may be assumed to be least feature rich to most feature rich, and clients may
20
+// choose to prefer the latter items in the list over the former items when presented
21
+// with a set of versions to choose.
22
+var Versions = []string{"v1beta1"}
23
+
24
+// Codec is the default codec for serializing output that should use
25
+// the latest supported version.  Use this Codec when writing to
26
+// disk, a data store that is not dynamically versioned, or in tests.
27
+// This codec can decode any object that OpenShift is aware of.
28
+var Codec = v1beta1.Codec
29
+
30
+// ResourceVersioner describes a default versioner that can handle all types
31
+// of versioning.
32
+// TODO: when versioning changes, make this part of each API definition.
33
+var ResourceVersioner = runtime.NewJSONBaseResourceVersioner()
34
+
35
+// InterfacesFor returns the default Codec and ResourceVersioner for a given version
36
+// string, or an error if the version is not known.
37
+func InterfacesFor(version string) (codec runtime.Codec, versioner runtime.ResourceVersioner, err error) {
38
+	switch version {
39
+	case "v1beta1":
40
+		codec, versioner = v1beta1.Codec, ResourceVersioner
41
+	default:
42
+		err = fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(Versions, ", "))
43
+	}
44
+	return
45
+}
... ...
@@ -1,9 +1,20 @@
1 1
 package api
2 2
 
3 3
 import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
4 5
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
6
+
7
+	_ "github.com/openshift/origin/pkg/build/api"
8
+	_ "github.com/openshift/origin/pkg/config/api"
9
+	_ "github.com/openshift/origin/pkg/deploy/api"
10
+	_ "github.com/openshift/origin/pkg/image/api"
11
+	_ "github.com/openshift/origin/pkg/template/api"
5 12
 )
6 13
 
14
+// Codec is the identity codec for this package - it can only convert itself
15
+// to itself.
16
+var Codec = runtime.CodecFor(api.Scheme, "")
17
+
7 18
 func init() {
8
-	runtime.AddKnownTypes("")
19
+	api.Scheme.AddKnownTypes("")
9 20
 }
... ...
@@ -1,9 +1,19 @@
1 1
 package v1beta1
2 2
 
3 3
 import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
4 5
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
6
+
7
+	_ "github.com/openshift/origin/pkg/build/api/v1beta1"
8
+	_ "github.com/openshift/origin/pkg/config/api/v1beta1"
9
+	_ "github.com/openshift/origin/pkg/deploy/api/v1beta1"
10
+	_ "github.com/openshift/origin/pkg/image/api/v1beta1"
11
+	_ "github.com/openshift/origin/pkg/template/api/v1beta1"
5 12
 )
6 13
 
14
+// Codec encodes internal objects to the v1beta1 scheme
15
+var Codec = runtime.CodecFor(api.Scheme, "v1beta1")
16
+
7 17
 func init() {
8
-	runtime.AddKnownTypes("v1beta1")
18
+	api.Scheme.AddKnownTypes("v1beta1")
9 19
 }
... ...
@@ -1,14 +1,19 @@
1 1
 package api
2 2
 
3 3
 import (
4
-	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5 5
 )
6 6
 
7 7
 func init() {
8
-	runtime.AddKnownTypes("",
9
-		Build{},
10
-		BuildList{},
11
-		BuildConfig{},
12
-		BuildConfigList{},
8
+	api.Scheme.AddKnownTypes("",
9
+		&Build{},
10
+		&BuildList{},
11
+		&BuildConfig{},
12
+		&BuildConfigList{},
13 13
 	)
14 14
 }
15
+
16
+func (*Build) IsAnAPIObject()           {}
17
+func (*BuildList) IsAnAPIObject()       {}
18
+func (*BuildConfig) IsAnAPIObject()     {}
19
+func (*BuildConfigList) IsAnAPIObject() {}
... ...
@@ -1,14 +1,19 @@
1 1
 package v1beta1
2 2
 
3 3
 import (
4
-	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5 5
 )
6 6
 
7 7
 func init() {
8
-	runtime.AddKnownTypes("v1beta1",
9
-		Build{},
10
-		BuildList{},
11
-		BuildConfig{},
12
-		BuildConfigList{},
8
+	api.Scheme.AddKnownTypes("v1beta1",
9
+		&Build{},
10
+		&BuildList{},
11
+		&BuildConfig{},
12
+		&BuildConfigList{},
13 13
 	)
14 14
 }
15
+
16
+func (*Build) IsAnAPIObject()           {}
17
+func (*BuildList) IsAnAPIObject()       {}
18
+func (*BuildConfig) IsAnAPIObject()     {}
19
+func (*BuildConfigList) IsAnAPIObject() {}
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	kubeclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
11 11
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
12
+
12 13
 	"github.com/golang/glog"
13 14
 	"github.com/openshift/origin/pkg/build/api"
14 15
 	osclient "github.com/openshift/origin/pkg/client"
... ...
@@ -113,7 +114,7 @@ func (bc *BuildController) synchronize(build *api.Build) (api.BuildStatus, error
113 113
 		}
114 114
 
115 115
 		glog.Infof("Attempting to create pod: %#v", podSpec)
116
-		_, err = bc.kubeClient.CreatePod(*podSpec)
116
+		_, err = bc.kubeClient.CreatePod(podSpec)
117 117
 
118 118
 		// TODO: strongly typed error checking
119 119
 		if err != nil {
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
11 11
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
12 12
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
13
+
13 14
 	"github.com/openshift/origin/pkg/build/api"
14 15
 	"github.com/openshift/origin/pkg/build/api/validation"
15 16
 )
... ...
@@ -25,12 +26,12 @@ func NewREST(registry Registry) apiserver.RESTStorage {
25 25
 }
26 26
 
27 27
 // New creates a new Build object
28
-func (r *REST) New() interface{} {
28
+func (r *REST) New() runtime.Object {
29 29
 	return &api.Build{}
30 30
 }
31 31
 
32 32
 // List obtains a list of Builds that match selector.
33
-func (r *REST) List(selector labels.Selector) (interface{}, error) {
33
+func (r *REST) List(selector, fields labels.Selector) (runtime.Object, error) {
34 34
 	builds, err := r.registry.ListBuilds(selector)
35 35
 	if err != nil {
36 36
 		return nil, err
... ...
@@ -40,7 +41,7 @@ func (r *REST) List(selector labels.Selector) (interface{}, error) {
40 40
 }
41 41
 
42 42
 // Get obtains the build specified by its id.
43
-func (r *REST) Get(id string) (interface{}, error) {
43
+func (r *REST) Get(id string) (runtime.Object, error) {
44 44
 	build, err := r.registry.GetBuild(id)
45 45
 	if err != nil {
46 46
 		return nil, err
... ...
@@ -49,21 +50,14 @@ func (r *REST) Get(id string) (interface{}, error) {
49 49
 }
50 50
 
51 51
 // Delete asynchronously deletes the Build specified by its id.
52
-func (r *REST) Delete(id string) (<-chan interface{}, error) {
53
-	return apiserver.MakeAsync(func() (interface{}, error) {
52
+func (r *REST) Delete(id string) (<-chan runtime.Object, error) {
53
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
54 54
 		return &kubeapi.Status{Status: kubeapi.StatusSuccess}, r.registry.DeleteBuild(id)
55 55
 	}), nil
56 56
 }
57 57
 
58
-// Extract deserializes user provided data into an api.Build.
59
-func (r *REST) Extract(body []byte) (interface{}, error) {
60
-	result := api.Build{}
61
-	err := runtime.DecodeInto(body, &result)
62
-	return result, err
63
-}
64
-
65 58
 // Create registers a given new Build instance to r.registry.
66
-func (r *REST) Create(obj interface{}) (<-chan interface{}, error) {
59
+func (r *REST) Create(obj runtime.Object) (<-chan runtime.Object, error) {
67 60
 	build, ok := obj.(*api.Build)
68 61
 	if !ok {
69 62
 		return nil, fmt.Errorf("not a build: %#v", obj)
... ...
@@ -78,7 +72,7 @@ func (r *REST) Create(obj interface{}) (<-chan interface{}, error) {
78 78
 	if errs := validation.ValidateBuild(build); len(errs) > 0 {
79 79
 		return nil, errors.NewInvalid("build", build.ID, errs)
80 80
 	}
81
-	return apiserver.MakeAsync(func() (interface{}, error) {
81
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
82 82
 		err := r.registry.CreateBuild(build)
83 83
 		if err != nil {
84 84
 			return nil, err
... ...
@@ -88,7 +82,7 @@ func (r *REST) Create(obj interface{}) (<-chan interface{}, error) {
88 88
 }
89 89
 
90 90
 // Update replaces a given Build instance with an existing instance in r.registry.
91
-func (r *REST) Update(obj interface{}) (<-chan interface{}, error) {
91
+func (r *REST) Update(obj runtime.Object) (<-chan runtime.Object, error) {
92 92
 	build, ok := obj.(*api.Build)
93 93
 	if !ok {
94 94
 		return nil, fmt.Errorf("not a build: %#v", obj)
... ...
@@ -96,7 +90,7 @@ func (r *REST) Update(obj interface{}) (<-chan interface{}, error) {
96 96
 	if errs := validation.ValidateBuild(build); len(errs) > 0 {
97 97
 		return nil, errors.NewInvalid("build", build.ID, errs)
98 98
 	}
99
-	return apiserver.MakeAsync(func() (interface{}, error) {
99
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
100 100
 		err := r.registry.UpdateBuild(build)
101 101
 		if err != nil {
102 102
 			return nil, err
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
11 11
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
12 12
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
13
+
13 14
 	"github.com/openshift/origin/pkg/build/api"
14 15
 	"github.com/openshift/origin/pkg/build/api/validation"
15 16
 )
... ...
@@ -25,12 +26,12 @@ func NewREST(registry Registry) apiserver.RESTStorage {
25 25
 }
26 26
 
27 27
 // New creates a new BuildConfig.
28
-func (r *REST) New() interface{} {
28
+func (r *REST) New() runtime.Object {
29 29
 	return &api.BuildConfig{}
30 30
 }
31 31
 
32 32
 // List obtains a list of BuildConfigs that match selector.
33
-func (r *REST) List(selector labels.Selector) (interface{}, error) {
33
+func (r *REST) List(selector, fields labels.Selector) (runtime.Object, error) {
34 34
 	builds, err := r.registry.ListBuildConfigs(selector)
35 35
 	if err != nil {
36 36
 		return nil, err
... ...
@@ -39,7 +40,7 @@ func (r *REST) List(selector labels.Selector) (interface{}, error) {
39 39
 }
40 40
 
41 41
 // Get obtains the BuildConfig specified by its id.
42
-func (r *REST) Get(id string) (interface{}, error) {
42
+func (r *REST) Get(id string) (runtime.Object, error) {
43 43
 	buildConfig, err := r.registry.GetBuildConfig(id)
44 44
 	if err != nil {
45 45
 		return nil, err
... ...
@@ -48,21 +49,14 @@ func (r *REST) Get(id string) (interface{}, error) {
48 48
 }
49 49
 
50 50
 // Delete asynchronously deletes the BuildConfig specified by its id.
51
-func (r *REST) Delete(id string) (<-chan interface{}, error) {
52
-	return apiserver.MakeAsync(func() (interface{}, error) {
51
+func (r *REST) Delete(id string) (<-chan runtime.Object, error) {
52
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
53 53
 		return &kubeapi.Status{Status: kubeapi.StatusSuccess}, r.registry.DeleteBuildConfig(id)
54 54
 	}), nil
55 55
 }
56 56
 
57
-// Extract deserializes user provided data into an api.BuildConfig.
58
-func (r *REST) Extract(body []byte) (interface{}, error) {
59
-	result := api.BuildConfig{}
60
-	err := runtime.DecodeInto(body, &result)
61
-	return result, err
62
-}
63
-
64 57
 // Create registers a given new BuildConfig instance to r.registry.
65
-func (r *REST) Create(obj interface{}) (<-chan interface{}, error) {
58
+func (r *REST) Create(obj runtime.Object) (<-chan runtime.Object, error) {
66 59
 	buildConfig, ok := obj.(*api.BuildConfig)
67 60
 	if !ok {
68 61
 		return nil, fmt.Errorf("not a buildConfig: %#v", obj)
... ...
@@ -74,7 +68,7 @@ func (r *REST) Create(obj interface{}) (<-chan interface{}, error) {
74 74
 	if errs := validation.ValidateBuildConfig(buildConfig); len(errs) > 0 {
75 75
 		return nil, errors.NewInvalid("buildConfig", buildConfig.ID, errs)
76 76
 	}
77
-	return apiserver.MakeAsync(func() (interface{}, error) {
77
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
78 78
 		err := r.registry.CreateBuildConfig(buildConfig)
79 79
 		if err != nil {
80 80
 			return nil, err
... ...
@@ -84,7 +78,7 @@ func (r *REST) Create(obj interface{}) (<-chan interface{}, error) {
84 84
 }
85 85
 
86 86
 // Update replaces a given BuildConfig instance with an existing instance in r.registry.
87
-func (r *REST) Update(obj interface{}) (<-chan interface{}, error) {
87
+func (r *REST) Update(obj runtime.Object) (<-chan runtime.Object, error) {
88 88
 	buildConfig, ok := obj.(*api.BuildConfig)
89 89
 	if !ok {
90 90
 		return nil, fmt.Errorf("not a buildConfig: %#v", obj)
... ...
@@ -92,7 +86,7 @@ func (r *REST) Update(obj interface{}) (<-chan interface{}, error) {
92 92
 	if errs := validation.ValidateBuildConfig(buildConfig); len(errs) > 0 {
93 93
 		return nil, errors.NewInvalid("buildConfig", buildConfig.ID, errs)
94 94
 	}
95
-	return apiserver.MakeAsync(func() (interface{}, error) {
95
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
96 96
 		err := r.registry.UpdateBuildConfig(buildConfig)
97 97
 		if err != nil {
98 98
 			return nil, err
... ...
@@ -3,7 +3,6 @@ package etcd
3 3
 import (
4 4
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
5 5
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
6
-	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
7 6
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
8 7
 
9 8
 	"github.com/openshift/origin/pkg/build/api"
... ...
@@ -14,17 +13,11 @@ type Etcd struct {
14 14
 	tools.EtcdHelper
15 15
 }
16 16
 
17
-// NewEtcd creates an etcd registry.
18
-// 'client' is the connection to etcd
19
-func NewEtcd(client tools.EtcdClient) *Etcd {
20
-	registry := &Etcd{
21
-		EtcdHelper: tools.EtcdHelper{
22
-			client,
23
-			runtime.Codec,
24
-			runtime.ResourceVersioner,
25
-		},
17
+// New creates an etcd registry.
18
+func New(helper tools.EtcdHelper) *Etcd {
19
+	return &Etcd{
20
+		EtcdHelper: helper,
26 21
 	}
27
-	return registry
28 22
 }
29 23
 
30 24
 func makeBuildKey(id string) string {
... ...
@@ -27,9 +27,8 @@ func (bs *DockerBuildStrategy) CreateBuildPod(build *buildapi.Build, dockerRegis
27 27
 				Version: "v1beta1",
28 28
 				Containers: []api.Container{
29 29
 					{
30
-						Name:          "docker-build",
31
-						Image:         bs.dockerBuilderImage,
32
-						RestartPolicy: "runOnce",
30
+						Name:  "docker-build",
31
+						Image: bs.dockerBuilderImage,
33 32
 						Env: []api.EnvVar{
34 33
 							{Name: "BUILD_TAG", Value: build.Input.ImageTag},
35 34
 							{Name: "DOCKER_CONTEXT_URL", Value: build.Input.SourceURI},
... ...
@@ -37,6 +36,9 @@ func (bs *DockerBuildStrategy) CreateBuildPod(build *buildapi.Build, dockerRegis
37 37
 						},
38 38
 					},
39 39
 				},
40
+				RestartPolicy: api.RestartPolicy{
41
+					Never: &api.RestartPolicyNever{},
42
+				},
40 43
 			},
41 44
 		},
42 45
 	}
... ...
@@ -43,9 +43,8 @@ func (bs *STIBuildStrategy) CreateBuildPod(build *buildapi.Build, dockerRegistry
43 43
 				Version: "v1beta1",
44 44
 				Containers: []api.Container{
45 45
 					{
46
-						Name:          "sti-build",
47
-						Image:         bs.stiBuilderImage,
48
-						RestartPolicy: "runOnce",
46
+						Name:  "sti-build",
47
+						Image: bs.stiBuilderImage,
49 48
 						Env: []api.EnvVar{
50 49
 							{Name: "BUILD_TAG", Value: build.Input.ImageTag},
51 50
 							{Name: "DOCKER_REGISTRY", Value: dockerRegistry},
... ...
@@ -55,6 +54,9 @@ func (bs *STIBuildStrategy) CreateBuildPod(build *buildapi.Build, dockerRegistry
55 55
 						},
56 56
 					},
57 57
 				},
58
+				RestartPolicy: api.RestartPolicy{
59
+					Never: &api.RestartPolicyNever{},
60
+				},
58 61
 			},
59 62
 		},
60 63
 	}
... ...
@@ -59,7 +59,7 @@ func (c *controller) ServeHTTP(w http.ResponseWriter, req *http.Request) {
59 59
 
60 60
 	plugin, ok := c.plugins[uv.plugin]
61 61
 	if !ok {
62
-		notFound(w, "Plugin ", uv.plugin, " not found!")
62
+		notFound(w, "Plugin ", uv.plugin, " not found")
63 63
 		return
64 64
 	}
65 65
 	build, proceed, err := plugin.Extract(buildCfg, uv.path, req)
... ...
@@ -84,7 +84,7 @@ func (c *controller) ServeHTTP(w http.ResponseWriter, req *http.Request) {
84 84
 func parseUrl(url string) (uv urlVars, err error) {
85 85
 	parts := splitPath(url)
86 86
 	if len(parts) < 3 {
87
-		err = fmt.Errorf("Unexpected URL %s!", url)
87
+		err = fmt.Errorf("Unexpected URL %s", url)
88 88
 		return
89 89
 	}
90 90
 	uv = urlVars{parts[0], parts[1], parts[2], ""}
... ...
@@ -26,7 +26,7 @@ func (p *GitHubWebHook) Extract(buildCfg *api.BuildConfig, path string, req *htt
26 26
 	}
27 27
 	method := req.Header.Get("X-GitHub-Event")
28 28
 	if method != "ping" && method != "push" {
29
-		err = fmt.Errorf("Unknown X-GitHub-Event %s!", method)
29
+		err = fmt.Errorf("Unknown X-GitHub-Event %s", method)
30 30
 		return
31 31
 	}
32 32
 	proceed = (method == "push")
... ...
@@ -44,16 +44,16 @@ func (p *GitHubWebHook) Extract(buildCfg *api.BuildConfig, path string, req *htt
44 44
 
45 45
 func verifyRequest(req *http.Request) error {
46 46
 	if method := req.Method; method != "POST" {
47
-		return fmt.Errorf("Unsupported HTTP method %s!", method)
47
+		return fmt.Errorf("Unsupported HTTP method %s", method)
48 48
 	}
49 49
 	if contentType := req.Header.Get("Content-Type"); contentType != "application/json" {
50
-		return fmt.Errorf("Unsupported Content-Type %s!", contentType)
50
+		return fmt.Errorf("Unsupported Content-Type %s", contentType)
51 51
 	}
52 52
 	if userAgent := req.Header.Get("User-Agent"); !strings.HasPrefix(userAgent, "GitHub-Hookshot/") {
53
-		return fmt.Errorf("Unsupported User-Agent %s!")
53
+		return fmt.Errorf("Unsupported User-Agent %s")
54 54
 	}
55 55
 	if req.Header.Get("X-GitHub-Event") == "" {
56
-		return errors.New("Missing X-GitHub-Event!")
56
+		return errors.New("Missing X-GitHub-Event")
57 57
 	}
58 58
 	return nil
59 59
 }
... ...
@@ -1,15 +1,17 @@
1 1
 package client
2 2
 
3 3
 import (
4
+	"fmt"
5
+	"strings"
6
+
4 7
 	kubeclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
5 8
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
6 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
10
+
11
+	"github.com/openshift/origin/pkg/api/latest"
7 12
 	buildapi "github.com/openshift/origin/pkg/build/api"
8
-	_ "github.com/openshift/origin/pkg/build/api/v1beta1"
9 13
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
10
-	_ "github.com/openshift/origin/pkg/deploy/api/v1beta1"
11 14
 	imageapi "github.com/openshift/origin/pkg/image/api"
12
-	_ "github.com/openshift/origin/pkg/image/api/v1beta1"
13 15
 )
14 16
 
15 17
 // Interface exposes methods on OpenShift resources.
... ...
@@ -85,10 +87,20 @@ type Client struct {
85 85
 }
86 86
 
87 87
 // New creates and returns a new Client.
88
-func New(host string, auth *kubeclient.AuthInfo) (*Client, error) {
89
-	restClient, err := kubeclient.NewRESTClient(host, auth, "/osapi/v1beta1")
88
+func New(host, version string, auth *kubeclient.AuthInfo) (*Client, error) {
89
+	if version == "" {
90
+		// Clients default to the preferred code API version
91
+		// TODO: implement version negotation (highest version supported by server)
92
+		version = latest.Version
93
+	}
94
+	serverCodec, _, err := latest.InterfacesFor(version)
95
+	if err != nil {
96
+		return nil, fmt.Errorf("API version '%s' is not recognized (valid values: %s)", version, strings.Join(latest.Versions, ", "))
97
+	}
98
+	prefix := fmt.Sprintf("/osapi/%s/", version)
99
+	restClient, err := kubeclient.NewRESTClient(host, auth, prefix, serverCodec)
90 100
 	if err != nil {
91
-		return nil, err
101
+		return nil, fmt.Errorf("API URL '%s' is not valid: %v", host, err)
92 102
 	}
93 103
 	return &Client{restClient}, nil
94 104
 }
... ...
@@ -3,6 +3,7 @@ package client
3 3
 import (
4 4
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
5 5
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
6
+
6 7
 	buildapi "github.com/openshift/origin/pkg/build/api"
7 8
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
8 9
 	imageapi "github.com/openshift/origin/pkg/image/api"
... ...
@@ -1,6 +1,9 @@
1 1
 package api
2 2
 
3
-import "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
3
+import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
5
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
6
+)
4 7
 
5 8
 type RESTClient interface {
6 9
 	Verb(verb string) *client.Request
... ...
@@ -9,4 +12,5 @@ type RESTClient interface {
9 9
 type ClientMappings map[string]struct {
10 10
 	Kind   string
11 11
 	Client RESTClient
12
+	Codec  runtime.Codec
12 13
 }
... ...
@@ -45,5 +45,10 @@ func NewCommandKubecfg(name string) *cobra.Command {
45 45
 	flag.StringVar(&cfg.WWW, "www", "", "If -proxy is true, use this directory to serve static files")
46 46
 	flag.StringVar(&cfg.TemplateFile, "template_file", "", "If present, load this file as a golang template and use it for output printing")
47 47
 	flag.StringVar(&cfg.TemplateStr, "template", "", "If present, parse this string as a golang template and use it for output printing")
48
+	flag.StringVar(&cfg.CAFile, "certificate_authority", "", "Path to a cert. file for the certificate authority")
49
+	flag.StringVar(&cfg.CertFile, "client_certificate", "", "Path to a client certificate for TLS.")
50
+	flag.StringVar(&cfg.KeyFile, "client_key", "", "Path to a client key file for TLS.")
51
+	flag.StringVar(&cfg.ImageName, "image", "", "Image used when updating a replicationController.  Will apply to the first container in the pod template.")
52
+
48 53
 	return cmd
49 54
 }
... ...
@@ -30,12 +30,15 @@ import (
30 30
 	"time"
31 31
 
32 32
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
33
+	klatest "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
33 34
 	kubeclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
34 35
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubecfg"
35 36
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
36 37
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
37 38
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
38 39
 	"github.com/golang/glog"
40
+
41
+	"github.com/openshift/origin/pkg/api/latest"
39 42
 	buildapi "github.com/openshift/origin/pkg/build/api"
40 43
 	osclient "github.com/openshift/origin/pkg/client"
41 44
 	. "github.com/openshift/origin/pkg/cmd/client/api"
... ...
@@ -43,7 +46,6 @@ import (
43 43
 	"github.com/openshift/origin/pkg/cmd/client/image"
44 44
 	"github.com/openshift/origin/pkg/config"
45 45
 	configapi "github.com/openshift/origin/pkg/config/api"
46
-	_ "github.com/openshift/origin/pkg/config/api/v1beta1"
47 46
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
48 47
 	deployclient "github.com/openshift/origin/pkg/deploy/client"
49 48
 	imageapi "github.com/openshift/origin/pkg/image/api"
... ...
@@ -68,6 +70,15 @@ type KubeConfig struct {
68 68
 	TemplateFile   string
69 69
 	TemplateStr    string
70 70
 
71
+	ImageName string
72
+
73
+	CAFile   string
74
+	CertFile string
75
+	KeyFile  string
76
+
77
+	APIVersion   string
78
+	OSAPIVersion string
79
+
71 80
 	Args []string
72 81
 }
73 82
 
... ...
@@ -84,10 +95,16 @@ func usage(name string) string {
84 84
   %[1]s [OPTIONS] get|list|create|delete|update <%[2]s>[/<id>]
85 85
 
86 86
   Manage replication controllers:
87
-  %[1]s [OPTIONS] stop|rm|rollingupdate <controller>
88
-  %[1]s [OPTIONS] run <image> <replicas> <controller>
87
+
88
+  %[1]s [OPTIONS] stop|rm <controller>
89
+  %[1]s [OPTIONS] [-u <time>] [-image <image>] rollingupdate <controller>
89 90
   %[1]s [OPTIONS] resize <controller> <replicas>
90 91
 
92
+  Launch a simple ReplicationController with a single container based
93
+  on the given image:
94
+
95
+  %[1]s [OPTIONS] [-p <port spec>] run <image> <replicas> <controller>
96
+
91 97
   Perform bulk operations on groups of Kubernetes resources:
92 98
   %[1]s [OPTIONS] apply -c config.json
93 99
 
... ...
@@ -96,19 +113,19 @@ func usage(name string) string {
96 96
 `, name, prettyWireStorage())
97 97
 }
98 98
 
99
-var parser = kubecfg.NewParser(map[string]interface{}{
100
-	"pods":                    api.Pod{},
101
-	"services":                api.Service{},
102
-	"replicationControllers":  api.ReplicationController{},
103
-	"minions":                 api.Minion{},
104
-	"builds":                  buildapi.Build{},
105
-	"buildConfigs":            buildapi.BuildConfig{},
106
-	"images":                  imageapi.Image{},
107
-	"imageRepositories":       imageapi.ImageRepository{},
108
-	"imageRepositoryMappings": imageapi.ImageRepositoryMapping{},
109
-	"config":                  configapi.Config{},
110
-	"deployments":             deployapi.Deployment{},
111
-	"deploymentConfigs":       deployapi.DeploymentConfig{},
99
+var parser = kubecfg.NewParser(map[string]runtime.Object{
100
+	"pods":                    &api.Pod{},
101
+	"services":                &api.Service{},
102
+	"replicationControllers":  &api.ReplicationController{},
103
+	"minions":                 &api.Minion{},
104
+	"builds":                  &buildapi.Build{},
105
+	"buildConfigs":            &buildapi.BuildConfig{},
106
+	"images":                  &imageapi.Image{},
107
+	"imageRepositories":       &imageapi.ImageRepository{},
108
+	"imageRepositoryMappings": &imageapi.ImageRepositoryMapping{},
109
+	"config":                  &configapi.Config{},
110
+	"deployments":             &deployapi.Deployment{},
111
+	"deploymentConfigs":       &deployapi.DeploymentConfig{},
112 112
 })
113 113
 
114 114
 func prettyWireStorage() string {
... ...
@@ -117,45 +134,49 @@ func prettyWireStorage() string {
117 117
 	return strings.Join(types, "|")
118 118
 }
119 119
 
120
-// readConfig reads and parses pod, replicationController, and service
121
-// configuration files. If any errors log and exit non-zero.
122
-func (c *KubeConfig) readConfig(storage string) []byte {
123
-	if len(c.Config) == 0 {
124
-		glog.Fatal("Need config file (-c)")
125
-	}
126
-
127
-	var data []byte
120
+// readConfigData reads the bytes from the specified filesytem or network location associated with the *config flag
121
+func (c *KubeConfig) readConfigData() []byte {
122
+	// read from STDIN
128 123
 	if c.Config == "-" {
129
-		body, err := ioutil.ReadAll(os.Stdin)
124
+		data, err := ioutil.ReadAll(os.Stdin)
130 125
 		if err != nil {
131
-			glog.Fatalf("Unable to read from STDIN: %v", err)
126
+			glog.Fatalf("Unable to read from STDIN: %v\n", err)
132 127
 		}
133
-		data = body
128
+		return data
129
+	}
134 130
 
135
-	} else if url, err := url.Parse(c.Config); err == nil && (url.Scheme == "http" || url.Scheme == "https") {
131
+	// we look for http:// or https:// to determine if valid URL, otherwise do normal file IO
132
+	if url, err := url.Parse(c.Config); err == nil && (url.Scheme == "http" || url.Scheme == "https") {
136 133
 		resp, err := http.Get(url.String())
137 134
 		if err != nil {
138
-			glog.Fatalf("Unable to access URL %v: %v", url, err)
135
+			glog.Fatalf("Unable to access URL %v: %v\n", c.Config, err)
139 136
 		}
140 137
 		defer resp.Body.Close()
141 138
 		if resp.StatusCode != 200 {
142 139
 			glog.Fatalf("Unable to read URL, server reported %d %s", resp.StatusCode, resp.Status)
143 140
 		}
144
-		body, err := ioutil.ReadAll(resp.Body)
141
+		data, err := ioutil.ReadAll(resp.Body)
145 142
 		if err != nil {
146
-			glog.Fatalf("Unable to read URL %v: %v", url, err)
143
+			glog.Fatalf("Unable to read URL %v: %v\n", c.Config, err)
147 144
 		}
148
-		data = body
145
+		return data
146
+	}
149 147
 
150
-	} else {
151
-		body, err := ioutil.ReadFile(c.Config)
152
-		if err != nil {
153
-			glog.Fatalf("Unable to read %v: %v", c.Config, err)
154
-		}
155
-		data = body
148
+	data, err := ioutil.ReadFile(c.Config)
149
+	if err != nil {
150
+		glog.Fatalf("Unable to read %v: %v\n", c.Config, err)
156 151
 	}
152
+	return data
153
+}
157 154
 
158
-	data, err := parser.ToWireFormat(data, storage)
155
+// readConfig reads and parses pod, replicationController, and service
156
+// configuration files. If any errors log and exit non-zero.
157
+func (c *KubeConfig) readConfig(storage string, serverCodec runtime.Codec) []byte {
158
+	if len(c.Config) == 0 {
159
+		glog.Fatal("Need config file (-c)")
160
+	}
161
+
162
+	data, err := parser.ToWireFormat(c.readConfigData(), storage, latest.Codec, serverCodec)
159 163
 	if err != nil {
160 164
 		glog.Fatalf("Error parsing %v as an object for %v: %v", c.Config, storage, err)
161 165
 	}
... ...
@@ -177,11 +198,11 @@ func (c *KubeConfig) Run() {
177 177
 	} else {
178 178
 		masterServer = "http://localhost:8080"
179 179
 	}
180
-	kubeClient, err := kubeclient.New(masterServer, nil)
180
+	kubeClient, err := kubeclient.New(masterServer, c.APIVersion, nil)
181 181
 	if err != nil {
182 182
 		glog.Fatalf("Unable to parse %s as a URL: %v", masterServer, err)
183 183
 	}
184
-	client, err := osclient.New(masterServer, nil)
184
+	client, err := osclient.New(masterServer, c.OSAPIVersion, nil)
185 185
 	if err != nil {
186 186
 		glog.Fatalf("Unable to parse %s as a URL: %v", masterServer, err)
187 187
 	}
... ...
@@ -193,11 +214,20 @@ func (c *KubeConfig) Run() {
193 193
 		if err != nil {
194 194
 			glog.Fatalf("Error loading auth: %v", err)
195 195
 		}
196
-		kubeClient, err = kubeclient.New(masterServer, auth)
196
+		if c.CAFile != "" {
197
+			auth.CAFile = c.CAFile
198
+		}
199
+		if c.CertFile != "" {
200
+			auth.CertFile = c.CertFile
201
+		}
202
+		if c.KeyFile != "" {
203
+			auth.KeyFile = c.KeyFile
204
+		}
205
+		kubeClient, err = kubeclient.New(masterServer, c.APIVersion, auth)
197 206
 		if err != nil {
198 207
 			glog.Fatalf("Unable to parse %s as a URL: %v", masterServer, err)
199 208
 		}
200
-		client, err = osclient.New(masterServer, auth)
209
+		client, err = osclient.New(masterServer, c.OSAPIVersion, auth)
201 210
 		if err != nil {
202 211
 			glog.Fatalf("Unable to parse %s as a URL: %v", masterServer, err)
203 212
 		}
... ...
@@ -234,17 +264,17 @@ func (c *KubeConfig) Run() {
234 234
 
235 235
 	method := c.Arg(0)
236 236
 	clients := ClientMappings{
237
-		"minions":                 {"Minion", kubeClient.RESTClient},
238
-		"pods":                    {"Pod", kubeClient.RESTClient},
239
-		"services":                {"Service", kubeClient.RESTClient},
240
-		"replicationControllers":  {"ReplicationController", kubeClient.RESTClient},
241
-		"builds":                  {"Build", client.RESTClient},
242
-		"buildConfigs":            {"BuildConfig", client.RESTClient},
243
-		"images":                  {"Image", client.RESTClient},
244
-		"imageRepositories":       {"ImageRepository", client.RESTClient},
245
-		"imageRepositoryMappings": {"ImageRepositoryMapping", client.RESTClient},
246
-		"deployments":             {"Deployment", client.RESTClient},
247
-		"deploymentConfigs":       {"DeploymentConfig", client.RESTClient},
237
+		"minions":                 {"Minion", kubeClient.RESTClient, klatest.Codec},
238
+		"pods":                    {"Pod", kubeClient.RESTClient, klatest.Codec},
239
+		"services":                {"Service", kubeClient.RESTClient, klatest.Codec},
240
+		"replicationControllers":  {"ReplicationController", kubeClient.RESTClient, klatest.Codec},
241
+		"builds":                  {"Build", client.RESTClient, latest.Codec},
242
+		"buildConfigs":            {"BuildConfig", client.RESTClient, latest.Codec},
243
+		"images":                  {"Image", client.RESTClient, latest.Codec},
244
+		"imageRepositories":       {"ImageRepository", client.RESTClient, latest.Codec},
245
+		"imageRepositoryMappings": {"ImageRepositoryMapping", client.RESTClient, latest.Codec},
246
+		"deployments":             {"Deployment", client.RESTClient, latest.Codec},
247
+		"deploymentConfigs":       {"DeploymentConfig", client.RESTClient, latest.Codec},
248 248
 	}
249 249
 
250 250
 	matchFound := c.executeConfigRequest(method, clients) || c.executeTemplateRequest(method, client) || c.executeControllerRequest(method, kubeClient) || c.executeAPIRequest(method, clients)
... ...
@@ -331,8 +361,8 @@ func (c *KubeConfig) executeAPIRequest(method string, clients ClientMappings) bo
331 331
 		ParseSelectorParam("labels", c.Selector)
332 332
 	if setBody {
333 333
 		if version != 0 {
334
-			data := c.readConfig(storage)
335
-			obj, err := runtime.Decode(data)
334
+			data := c.readConfig(storage, client.Codec)
335
+			obj, err := latest.Codec.Decode(data)
336 336
 			if err != nil {
337 337
 				glog.Fatalf("error setting resource version: %v", err)
338 338
 			}
... ...
@@ -341,13 +371,13 @@ func (c *KubeConfig) executeAPIRequest(method string, clients ClientMappings) bo
341 341
 				glog.Fatalf("error setting resource version: %v", err)
342 342
 			}
343 343
 			jsonBase.SetResourceVersion(version)
344
-			data, err = runtime.Encode(obj)
344
+			data, err = client.Codec.Encode(obj)
345 345
 			if err != nil {
346 346
 				glog.Fatalf("error setting resource version: %v", err)
347 347
 			}
348 348
 			r.Body(data)
349 349
 		} else {
350
-			r.Body(c.readConfig(storage))
350
+			r.Body(c.readConfig(storage, client.Codec))
351 351
 		}
352 352
 	}
353 353
 	result := r.Do()
... ...
@@ -411,7 +441,7 @@ func (c *KubeConfig) executeControllerRequest(method string, client *kubeclient.
411 411
 	case "rm":
412 412
 		err = kubecfg.DeleteController(parseController(), client)
413 413
 	case "rollingupdate":
414
-		err = kubecfg.Update(parseController(), client, c.UpdatePeriod)
414
+		err = kubecfg.Update(parseController(), client, c.UpdatePeriod, c.ImageName)
415 415
 	case "run":
416 416
 		if len(c.Args) != 4 {
417 417
 			glog.Fatal("usage: kubecfg [OPTIONS] run <image> <replicas> <controller>")
... ...
@@ -476,7 +506,7 @@ func (c *KubeConfig) executeConfigRequest(method string, clients ClientMappings)
476 476
 	if len(c.Config) == 0 {
477 477
 		glog.Fatal("Need to pass valid configuration file (-c config.json)")
478 478
 	}
479
-	errs := config.Apply(c.readConfig("config"), clients)
479
+	errs := config.Apply(c.readConfig("config", latest.Codec), clients)
480 480
 	for _, err := range errs {
481 481
 		fmt.Println(err.Error())
482 482
 	}
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"time"
8 8
 
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
10
+	klatest "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
10 11
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
11 12
 	kubeclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
12 13
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
... ...
@@ -15,7 +16,6 @@ import (
15 15
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
16 16
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/proxy"
17 17
 	pconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/proxy/config"
18
-	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
19 18
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
20 19
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
21 20
 	"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler"
... ...
@@ -27,8 +27,8 @@ import (
27 27
 	cadvisor "github.com/google/cadvisor/client"
28 28
 	"github.com/spf13/cobra"
29 29
 
30
-	_ "github.com/openshift/origin/pkg/api"
31
-	_ "github.com/openshift/origin/pkg/api/v1beta1"
30
+	"github.com/openshift/origin/pkg/api/latest"
31
+	"github.com/openshift/origin/pkg/api/v1beta1"
32 32
 	"github.com/openshift/origin/pkg/build"
33 33
 	buildapi "github.com/openshift/origin/pkg/build/api"
34 34
 	buildregistry "github.com/openshift/origin/pkg/build/registry/build"
... ...
@@ -102,10 +102,27 @@ type config struct {
102 102
 	masterHost string
103 103
 	nodeHosts  []string
104 104
 	bindAddr   string
105
+
106
+	storageVersion string
107
+}
108
+
109
+// newEtcdHelper returns an EtcdHelper for the provided arguments or an error if the version
110
+// is incorrect.
111
+func (c *config) newEtcdHelper() (helper tools.EtcdHelper, err error) {
112
+	client, _ := c.getEtcdClient()
113
+	version := c.storageVersion
114
+	if version == "" {
115
+		version = latest.Version
116
+	}
117
+	codec, versioner, err := latest.InterfacesFor(version)
118
+	if err != nil {
119
+		return helper, err
120
+	}
121
+	return tools.EtcdHelper{client, codec, versioner}, nil
105 122
 }
106 123
 
107 124
 func (c *config) getKubeClient() *kubeclient.Client {
108
-	kubeClient, err := kubeclient.New("http://"+c.ListenAddr, nil)
125
+	kubeClient, err := kubeclient.New("http://"+c.ListenAddr, klatest.Version, nil)
109 126
 	if err != nil {
110 127
 		glog.Fatalf("Unable to configure client - bad URL: %v", err)
111 128
 	}
... ...
@@ -113,7 +130,7 @@ func (c *config) getKubeClient() *kubeclient.Client {
113 113
 }
114 114
 
115 115
 func (c *config) getOsClient() *osclient.Client {
116
-	osClient, err := osclient.New("http://"+c.ListenAddr, nil)
116
+	osClient, err := osclient.New("http://"+c.ListenAddr, latest.Version, nil)
117 117
 	if err != nil {
118 118
 		glog.Fatalf("Unable to configure client - bad URL: %v", err)
119 119
 	}
... ...
@@ -174,15 +191,24 @@ func (c *config) runApiserver() {
174 174
 	osAddr := c.ListenAddr
175 175
 
176 176
 	kubePrefix := "/api/v1beta1"
177
+	kube2Prefix := "/api/v1beta2"
177 178
 	osPrefix := "/osapi/v1beta1"
178 179
 
179 180
 	kubeClient := c.getKubeClient()
180 181
 	osClient := c.getOsClient()
181
-	etcdClient, etcdServers := c.getEtcdClient()
182
+	_, etcdServers := c.getEtcdClient()
183
+	etcdHelper, err := c.newEtcdHelper()
184
+	if err != nil {
185
+		glog.Errorf("Error setting up server storage: %v", err)
186
+	}
187
+	ketcdHelper, err := master.NewEtcdHelper(etcdServers, klatest.Version)
188
+	if err != nil {
189
+		glog.Errorf("Error setting up Kubernetes server storage: %v", err)
190
+	}
182 191
 
183
-	buildRegistry := buildetcd.NewEtcd(etcdClient)
184
-	imageRegistry := imageetcd.NewEtcd(etcdClient)
185
-	deployEtcd := deployetcd.NewEtcd(etcdClient)
192
+	buildRegistry := buildetcd.New(etcdHelper)
193
+	imageRegistry := imageetcd.New(etcdHelper)
194
+	deployEtcd := deployetcd.New(etcdHelper)
186 195
 
187 196
 	// initialize OpenShift API
188 197
 	storage := map[string]apiserver.RESTStorage{
... ...
@@ -191,9 +217,9 @@ func (c *config) runApiserver() {
191 191
 		"images":                  image.NewREST(imageRegistry),
192 192
 		"imageRepositories":       imagerepository.NewREST(imageRegistry),
193 193
 		"imageRepositoryMappings": imagerepositorymapping.NewREST(imageRegistry, imageRegistry),
194
-		"templateConfigs":         template.NewStorage(),
195 194
 		"deployments":             deployregistry.NewREST(deployEtcd),
196 195
 		"deploymentConfigs":       deployconfigregistry.NewREST(deployEtcd),
196
+		"templateConfigs":         template.NewStorage(),
197 197
 	}
198 198
 
199 199
 	osMux := http.NewServeMux()
... ...
@@ -212,7 +238,7 @@ func (c *config) runApiserver() {
212 212
 	}
213 213
 	masterConfig := &master.Config{
214 214
 		Client:             kubeClient,
215
-		EtcdServers:        etcdServers,
215
+		EtcdHelper:         ketcdHelper,
216 216
 		HealthCheckMinions: true,
217 217
 		Minions:            c.nodeHosts,
218 218
 		PodInfoGetter:      podInfoGetter,
... ...
@@ -220,7 +246,8 @@ func (c *config) runApiserver() {
220 220
 	m := master.New(masterConfig)
221 221
 
222 222
 	apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(osMux, kubePrefix)
223
-	apiserver.NewAPIGroup(storage, runtime.Codec).InstallREST(osMux, osPrefix)
223
+	apiserver.NewAPIGroup(m.API_v1beta2()).InstallREST(osMux, kube2Prefix)
224
+	apiserver.NewAPIGroup(storage, v1beta1.Codec).InstallREST(osMux, osPrefix)
224 225
 	apiserver.InstallSupport(osMux)
225 226
 
226 227
 	osApi := &http.Server{
... ...
@@ -233,6 +260,7 @@ func (c *config) runApiserver() {
233 233
 
234 234
 	go util.Forever(func() {
235 235
 		glog.Infof("Started Kubernetes API at http://%s%s", osAddr, kubePrefix)
236
+		glog.Infof("Started Kubernetes API at http://%s%s", osAddr, kube2Prefix)
236 237
 		glog.Infof("Started OpenShift API at http://%s%s", osAddr, osPrefix)
237 238
 		glog.Fatal(osApi.ListenAndServe())
238 239
 	}, 0)
... ...
@@ -289,7 +317,7 @@ func (c *config) runProxy() {
289 289
 		serviceConfig.Channel("etcd"),
290 290
 		endpointsConfig.Channel("etcd"))
291 291
 	loadBalancer := proxy.NewLoadBalancerRR()
292
-	proxier := proxy.NewProxier(loadBalancer)
292
+	proxier := proxy.NewProxier(loadBalancer, c.bindAddr)
293 293
 	serviceConfig.RegisterHandler(proxier)
294 294
 	endpointsConfig.RegisterHandler(loadBalancer)
295 295
 	glog.Infof("Started Kubernetes Proxy")
... ...
@@ -1,7 +1,13 @@
1 1
 package api
2 2
 
3
-import "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
3
+import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5
+)
4 6
 
5 7
 func init() {
6
-	runtime.AddKnownTypes("", Config{})
8
+	api.Scheme.AddKnownTypes("",
9
+		&Config{},
10
+	)
7 11
 }
12
+
13
+func (*Config) IsAnAPIObject() {}
... ...
@@ -19,7 +19,7 @@ type Config struct {
19 19
 
20 20
 	// Required: Items is an array of Kubernetes resources of Service,
21 21
 	// Pod and/or ReplicationController kind.
22
-	// TODO: Handle unregistered types. Define custom []interface{}
22
+	// TODO: Handle unregistered types. Define custom []runtime.Object
23 23
 	//       type and its unmarshaller instead of []runtime.Object.
24
-	Items []runtime.Object `json:"items" yaml:"items"`
24
+	Items []runtime.EmbeddedObject `json:"items" yaml:"items"`
25 25
 }
... ...
@@ -1,7 +1,13 @@
1 1
 package v1beta1
2 2
 
3
-import "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
3
+import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5
+)
4 6
 
5 7
 func init() {
6
-	runtime.AddKnownTypes("v1beta1", Config{})
8
+	api.Scheme.AddKnownTypes("v1beta1",
9
+		&Config{},
10
+	)
7 11
 }
12
+
13
+func (*Config) IsAnAPIObject() {}
... ...
@@ -19,7 +19,7 @@ type Config struct {
19 19
 
20 20
 	// Required: Items is an array of Kubernetes resources of Service,
21 21
 	// Pod and/or ReplicationController kind.
22
-	// TODO: Handle unregistered types. Define custom []interface{}
22
+	// TODO: Handle unregistered types. Define custom []runtime.Object
23 23
 	//       type and its unmarshaller instead of []runtime.Object.
24
-	Items []runtime.Object `json:"items" yaml:"items"`
24
+	Items []runtime.RawExtension `json:"items" yaml:"items"`
25 25
 }
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"fmt"
6 6
 
7 7
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
8
+
8 9
 	clientapi "github.com/openshift/origin/pkg/cmd/client/api"
9 10
 )
10 11
 
... ...
@@ -1,14 +1,19 @@
1 1
 package api
2 2
 
3 3
 import (
4
-	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5 5
 )
6 6
 
7 7
 func init() {
8
-	runtime.AddKnownTypes("",
9
-		DeploymentList{},
10
-		Deployment{},
11
-		DeploymentConfigList{},
12
-		DeploymentConfig{},
8
+	api.Scheme.AddKnownTypes("",
9
+		&Deployment{},
10
+		&DeploymentList{},
11
+		&DeploymentConfig{},
12
+		&DeploymentConfigList{},
13 13
 	)
14 14
 }
15
+
16
+func (*Deployment) IsAnAPIObject()           {}
17
+func (*DeploymentList) IsAnAPIObject()       {}
18
+func (*DeploymentConfig) IsAnAPIObject()     {}
19
+func (*DeploymentConfigList) IsAnAPIObject() {}
... ...
@@ -1,14 +1,19 @@
1 1
 package v1beta1
2 2
 
3 3
 import (
4
-	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5 5
 )
6 6
 
7 7
 func init() {
8
-	runtime.AddKnownTypes("v1beta1",
9
-		DeploymentList{},
10
-		Deployment{},
11
-		DeploymentConfigList{},
12
-		DeploymentConfig{},
8
+	api.Scheme.AddKnownTypes("v1beta1",
9
+		&Deployment{},
10
+		&DeploymentList{},
11
+		&DeploymentConfig{},
12
+		&DeploymentConfigList{},
13 13
 	)
14 14
 }
15
+
16
+func (*Deployment) IsAnAPIObject()           {}
17
+func (*DeploymentList) IsAnAPIObject()       {}
18
+func (*DeploymentConfig) IsAnAPIObject()     {}
19
+func (*DeploymentConfigList) IsAnAPIObject() {}
... ...
@@ -101,7 +101,7 @@ func (dh *DefaultDeploymentHandler) saveDeployment(deployment *deployapi.Deploym
101 101
 	return err
102 102
 }
103 103
 
104
-func (dh *DefaultDeploymentHandler) makeDeploymentPod(deployment *deployapi.Deployment) api.Pod {
104
+func (dh *DefaultDeploymentHandler) makeDeploymentPod(deployment *deployapi.Deployment) *api.Pod {
105 105
 	podID := deploymentPodID(deployment)
106 106
 
107 107
 	envVars := deployment.Strategy.CustomPod.Environment
... ...
@@ -110,7 +110,7 @@ func (dh *DefaultDeploymentHandler) makeDeploymentPod(deployment *deployapi.Depl
110 110
 		envVars = append(envVars, env)
111 111
 	}
112 112
 
113
-	return api.Pod{
113
+	return &api.Pod{
114 114
 		JSONBase: api.JSONBase{
115 115
 			ID: podID,
116 116
 		},
... ...
@@ -119,15 +119,14 @@ func (dh *DefaultDeploymentHandler) makeDeploymentPod(deployment *deployapi.Depl
119 119
 				Version: "v1beta1",
120 120
 				Containers: []api.Container{
121 121
 					{
122
-						Name:          "deployment",
123
-						Image:         deployment.Strategy.CustomPod.Image,
124
-						Env:           envVars,
125
-						RestartPolicy: "runOnce",
122
+						Name:  "deployment",
123
+						Image: deployment.Strategy.CustomPod.Image,
124
+						Env:   envVars,
126 125
 					},
127 126
 				},
128
-			},
129
-			RestartPolicy: api.RestartPolicy{
130
-				Type: api.RestartNever,
127
+				RestartPolicy: api.RestartPolicy{
128
+					Never: &api.RestartPolicyNever{},
129
+				},
131 130
 			},
132 131
 		},
133 132
 	}
... ...
@@ -190,7 +189,7 @@ func (dh *DefaultDeploymentHandler) HandleRunning(deployment *deployapi.Deployme
190 190
 	return dh.saveDeployment(deployment)
191 191
 }
192 192
 
193
-func (dh *DefaultDeploymentHandler) checkForTerminatedDeploymentPod(deployment *deployapi.Deployment, pod api.Pod) {
193
+func (dh *DefaultDeploymentHandler) checkForTerminatedDeploymentPod(deployment *deployapi.Deployment, pod *api.Pod) {
194 194
 	if pod.CurrentState.Status != api.PodTerminated {
195 195
 		glog.Infof("The deployment has not yet finished. Pod status is %s. Continuing", pod.CurrentState.Status)
196 196
 		return
... ...
@@ -8,7 +8,9 @@ import (
8 8
 	kubeerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
11
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
11 12
 	"github.com/golang/glog"
13
+
12 14
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
13 15
 	"github.com/openshift/origin/pkg/deploy/api/validation"
14 16
 )
... ...
@@ -25,7 +27,7 @@ func NewREST(registry Registry) apiserver.RESTStorage {
25 25
 }
26 26
 
27 27
 // List obtains a list of Deployments that match selector.
28
-func (s *REST) List(selector labels.Selector) (interface{}, error) {
28
+func (s *REST) List(selector, fields labels.Selector) (runtime.Object, error) {
29 29
 	deployments, err := s.registry.ListDeployments(selector)
30 30
 	if err != nil {
31 31
 		return nil, err
... ...
@@ -35,12 +37,12 @@ func (s *REST) List(selector labels.Selector) (interface{}, error) {
35 35
 }
36 36
 
37 37
 // New creates a new Deployment for use with Create and Update
38
-func (s *REST) New() interface{} {
38
+func (s *REST) New() runtime.Object {
39 39
 	return &deployapi.Deployment{}
40 40
 }
41 41
 
42 42
 // Get obtains the Deployment specified by its id.
43
-func (s *REST) Get(id string) (interface{}, error) {
43
+func (s *REST) Get(id string) (runtime.Object, error) {
44 44
 	deployment, err := s.registry.GetDeployment(id)
45 45
 	if err != nil {
46 46
 		return nil, err
... ...
@@ -49,14 +51,14 @@ func (s *REST) Get(id string) (interface{}, error) {
49 49
 }
50 50
 
51 51
 // Delete asynchronously deletes the Deployment specified by its id.
52
-func (s *REST) Delete(id string) (<-chan interface{}, error) {
53
-	return apiserver.MakeAsync(func() (interface{}, error) {
54
-		return api.Status{Status: api.StatusSuccess}, s.registry.DeleteDeployment(id)
52
+func (s *REST) Delete(id string) (<-chan runtime.Object, error) {
53
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
54
+		return &api.Status{Status: api.StatusSuccess}, s.registry.DeleteDeployment(id)
55 55
 	}), nil
56 56
 }
57 57
 
58 58
 // Create registers a given new Deployment instance to s.registry.
59
-func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
59
+func (s *REST) Create(obj runtime.Object) (<-chan runtime.Object, error) {
60 60
 	deployment, ok := obj.(*deployapi.Deployment)
61 61
 	if !ok {
62 62
 		return nil, fmt.Errorf("not a deployment: %#v", obj)
... ...
@@ -73,17 +75,17 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
73 73
 		return nil, kubeerrors.NewInvalid("deployment", deployment.ID, errs)
74 74
 	}
75 75
 
76
-	return apiserver.MakeAsync(func() (interface{}, error) {
76
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
77 77
 		err := s.registry.CreateDeployment(deployment)
78 78
 		if err != nil {
79 79
 			return nil, err
80 80
 		}
81
-		return *deployment, nil
81
+		return deployment, nil
82 82
 	}), nil
83 83
 }
84 84
 
85 85
 // Update replaces a given Deployment instance with an existing instance in s.registry.
86
-func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
86
+func (s *REST) Update(obj runtime.Object) (<-chan runtime.Object, error) {
87 87
 	deployment, ok := obj.(*deployapi.Deployment)
88 88
 	if !ok {
89 89
 		return nil, fmt.Errorf("not a deployment: %#v", obj)
... ...
@@ -91,7 +93,7 @@ func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
91 91
 	if len(deployment.ID) == 0 {
92 92
 		return nil, fmt.Errorf("id is unspecified: %#v", deployment)
93 93
 	}
94
-	return apiserver.MakeAsync(func() (interface{}, error) {
94
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
95 95
 		err := s.registry.UpdateDeployment(deployment)
96 96
 		if err != nil {
97 97
 			return nil, err
... ...
@@ -7,6 +7,8 @@ import (
7 7
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
8 8
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
10
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
11
+
10 12
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
11 13
 )
12 14
 
... ...
@@ -22,7 +24,7 @@ func NewREST(registry Registry) apiserver.RESTStorage {
22 22
 }
23 23
 
24 24
 // List obtains a list of DeploymentConfigs that match selector.
25
-func (s *REST) List(selector labels.Selector) (interface{}, error) {
25
+func (s *REST) List(selector, fields labels.Selector) (runtime.Object, error) {
26 26
 	deploymentConfigs, err := s.registry.ListDeploymentConfigs(selector)
27 27
 	if err != nil {
28 28
 		return nil, err
... ...
@@ -32,7 +34,7 @@ func (s *REST) List(selector labels.Selector) (interface{}, error) {
32 32
 }
33 33
 
34 34
 // Get obtains the DeploymentConfig specified by its id.
35
-func (s *REST) Get(id string) (interface{}, error) {
35
+func (s *REST) Get(id string) (runtime.Object, error) {
36 36
 	deploymentConfig, err := s.registry.GetDeploymentConfig(id)
37 37
 	if err != nil {
38 38
 		return nil, err
... ...
@@ -41,19 +43,19 @@ func (s *REST) Get(id string) (interface{}, error) {
41 41
 }
42 42
 
43 43
 // Delete asynchronously deletes the DeploymentConfig specified by its id.
44
-func (s *REST) Delete(id string) (<-chan interface{}, error) {
45
-	return apiserver.MakeAsync(func() (interface{}, error) {
46
-		return api.Status{Status: api.StatusSuccess}, s.registry.DeleteDeploymentConfig(id)
44
+func (s *REST) Delete(id string) (<-chan runtime.Object, error) {
45
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
46
+		return &api.Status{Status: api.StatusSuccess}, s.registry.DeleteDeploymentConfig(id)
47 47
 	}), nil
48 48
 }
49 49
 
50 50
 // New creates a new DeploymentConfig for use with Create and Update
51
-func (s *REST) New() interface{} {
51
+func (s *REST) New() runtime.Object {
52 52
 	return &deployapi.DeploymentConfig{}
53 53
 }
54 54
 
55 55
 // Create registers a given new DeploymentConfig instance to s.registry.
56
-func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
56
+func (s *REST) Create(obj runtime.Object) (<-chan runtime.Object, error) {
57 57
 	deploymentConfig, ok := obj.(*deployapi.DeploymentConfig)
58 58
 	if !ok {
59 59
 		return nil, fmt.Errorf("not a deploymentConfig: %#v", obj)
... ...
@@ -64,7 +66,7 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
64 64
 
65 65
 	//TODO: Add validation
66 66
 
67
-	return apiserver.MakeAsync(func() (interface{}, error) {
67
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
68 68
 		err := s.registry.CreateDeploymentConfig(deploymentConfig)
69 69
 		if err != nil {
70 70
 			return nil, err
... ...
@@ -74,7 +76,7 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
74 74
 }
75 75
 
76 76
 // Update replaces a given DeploymentConfig instance with an existing instance in s.registry.
77
-func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
77
+func (s *REST) Update(obj runtime.Object) (<-chan runtime.Object, error) {
78 78
 	deploymentConfig, ok := obj.(*deployapi.DeploymentConfig)
79 79
 	if !ok {
80 80
 		return nil, fmt.Errorf("not a deploymentConfig: %#v", obj)
... ...
@@ -82,7 +84,7 @@ func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
82 82
 	if len(deploymentConfig.ID) == 0 {
83 83
 		return nil, fmt.Errorf("id is unspecified: %#v", deploymentConfig)
84 84
 	}
85
-	return apiserver.MakeAsync(func() (interface{}, error) {
85
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
86 86
 		err := s.registry.UpdateDeploymentConfig(deploymentConfig)
87 87
 		if err != nil {
88 88
 			return nil, err
... ...
@@ -3,8 +3,8 @@ package etcd
3 3
 import (
4 4
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
5 5
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
6
-	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
7 6
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
7
+
8 8
 	"github.com/openshift/origin/pkg/deploy/api"
9 9
 )
10 10
 
... ...
@@ -13,12 +13,11 @@ type Etcd struct {
13 13
 	tools.EtcdHelper
14 14
 }
15 15
 
16
-// NewEtcd creates an etcd registry using the given etcd client.
17
-func NewEtcd(client tools.EtcdClient) *Etcd {
18
-	registry := &Etcd{
19
-		tools.EtcdHelper{client, runtime.Codec, runtime.ResourceVersioner},
16
+// New creates an etcd registry.
17
+func New(helper tools.EtcdHelper) *Etcd {
18
+	return &Etcd{
19
+		EtcdHelper: helper,
20 20
 	}
21
-	return registry
22 21
 }
23 22
 
24 23
 // ListDeployments obtains a list of Deployments.
... ...
@@ -1,13 +1,21 @@
1 1
 package api
2 2
 
3
-import "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
3
+import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5
+)
4 6
 
5 7
 func init() {
6
-	runtime.AddKnownTypes("",
7
-		Image{},
8
-		ImageList{},
9
-		ImageRepository{},
10
-		ImageRepositoryList{},
11
-		ImageRepositoryMapping{},
8
+	api.Scheme.AddKnownTypes("",
9
+		&Image{},
10
+		&ImageList{},
11
+		&ImageRepository{},
12
+		&ImageRepositoryList{},
13
+		&ImageRepositoryMapping{},
12 14
 	)
13 15
 }
16
+
17
+func (*Image) IsAnAPIObject()                  {}
18
+func (*ImageList) IsAnAPIObject()              {}
19
+func (*ImageRepository) IsAnAPIObject()        {}
20
+func (*ImageRepositoryList) IsAnAPIObject()    {}
21
+func (*ImageRepositoryMapping) IsAnAPIObject() {}
... ...
@@ -1,13 +1,21 @@
1 1
 package v1beta1
2 2
 
3
-import "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
3
+import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5
+)
4 6
 
5 7
 func init() {
6
-	runtime.AddKnownTypes("v1beta1",
7
-		Image{},
8
-		ImageList{},
9
-		ImageRepository{},
10
-		ImageRepositoryList{},
11
-		ImageRepositoryMapping{},
8
+	api.Scheme.AddKnownTypes("v1beta1",
9
+		&Image{},
10
+		&ImageList{},
11
+		&ImageRepository{},
12
+		&ImageRepositoryList{},
13
+		&ImageRepositoryMapping{},
12 14
 	)
13 15
 }
16
+
17
+func (*Image) IsAnAPIObject()                  {}
18
+func (*ImageList) IsAnAPIObject()              {}
19
+func (*ImageRepository) IsAnAPIObject()        {}
20
+func (*ImageRepositoryList) IsAnAPIObject()    {}
21
+func (*ImageRepositoryMapping) IsAnAPIObject() {}
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
11 11
 	"github.com/golang/glog"
12
+
12 13
 	"github.com/openshift/origin/pkg/image/api"
13 14
 )
14 15
 
... ...
@@ -17,17 +18,11 @@ type Etcd struct {
17 17
 	tools.EtcdHelper
18 18
 }
19 19
 
20
-// NewEtcd returns a new Etcd.
21
-func NewEtcd(client tools.EtcdClient) *Etcd {
22
-	registry := &Etcd{
23
-		EtcdHelper: tools.EtcdHelper{
24
-			client,
25
-			runtime.Codec,
26
-			runtime.ResourceVersioner,
27
-		},
20
+// New returns a new etcd registry.
21
+func New(helper tools.EtcdHelper) *Etcd {
22
+	return &Etcd{
23
+		EtcdHelper: helper,
28 24
 	}
29
-
30
-	return registry
31 25
 }
32 26
 
33 27
 // ListImages retrieves a list of images that match selector.
... ...
@@ -116,7 +111,7 @@ func (r *Etcd) GetImageRepository(id string) (*api.ImageRepository, error) {
116 116
 
117 117
 // WatchImageRepositories begins watching for new, changed, or deleted ImageRepositories.
118 118
 func (r *Etcd) WatchImageRepositories(resourceVersion uint64, filter func(repo *api.ImageRepository) bool) (watch.Interface, error) {
119
-	return r.WatchList("/imageRepositories", resourceVersion, func(obj interface{}) bool {
119
+	return r.WatchList("/imageRepositories", resourceVersion, func(obj runtime.Object) bool {
120 120
 		repo, ok := obj.(*api.ImageRepository)
121 121
 		if !ok {
122 122
 			glog.Errorf("Unexpected object during image repository watch: %#v", obj)
... ...
@@ -7,7 +7,9 @@ import (
7 7
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
8 8
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
10
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
10 11
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
12
+
11 13
 	"github.com/openshift/origin/pkg/image/api"
12 14
 	"github.com/openshift/origin/pkg/image/api/validation"
13 15
 )
... ...
@@ -23,12 +25,12 @@ func NewREST(registry Registry) apiserver.RESTStorage {
23 23
 }
24 24
 
25 25
 // New returns a new Image for use with Create and Update.
26
-func (s *REST) New() interface{} {
26
+func (s *REST) New() runtime.Object {
27 27
 	return &api.Image{}
28 28
 }
29 29
 
30 30
 // Get retrieves an Image by id.
31
-func (s *REST) Get(id string) (interface{}, error) {
31
+func (s *REST) Get(id string) (runtime.Object, error) {
32 32
 	image, err := s.registry.GetImage(id)
33 33
 	if err != nil {
34 34
 		return nil, err
... ...
@@ -37,7 +39,7 @@ func (s *REST) Get(id string) (interface{}, error) {
37 37
 }
38 38
 
39 39
 // List retrieves a list of Images that match selector.
40
-func (s *REST) List(selector labels.Selector) (interface{}, error) {
40
+func (s *REST) List(selector, fields labels.Selector) (runtime.Object, error) {
41 41
 	images, err := s.registry.ListImages(selector)
42 42
 	if err != nil {
43 43
 		return nil, err
... ...
@@ -47,7 +49,7 @@ func (s *REST) List(selector labels.Selector) (interface{}, error) {
47 47
 }
48 48
 
49 49
 // Create registers the given Image.
50
-func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
50
+func (s *REST) Create(obj runtime.Object) (<-chan runtime.Object, error) {
51 51
 	image, ok := obj.(*api.Image)
52 52
 	if !ok {
53 53
 		return nil, fmt.Errorf("not an image: %#v", obj)
... ...
@@ -59,7 +61,7 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
59 59
 		return nil, errors.NewInvalid("image", image.ID, errs)
60 60
 	}
61 61
 
62
-	return apiserver.MakeAsync(func() (interface{}, error) {
62
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
63 63
 		if err := s.registry.CreateImage(image); err != nil {
64 64
 			return nil, err
65 65
 		}
... ...
@@ -68,13 +70,13 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
68 68
 }
69 69
 
70 70
 // Update is not supported for Images, as they are immutable.
71
-func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
71
+func (s *REST) Update(obj runtime.Object) (<-chan runtime.Object, error) {
72 72
 	return nil, fmt.Errorf("Images may not be changed.")
73 73
 }
74 74
 
75 75
 // Delete asynchronously deletes an Image specified by its id.
76
-func (s *REST) Delete(id string) (<-chan interface{}, error) {
77
-	return apiserver.MakeAsync(func() (interface{}, error) {
76
+func (s *REST) Delete(id string) (<-chan runtime.Object, error) {
77
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
78 78
 		return &kubeapi.Status{Status: kubeapi.StatusSuccess}, s.registry.DeleteImage(id)
79 79
 	}), nil
80 80
 }
... ...
@@ -8,8 +8,10 @@ import (
8 8
 	baseapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
11
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
11 12
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
12 13
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
14
+
13 15
 	"github.com/openshift/origin/pkg/image/api"
14 16
 )
15 17
 
... ...
@@ -24,12 +26,12 @@ func NewREST(registry Registry) apiserver.RESTStorage {
24 24
 }
25 25
 
26 26
 // New returns a new ImageRepository for use with Create and Update.
27
-func (s *REST) New() interface{} {
27
+func (s *REST) New() runtime.Object {
28 28
 	return &api.ImageRepository{}
29 29
 }
30 30
 
31 31
 // Get retrieves an ImageRepository by id.
32
-func (s *REST) Get(id string) (interface{}, error) {
32
+func (s *REST) Get(id string) (runtime.Object, error) {
33 33
 	repo, err := s.registry.GetImageRepository(id)
34 34
 	if err != nil {
35 35
 		return nil, err
... ...
@@ -38,7 +40,7 @@ func (s *REST) Get(id string) (interface{}, error) {
38 38
 }
39 39
 
40 40
 // List retrieves a list of ImageRepositories that match selector.
41
-func (s *REST) List(selector labels.Selector) (interface{}, error) {
41
+func (s *REST) List(selector, fields labels.Selector) (runtime.Object, error) {
42 42
 	imageRepositories, err := s.registry.ListImageRepositories(selector)
43 43
 	if err != nil {
44 44
 		return nil, err
... ...
@@ -58,7 +60,7 @@ func (s *REST) Watch(label, field labels.Selector, resourceVersion uint64) (watc
58 58
 }
59 59
 
60 60
 // Create registers the given ImageRepository.
61
-func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
61
+func (s *REST) Create(obj runtime.Object) (<-chan runtime.Object, error) {
62 62
 	repo, ok := obj.(*api.ImageRepository)
63 63
 	if !ok {
64 64
 		return nil, fmt.Errorf("not an image repository: %#v", obj)
... ...
@@ -74,7 +76,7 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
74 74
 
75 75
 	repo.CreationTimestamp = util.Now()
76 76
 
77
-	return apiserver.MakeAsync(func() (interface{}, error) {
77
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
78 78
 		if err := s.registry.CreateImageRepository(repo); err != nil {
79 79
 			return nil, err
80 80
 		}
... ...
@@ -83,7 +85,7 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
83 83
 }
84 84
 
85 85
 // Update replaces an existing ImageRepository in the registry with the given ImageRepository.
86
-func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
86
+func (s *REST) Update(obj runtime.Object) (<-chan runtime.Object, error) {
87 87
 	repo, ok := obj.(*api.ImageRepository)
88 88
 	if !ok {
89 89
 		return nil, fmt.Errorf("not an image repository: %#v", obj)
... ...
@@ -92,7 +94,7 @@ func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
92 92
 		return nil, fmt.Errorf("id is unspecified: %#v", repo)
93 93
 	}
94 94
 
95
-	return apiserver.MakeAsync(func() (interface{}, error) {
95
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
96 96
 		err := s.registry.UpdateImageRepository(repo)
97 97
 		if err != nil {
98 98
 			return nil, err
... ...
@@ -102,8 +104,8 @@ func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
102 102
 }
103 103
 
104 104
 // Delete asynchronously deletes an ImageRepository specified by its id.
105
-func (s *REST) Delete(id string) (<-chan interface{}, error) {
106
-	return apiserver.MakeAsync(func() (interface{}, error) {
105
+func (s *REST) Delete(id string) (<-chan runtime.Object, error) {
106
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
107 107
 		return &baseapi.Status{Status: baseapi.StatusSuccess}, s.registry.DeleteImageRepository(id)
108 108
 	}), nil
109 109
 }
... ...
@@ -7,7 +7,9 @@ import (
7 7
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
8 8
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
10
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
10 11
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
12
+
11 13
 	"github.com/openshift/origin/pkg/image/api"
12 14
 	"github.com/openshift/origin/pkg/image/api/validation"
13 15
 	"github.com/openshift/origin/pkg/image/registry/image"
... ...
@@ -27,22 +29,22 @@ func NewREST(imageRegistry image.Registry, imageRepositoryRegistry imagereposito
27 27
 }
28 28
 
29 29
 // New returns a new ImageRepositoryMapping for use with Create.
30
-func (s *REST) New() interface{} {
30
+func (s *REST) New() runtime.Object {
31 31
 	return &api.ImageRepositoryMapping{}
32 32
 }
33 33
 
34 34
 // Get is not supported.
35
-func (s *REST) Get(id string) (interface{}, error) {
35
+func (s *REST) Get(id string) (runtime.Object, error) {
36 36
 	return nil, errors.NewNotFound("imageRepositoryMapping", id)
37 37
 }
38 38
 
39 39
 // List is not supported.
40
-func (s *REST) List(selector labels.Selector) (interface{}, error) {
40
+func (s *REST) List(selector, fields labels.Selector) (runtime.Object, error) {
41 41
 	return nil, errors.NewNotFound("imageRepositoryMapping", "list")
42 42
 }
43 43
 
44 44
 // Create registers a new image (if it doesn't exist) and updates the specified ImageRepository's tags.
45
-func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
45
+func (s *REST) Create(obj runtime.Object) (<-chan runtime.Object, error) {
46 46
 	mapping, ok := obj.(*api.ImageRepositoryMapping)
47 47
 	if !ok {
48 48
 		return nil, fmt.Errorf("not an image repository mapping: %#v", obj)
... ...
@@ -73,7 +75,7 @@ func (s *REST) Create(obj interface{}) (<-chan interface{}, error) {
73 73
 	}
74 74
 	repo.Tags[mapping.Tag] = image.ID
75 75
 
76
-	return apiserver.MakeAsync(func() (interface{}, error) {
76
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
77 77
 		err = s.imageRegistry.CreateImage(&image)
78 78
 		if err != nil && !errors.IsAlreadyExists(err) {
79 79
 			return nil, err
... ...
@@ -108,11 +110,11 @@ func (s *REST) findImageRepository(dockerRepo string) (*api.ImageRepository, err
108 108
 }
109 109
 
110 110
 // Update is not supported.
111
-func (s *REST) Update(obj interface{}) (<-chan interface{}, error) {
111
+func (s *REST) Update(obj runtime.Object) (<-chan runtime.Object, error) {
112 112
 	return nil, fmt.Errorf("ImageRepositoryMappings may not be changed.")
113 113
 }
114 114
 
115 115
 // Delete is not supported.
116
-func (s *REST) Delete(id string) (<-chan interface{}, error) {
116
+func (s *REST) Delete(id string) (<-chan runtime.Object, error) {
117 117
 	return nil, errors.NewNotFound("imageRepositoryMapping", id)
118 118
 }
... ...
@@ -1,7 +1,13 @@
1 1
 package api
2 2
 
3
-import "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
3
+import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5
+)
4 6
 
5 7
 func init() {
6
-	runtime.AddKnownTypes("", Template{})
8
+	api.Scheme.AddKnownTypes("",
9
+		&Template{},
10
+	)
7 11
 }
12
+
13
+func (*Template) IsAnAPIObject() {}
... ...
@@ -17,9 +17,9 @@ type Template struct {
17 17
 
18 18
 	// Required: Items is an array of Kubernetes resources of Service,
19 19
 	// Pod and/or ReplicationController kind.
20
-	// TODO: Handle unregistered types. Define custom []interface{}
20
+	// TODO: Handle unregistered types. Define custom []runtime.Object
21 21
 	//       type and its unmarshaller instead of []runtime.Object.
22
-	Items []runtime.Object `json:"items" yaml:"items"`
22
+	Items []runtime.EmbeddedObject `json:"items" yaml:"items"`
23 23
 
24 24
 	// Optional: Parameters is an array of Parameters used during the
25 25
 	// Template to Config transformation.
... ...
@@ -47,6 +47,6 @@ type Parameter struct {
47 47
 
48 48
 	// Optional: Value holds the Parameter data. The data replaces all occurances
49 49
 	// of the Parameter name during the Template to Config transformation.
50
-	// TODO: Change this to interface{} and support more types than just string.
50
+	// TODO: Change this to runtime.Object and support more types than just string.
51 51
 	Value string `json:"value,omitempty" yaml:"value,omitempty"`
52 52
 }
... ...
@@ -1,7 +1,13 @@
1 1
 package v1beta1
2 2
 
3
-import "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
3
+import (
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
5
+)
4 6
 
5 7
 func init() {
6
-	runtime.AddKnownTypes("v1beta1", Template{})
8
+	api.Scheme.AddKnownTypes("v1beta1",
9
+		&Template{},
10
+	)
7 11
 }
12
+
13
+func (*Template) IsAnAPIObject() {}
... ...
@@ -17,9 +17,9 @@ type Template struct {
17 17
 
18 18
 	// Required: Items is an array of Kubernetes resources of Service,
19 19
 	// Pod and/or ReplicationController kind.
20
-	// TODO: Handle unregistered types. Define custom []interface{}
20
+	// TODO: Handle unregistered types. Define custom []runtime.Object
21 21
 	//       type and its unmarshaller instead of []runtime.Object.
22
-	Items []runtime.Object `json:"items" yaml:"items"`
22
+	Items []runtime.RawExtension `json:"items" yaml:"items"`
23 23
 
24 24
 	// Optional: Parameters is an array of Parameters used during the
25 25
 	// Template to Config transformation.
... ...
@@ -47,6 +47,6 @@ type Parameter struct {
47 47
 
48 48
 	// Optional: Value holds the Parameter data. The data replaces all occurances
49 49
 	// of the Parameter name during the Template to Config transformation.
50
-	// TODO: Change this to interface{} and support more types than just string.
50
+	// TODO: Change this to runtime.Object and support more types than just string.
51 51
 	Value string `json:"value,omitempty" yaml:"value,omitempty"`
52 52
 }
... ...
@@ -8,6 +8,7 @@ import (
8 8
 
9 9
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
10 10
 	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
11
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
11 12
 
12 13
 	"github.com/openshift/origin/pkg/template/api"
13 14
 	"github.com/openshift/origin/pkg/template/api/validation"
... ...
@@ -22,29 +23,29 @@ func NewStorage() apiserver.RESTStorage {
22 22
 	return &Storage{}
23 23
 }
24 24
 
25
-func (s *Storage) List(selector labels.Selector) (interface{}, error) {
25
+func (s *Storage) List(selector, fields labels.Selector) (runtime.Object, error) {
26 26
 	return nil, errors.New("template.Storage.List() is not implemented.")
27 27
 }
28 28
 
29
-func (s *Storage) Get(id string) (interface{}, error) {
29
+func (s *Storage) Get(id string) (runtime.Object, error) {
30 30
 	return nil, errors.New("template.Storage.Get() is not implemented.")
31 31
 }
32 32
 
33
-func (s *Storage) New() interface{} {
33
+func (s *Storage) New() runtime.Object {
34 34
 	return &api.Template{}
35 35
 }
36 36
 
37
-func (s *Storage) Delete(id string) (<-chan interface{}, error) {
38
-	return apiserver.MakeAsync(func() (interface{}, error) {
37
+func (s *Storage) Delete(id string) (<-chan runtime.Object, error) {
38
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
39 39
 		return nil, errors.New("template.Storage.Delete() is not implemented.")
40 40
 	}), nil
41 41
 }
42 42
 
43
-func (s *Storage) Update(minion interface{}) (<-chan interface{}, error) {
43
+func (s *Storage) Update(minion runtime.Object) (<-chan runtime.Object, error) {
44 44
 	return nil, errors.New("template.Storage.Update() is not implemented.")
45 45
 }
46 46
 
47
-func (s *Storage) Create(obj interface{}) (<-chan interface{}, error) {
47
+func (s *Storage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
48 48
 	template, ok := obj.(*api.Template)
49 49
 	if !ok {
50 50
 		return nil, errors.New("Not a template config.")
... ...
@@ -52,7 +53,7 @@ func (s *Storage) Create(obj interface{}) (<-chan interface{}, error) {
52 52
 	if errs := validation.ValidateTemplate(template); len(errs) > 0 {
53 53
 		return nil, errors.New(fmt.Sprintf("Invalid template config: %#v", errs))
54 54
 	}
55
-	return apiserver.MakeAsync(func() (interface{}, error) {
55
+	return apiserver.MakeAsync(func() (runtime.Object, error) {
56 56
 		generators := map[string]Generator{
57 57
 			"expression": NewExpressionValueGenerator(rand.New(rand.NewSource(time.Now().UnixNano()))),
58 58
 		}
... ...
@@ -91,10 +91,10 @@ func (p *TemplateProcessor) SubstituteParameters(t *api.Template) error {
91 91
 		switch obj := item.Object.(type) {
92 92
 		case *kubeapi.ReplicationController:
93 93
 			p.substituteParametersInManifest(&obj.DesiredState.PodTemplate.DesiredState.Manifest, paramMap)
94
-			t.Items[i] = runtime.Object{Object: *obj}
94
+			t.Items[i] = runtime.EmbeddedObject{Object: obj}
95 95
 		case *kubeapi.Pod:
96 96
 			p.substituteParametersInManifest(&obj.DesiredState.Manifest, paramMap)
97
-			t.Items[i] = runtime.Object{Object: *obj}
97
+			t.Items[i] = runtime.EmbeddedObject{Object: obj}
98 98
 		default:
99 99
 			glog.V(1).Infof("Parameter substitution not implemented for resource '%T'.", obj)
100 100
 		}