mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Make runtime less global for Codec
* Make Codec separate from Scheme * Move EncodeOrDie off Scheme to take a Codec * Make Copy work without a Codec * Create a "latest" package that imports all versions and sets global defaults for "most recent encoding" * v1beta1 is the current "latest", v1beta2 exists * Kill DefaultCodec, replace it with "latest.Codec" * This updates the client and etcd to store the latest known version * EmbeddedObject is per schema and per package now * Move runtime.DefaultScheme to api.Scheme * Split out WatchEvent since it's not an API object today, treat it like a special object in api * Kill DefaultResourceVersioner, instead place it on "latest" (as the package that understands all packages) * Move objDiff to runtime.ObjectDiff
This commit is contained in:
		@@ -29,6 +29,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
 | 
			
		||||
@@ -206,7 +207,7 @@ func runAtomicPutTest(c *client.Client) {
 | 
			
		||||
	var svc api.Service
 | 
			
		||||
	err := c.Post().Path("services").Body(
 | 
			
		||||
		&api.Service{
 | 
			
		||||
			JSONBase: api.JSONBase{ID: "atomicservice", APIVersion: "v1beta1"},
 | 
			
		||||
			JSONBase: api.JSONBase{ID: "atomicservice", APIVersion: latest.Version},
 | 
			
		||||
			Port:     12345,
 | 
			
		||||
			Labels: map[string]string{
 | 
			
		||||
				"name": "atomicService",
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubecfg"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								pkg/api/conversion.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								pkg/api/conversion.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Codec is the identity codec for this package - it can only convert itself
 | 
			
		||||
// to itself.
 | 
			
		||||
var Codec = runtime.CodecFor(Scheme, "")
 | 
			
		||||
 | 
			
		||||
// EmbeddedObject implements a Codec specific version of an
 | 
			
		||||
// embedded object.
 | 
			
		||||
type EmbeddedObject struct {
 | 
			
		||||
	runtime.Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSON implements the json.Unmarshaler interface.
 | 
			
		||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
 | 
			
		||||
	obj, err := runtime.CodecUnmarshalJSON(Codec, b)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON implements the json.Marshaler interface.
 | 
			
		||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return runtime.CodecMarshalJSON(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetYAML implements the yaml.Setter interface.
 | 
			
		||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
 | 
			
		||||
	obj, ok := runtime.CodecSetYAML(Codec, tag, value)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetYAML implements the yaml.Getter interface.
 | 
			
		||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
 | 
			
		||||
	return runtime.CodecGetYAML(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								pkg/api/latest/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								pkg/api/latest/doc.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// Package latest defines the default output serializations that code should
 | 
			
		||||
// use and imports the required schemas.  It also ensures all previously known
 | 
			
		||||
// and supported API versions are available for conversion.
 | 
			
		||||
package latest
 | 
			
		||||
							
								
								
									
										37
									
								
								pkg/api/latest/latest.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								pkg/api/latest/latest.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package latest
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Version is the string that represents the current external default version
 | 
			
		||||
var Version = "v1beta1"
 | 
			
		||||
 | 
			
		||||
// Codec is the default codec for serializing output that should use
 | 
			
		||||
// the latest supported version.  Use this Codec when writing to
 | 
			
		||||
// disk, a data store that is not dynamically versioned, or in tests.
 | 
			
		||||
// This codec can decode any object that Kubernetes is aware of.
 | 
			
		||||
var Codec = v1beta1.Codec
 | 
			
		||||
 | 
			
		||||
// ResourceVersioner describes a default versioner that can handle all types
 | 
			
		||||
// of versioning.
 | 
			
		||||
// TODO: when versioning changes, make this part of each API definition.
 | 
			
		||||
var ResourceVersioner = runtime.NewJSONBaseResourceVersioner()
 | 
			
		||||
							
								
								
									
										146
									
								
								pkg/api/latest/latest_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								pkg/api/latest/latest_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package latest
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	internal "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/fsouza/go-dockerclient"
 | 
			
		||||
	"github.com/google/gofuzz"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// apiObjectFuzzer can randomly populate api objects.
 | 
			
		||||
var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
 | 
			
		||||
	func(j *internal.JSONBase, c fuzz.Continue) {
 | 
			
		||||
		// We have to customize the randomization of JSONBases because their
 | 
			
		||||
		// APIVersion and Kind must remain blank in memory.
 | 
			
		||||
		j.APIVersion = ""
 | 
			
		||||
		j.Kind = ""
 | 
			
		||||
		j.ID = c.RandString()
 | 
			
		||||
		// TODO: Fix JSON/YAML packages and/or write custom encoding
 | 
			
		||||
		// for uint64's. Somehow the LS *byte* of this is lost, but
 | 
			
		||||
		// only when all 8 bytes are set.
 | 
			
		||||
		j.ResourceVersion = c.RandUint64() >> 8
 | 
			
		||||
		j.SelfLink = c.RandString()
 | 
			
		||||
 | 
			
		||||
		var sec, nsec int64
 | 
			
		||||
		c.Fuzz(&sec)
 | 
			
		||||
		c.Fuzz(&nsec)
 | 
			
		||||
		j.CreationTimestamp = util.Unix(sec, nsec).Rfc3339Copy()
 | 
			
		||||
	},
 | 
			
		||||
	func(intstr *util.IntOrString, c fuzz.Continue) {
 | 
			
		||||
		// util.IntOrString will panic if its kind is set wrong.
 | 
			
		||||
		if c.RandBool() {
 | 
			
		||||
			intstr.Kind = util.IntstrInt
 | 
			
		||||
			intstr.IntVal = int(c.RandUint64())
 | 
			
		||||
			intstr.StrVal = ""
 | 
			
		||||
		} else {
 | 
			
		||||
			intstr.Kind = util.IntstrString
 | 
			
		||||
			intstr.IntVal = 0
 | 
			
		||||
			intstr.StrVal = c.RandString()
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	func(u64 *uint64, c fuzz.Continue) {
 | 
			
		||||
		// TODO: uint64's are NOT handled right.
 | 
			
		||||
		*u64 = c.RandUint64() >> 8
 | 
			
		||||
	},
 | 
			
		||||
	func(pb map[docker.Port][]docker.PortBinding, c fuzz.Continue) {
 | 
			
		||||
		// This is necessary because keys with nil values get omitted.
 | 
			
		||||
		// TODO: Is this a bug?
 | 
			
		||||
		pb[docker.Port(c.RandString())] = []docker.PortBinding{
 | 
			
		||||
			{c.RandString(), c.RandString()},
 | 
			
		||||
			{c.RandString(), c.RandString()},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	func(pm map[string]docker.PortMapping, c fuzz.Continue) {
 | 
			
		||||
		// This is necessary because keys with nil values get omitted.
 | 
			
		||||
		// TODO: Is this a bug?
 | 
			
		||||
		pm[c.RandString()] = docker.PortMapping{
 | 
			
		||||
			c.RandString(): c.RandString(),
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestInternalRoundTrip(t *testing.T) {
 | 
			
		||||
	latest := "v1beta2"
 | 
			
		||||
 | 
			
		||||
	for k, _ := range internal.Scheme.KnownTypes("") {
 | 
			
		||||
		obj, err := internal.Scheme.New("", k)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%s: unexpected error: %v", k, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		apiObjectFuzzer.Fuzz(obj)
 | 
			
		||||
 | 
			
		||||
		newer, err := internal.Scheme.New(latest, k)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%s: unexpected error: %v", k, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := internal.Scheme.Convert(obj, newer); err != nil {
 | 
			
		||||
			t.Errorf("unable to convert %#v to %#v: %v", obj, newer, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		actual, err := internal.Scheme.New("", k)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%s: unexpected error: %v", k, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := internal.Scheme.Convert(newer, actual); err != nil {
 | 
			
		||||
			t.Errorf("unable to convert %#v to %#v: %v", newer, actual, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !reflect.DeepEqual(obj, actual) {
 | 
			
		||||
			t.Errorf("%s: diff %s", k, runtime.ObjectDiff(obj, actual))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestResourceVersioner(t *testing.T) {
 | 
			
		||||
	pod := internal.Pod{JSONBase: internal.JSONBase{ResourceVersion: 10}}
 | 
			
		||||
	version, err := ResourceVersioner.ResourceVersion(&pod)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if version != 10 {
 | 
			
		||||
		t.Errorf("unexpected version %d", version)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCodec(t *testing.T) {
 | 
			
		||||
	pod := internal.Pod{}
 | 
			
		||||
	data, err := Codec.Encode(&pod)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	other := internal.Pod{}
 | 
			
		||||
	if err := json.Unmarshal(data, &other); err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if other.APIVersion != Version || other.Kind != "Pod" {
 | 
			
		||||
		t.Errorf("unexpected unmarshalled object %#v", other)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -20,8 +20,10 @@ import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var Scheme = runtime.NewScheme()
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypes("",
 | 
			
		||||
	Scheme.AddKnownTypes("",
 | 
			
		||||
		&PodList{},
 | 
			
		||||
		&Pod{},
 | 
			
		||||
		&ReplicationControllerList{},
 | 
			
		||||
 
 | 
			
		||||
@@ -17,14 +17,14 @@ limitations under the License.
 | 
			
		||||
package api_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/fsouza/go-dockerclient"
 | 
			
		||||
@@ -105,27 +105,7 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
 | 
			
		||||
	},
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func objDiff(a, b runtime.Object) string {
 | 
			
		||||
	ab, err := json.Marshal(a)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic("a")
 | 
			
		||||
	}
 | 
			
		||||
	bb, err := json.Marshal(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic("b")
 | 
			
		||||
	}
 | 
			
		||||
	return util.StringDiff(string(ab), string(bb))
 | 
			
		||||
 | 
			
		||||
	// An alternate diff attempt, in case json isn't showing you
 | 
			
		||||
	// the difference. (reflect.DeepEqual makes a distinction between
 | 
			
		||||
	// nil and empty slices, for example.)
 | 
			
		||||
	return util.StringDiff(
 | 
			
		||||
		fmt.Sprintf("%#v", a),
 | 
			
		||||
		fmt.Sprintf("%#v", b),
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func runTest(t *testing.T, source runtime.Object) {
 | 
			
		||||
func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) {
 | 
			
		||||
	name := reflect.TypeOf(source).Elem().Name()
 | 
			
		||||
	apiObjectFuzzer.Fuzz(source)
 | 
			
		||||
	j, err := runtime.FindJSONBase(source)
 | 
			
		||||
@@ -135,30 +115,30 @@ func runTest(t *testing.T, source runtime.Object) {
 | 
			
		||||
	j.SetKind("")
 | 
			
		||||
	j.SetAPIVersion("")
 | 
			
		||||
 | 
			
		||||
	data, err := latest.Codec.Encode(source)
 | 
			
		||||
	data, err := codec.Encode(source)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("%v: %v (%#v)", name, err, source)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obj2, err := latest.Codec.Decode(data)
 | 
			
		||||
	obj2, err := codec.Decode(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("%v: %v", name, err)
 | 
			
		||||
		return
 | 
			
		||||
	} else {
 | 
			
		||||
		if !reflect.DeepEqual(source, obj2) {
 | 
			
		||||
			t.Errorf("1: %v: diff: %v", name, objDiff(source, obj2))
 | 
			
		||||
			t.Errorf("1: %v: diff: %v", name, runtime.ObjectDiff(source, obj2))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface().(runtime.Object)
 | 
			
		||||
	err = latest.Codec.DecodeInto(data, obj3)
 | 
			
		||||
	err = codec.DecodeInto(data, obj3)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("2: %v: %v", name, err)
 | 
			
		||||
		return
 | 
			
		||||
	} else {
 | 
			
		||||
		if !reflect.DeepEqual(source, obj3) {
 | 
			
		||||
			t.Errorf("3: %v: diff: %v", name, objDiff(source, obj3))
 | 
			
		||||
			t.Errorf("3: %v: diff: %v", name, runtime.ObjectDiff(source, obj3))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -184,7 +164,8 @@ func TestTypes(t *testing.T) {
 | 
			
		||||
	for _, item := range table {
 | 
			
		||||
		// Try a few times, since runTest uses random values.
 | 
			
		||||
		for i := 0; i < *fuzzIters; i++ {
 | 
			
		||||
			runTest(t, item)
 | 
			
		||||
			runTest(t, v1beta1.Codec, item)
 | 
			
		||||
			runTest(t, v1beta2.Codec, item)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,7 @@ limitations under the License.
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
	"github.com/fsouza/go-dockerclient"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -623,13 +621,3 @@ type ServerOpList struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*ServerOpList) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
// WatchEvent objects are streamed from the api server in response to a watch request.
 | 
			
		||||
type WatchEvent struct {
 | 
			
		||||
	// The type of the watch event; added, modified, or deleted.
 | 
			
		||||
	Type watch.EventType
 | 
			
		||||
 | 
			
		||||
	// For added or modified objects, this is the new object; for deleted objects,
 | 
			
		||||
	// it's the state of the object immediately prior to its deletion.
 | 
			
		||||
	Object runtime.EmbeddedObject
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,14 +17,13 @@ limitations under the License.
 | 
			
		||||
package v1beta1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	// Alias this so it can be easily changed when we cut the next version.
 | 
			
		||||
	newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	runtime.DefaultScheme.AddConversionFuncs(
 | 
			
		||||
	newer.Scheme.AddConversionFuncs(
 | 
			
		||||
		// EnvVar's Key is deprecated in favor of Name.
 | 
			
		||||
		func(in *newer.EnvVar, out *EnvVar, s conversion.Scope) error {
 | 
			
		||||
			out.Value = in.Value
 | 
			
		||||
@@ -81,3 +80,33 @@ func init() {
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EmbeddedObject implements a Codec specific version of an
 | 
			
		||||
// embedded object.
 | 
			
		||||
type EmbeddedObject struct {
 | 
			
		||||
	runtime.Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSON implements the json.Unmarshaler interface.
 | 
			
		||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
 | 
			
		||||
	obj, err := runtime.CodecUnmarshalJSON(Codec, b)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON implements the json.Marshaler interface.
 | 
			
		||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return runtime.CodecMarshalJSON(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetYAML implements the yaml.Setter interface.
 | 
			
		||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
 | 
			
		||||
	obj, ok := runtime.CodecSetYAML(Codec, tag, value)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetYAML implements the yaml.Getter interface.
 | 
			
		||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
 | 
			
		||||
	return runtime.CodecGetYAML(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,9 @@ import (
 | 
			
		||||
 | 
			
		||||
	newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var Convert = runtime.DefaultScheme.Convert
 | 
			
		||||
var Convert = newer.Scheme.Convert
 | 
			
		||||
 | 
			
		||||
func TestEnvConversion(t *testing.T) {
 | 
			
		||||
	nonCanonical := []v1beta1.EnvVar{
 | 
			
		||||
 
 | 
			
		||||
@@ -17,11 +17,15 @@ limitations under the License.
 | 
			
		||||
package v1beta1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Codec encodes internal objects to the v1beta1 scheme
 | 
			
		||||
var Codec = runtime.CodecFor(api.Scheme, "v1beta1")
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypes("v1beta1",
 | 
			
		||||
	api.Scheme.AddKnownTypes("v1beta1",
 | 
			
		||||
		&PodList{},
 | 
			
		||||
		&Pod{},
 | 
			
		||||
		&ReplicationControllerList{},
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,7 @@ limitations under the License.
 | 
			
		||||
package v1beta1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
	"github.com/fsouza/go-dockerclient"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -625,13 +623,3 @@ type ServerOpList struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*ServerOpList) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
// WatchEvent objects are streamed from the api server in response to a watch request.
 | 
			
		||||
type WatchEvent struct {
 | 
			
		||||
	// The type of the watch event; added, modified, or deleted.
 | 
			
		||||
	Type watch.EventType
 | 
			
		||||
 | 
			
		||||
	// For added or modified objects, this is the new object; for deleted objects,
 | 
			
		||||
	// it's the state of the object immediately prior to its deletion.
 | 
			
		||||
	Object runtime.EmbeddedObject
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,11 +17,67 @@ limitations under the License.
 | 
			
		||||
package v1beta2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	runtime.DefaultScheme.AddConversionFuncs()
 | 
			
		||||
	newer.Scheme.AddConversionFuncs(
 | 
			
		||||
		// EnvVar's Key is deprecated in favor of Name.
 | 
			
		||||
		func(in *newer.EnvVar, out *EnvVar, s conversion.Scope) error {
 | 
			
		||||
			out.Value = in.Value
 | 
			
		||||
			out.Key = in.Name
 | 
			
		||||
			out.Name = in.Name
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
		func(in *EnvVar, out *newer.EnvVar, s conversion.Scope) error {
 | 
			
		||||
			out.Value = in.Value
 | 
			
		||||
			if in.Name != "" {
 | 
			
		||||
				out.Name = in.Name
 | 
			
		||||
			} else {
 | 
			
		||||
				out.Name = in.Key
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// Path & MountType are deprecated.
 | 
			
		||||
		func(in *newer.VolumeMount, out *VolumeMount, s conversion.Scope) error {
 | 
			
		||||
			out.Name = in.Name
 | 
			
		||||
			out.ReadOnly = in.ReadOnly
 | 
			
		||||
			out.MountPath = in.MountPath
 | 
			
		||||
			out.Path = in.MountPath
 | 
			
		||||
			out.MountType = "" // MountType is ignored.
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
		func(in *VolumeMount, out *newer.VolumeMount, s conversion.Scope) error {
 | 
			
		||||
			out.Name = in.Name
 | 
			
		||||
			out.ReadOnly = in.ReadOnly
 | 
			
		||||
			if in.MountPath == "" {
 | 
			
		||||
				out.MountPath = in.Path
 | 
			
		||||
			} else {
 | 
			
		||||
				out.MountPath = in.MountPath
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// MinionList.Items had a wrong name in v1beta1
 | 
			
		||||
		func(in *newer.MinionList, out *MinionList, s conversion.Scope) error {
 | 
			
		||||
			s.Convert(&in.JSONBase, &out.JSONBase, 0)
 | 
			
		||||
			s.Convert(&in.Items, &out.Items, 0)
 | 
			
		||||
			out.Minions = out.Items
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
		func(in *MinionList, out *newer.MinionList, s conversion.Scope) error {
 | 
			
		||||
			s.Convert(&in.JSONBase, &out.JSONBase, 0)
 | 
			
		||||
			if len(in.Items) == 0 {
 | 
			
		||||
				s.Convert(&in.Minions, &out.Items, 0)
 | 
			
		||||
			} else {
 | 
			
		||||
				s.Convert(&in.Items, &out.Items, 0)
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EmbeddedObject implements a Codec specific version of an
 | 
			
		||||
 
 | 
			
		||||
@@ -17,14 +17,15 @@ limitations under the License.
 | 
			
		||||
package v1beta2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Codec encodes runtime objects to the v1beta2 scheme
 | 
			
		||||
var Codec = runtime.CodecFor(runtime.DefaultScheme, "v1beta2")
 | 
			
		||||
// Codec encodes internal objects to the v1beta2 scheme
 | 
			
		||||
var Codec = runtime.CodecFor(api.Scheme, "v1beta2")
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypes("v1beta2",
 | 
			
		||||
	api.Scheme.AddKnownTypes("v1beta2",
 | 
			
		||||
		&PodList{},
 | 
			
		||||
		&Pod{},
 | 
			
		||||
		&ReplicationControllerList{},
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,7 @@ limitations under the License.
 | 
			
		||||
package v1beta2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
	"github.com/fsouza/go-dockerclient"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -55,8 +53,8 @@ type ContainerManifest struct {
 | 
			
		||||
	// Required: This must be a DNS_SUBDOMAIN.
 | 
			
		||||
	// TODO: ID on Manifest is deprecated and will be removed in the future.
 | 
			
		||||
	ID string `yaml:"id" json:"id"`
 | 
			
		||||
	// TODO: UUID on Manifext is deprecated in the future once we are done
 | 
			
		||||
	// with the API refactory. It is required for now to determine the instance
 | 
			
		||||
	// TODO: UUID on Manifest is deprecated in the future once we are done
 | 
			
		||||
	// with the API refactoring. It is required for now to determine the instance
 | 
			
		||||
	// of a Pod.
 | 
			
		||||
	UUID          string        `yaml:"uuid,omitempty" json:"uuid,omitempty"`
 | 
			
		||||
	Volumes       []Volume      `yaml:"volumes" json:"volumes"`
 | 
			
		||||
@@ -166,7 +164,6 @@ type ExecAction struct {
 | 
			
		||||
	// command  is root ('/') in the container's filesystem.  The command is simply exec'd, it is
 | 
			
		||||
	// not run inside a shell, so traditional shell instructions ('|', etc) won't work.  To use
 | 
			
		||||
	// a shell, you need to explicitly call out to that shell.
 | 
			
		||||
	// A return code of zero is treated as 'Healthy', non-zero is 'Unhealthy'
 | 
			
		||||
	Command []string `yaml:"command,omitempty" json:"command,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -210,7 +207,6 @@ type Container struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handler defines a specific action that should be taken
 | 
			
		||||
// TODO: merge this with liveness probing?
 | 
			
		||||
// TODO: pass structured data to these actions, and document that data here.
 | 
			
		||||
type Handler struct {
 | 
			
		||||
	// One and only one of the following should be specified.
 | 
			
		||||
@@ -252,8 +248,6 @@ type JSONBase struct {
 | 
			
		||||
	APIVersion        string    `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*JSONBase) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
// PodStatus represents a status of a pod.
 | 
			
		||||
type PodStatus string
 | 
			
		||||
 | 
			
		||||
@@ -303,18 +297,19 @@ type ContainerStatus struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PodInfo contains one entry for every container with available info.
 | 
			
		||||
// TODO(dchen1107): Replace docker.Container below with ContainerStatus defined above.
 | 
			
		||||
type PodInfo map[string]docker.Container
 | 
			
		||||
 | 
			
		||||
type RestartPolicyAlways struct{}
 | 
			
		||||
 | 
			
		||||
// TODO(dchen1107): Define what kinds of failures should restart
 | 
			
		||||
// TODO(dchen1107): Define what kinds of failures should restart.
 | 
			
		||||
// TODO(dchen1107): Decide whether to support policy knobs, and, if so, which ones.
 | 
			
		||||
type RestartPolicyOnFailure struct{}
 | 
			
		||||
 | 
			
		||||
type RestartPolicyNever struct{}
 | 
			
		||||
 | 
			
		||||
type RestartPolicy struct {
 | 
			
		||||
	// Only one of the following restart policy may be specified.
 | 
			
		||||
	// Only one of the following restart policies may be specified.
 | 
			
		||||
	// If none of the following policies is specified, the default one
 | 
			
		||||
	// is RestartPolicyAlways.
 | 
			
		||||
	Always    *RestartPolicyAlways    `json:"always,omitempty" yaml:"always,omitempty"`
 | 
			
		||||
@@ -333,9 +328,9 @@ type PodState struct {
 | 
			
		||||
	// The key of this map is the *name* of the container within the manifest; it has one
 | 
			
		||||
	// entry per container in the manifest. The value of this map is currently the output
 | 
			
		||||
	// of `docker inspect`. This output format is *not* final and should not be relied
 | 
			
		||||
	// upon. To allow marshalling/unmarshalling, we copied the client's structs and added
 | 
			
		||||
	// json/yaml tags.
 | 
			
		||||
	// TODO: Make real decisions about what our info should look like.
 | 
			
		||||
	// upon.
 | 
			
		||||
	// TODO: Make real decisions about what our info should look like. Re-enable fuzz test
 | 
			
		||||
	// when we have done this.
 | 
			
		||||
	Info PodInfo `json:"info,omitempty" yaml:"info,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -550,14 +545,14 @@ const (
 | 
			
		||||
	//                   resource.
 | 
			
		||||
	//   "id"   string - the identifier of the missing resource
 | 
			
		||||
	// Status code 404
 | 
			
		||||
	StatusReasonNotFound StatusReason = "notFound"
 | 
			
		||||
	StatusReasonNotFound StatusReason = "not_found"
 | 
			
		||||
 | 
			
		||||
	// StatusReasonAlreadyExists means the resource you are creating already exists.
 | 
			
		||||
	// Details (optional):
 | 
			
		||||
	//   "kind" string - the kind attribute of the conflicting resource
 | 
			
		||||
	//   "id"   string - the identifier of the conflicting resource
 | 
			
		||||
	// Status code 409
 | 
			
		||||
	StatusReasonAlreadyExists StatusReason = "alreadyExists"
 | 
			
		||||
	StatusReasonAlreadyExists StatusReason = "already_exists"
 | 
			
		||||
 | 
			
		||||
	// StatusReasonConflict means the requested update operation cannot be completed
 | 
			
		||||
	// due to a conflict in the operation. The client may need to alter the request.
 | 
			
		||||
@@ -565,6 +560,19 @@ const (
 | 
			
		||||
	// conflict.
 | 
			
		||||
	// Status code 409
 | 
			
		||||
	StatusReasonConflict StatusReason = "conflict"
 | 
			
		||||
 | 
			
		||||
	// StatusReasonInvalid means the requested create or update operation cannot be
 | 
			
		||||
	// completed due to invalid data provided as part of the request. The client may
 | 
			
		||||
	// need to alter the request. When set, the client may use the StatusDetails
 | 
			
		||||
	// message field as a summary of the issues encountered.
 | 
			
		||||
	// Details (optional):
 | 
			
		||||
	//   "kind" string - the kind attribute of the invalid resource
 | 
			
		||||
	//   "id"   string - the identifier of the invalid resource
 | 
			
		||||
	//   "causes"      - one or more StatusCause entries indicating the data in the
 | 
			
		||||
	//                   provided resource that was invalid.  The code, message, and
 | 
			
		||||
	//                   field attributes will be set.
 | 
			
		||||
	// Status code 422
 | 
			
		||||
	StatusReasonInvalid StatusReason = "invalid"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// StatusCause provides more information about an api.Status failure, including
 | 
			
		||||
@@ -625,13 +633,3 @@ type ServerOpList struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*ServerOpList) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
// WatchEvent objects are streamed from the api server in response to a watch request.
 | 
			
		||||
type WatchEvent struct {
 | 
			
		||||
	// The type of the watch event; added, modified, or deleted.
 | 
			
		||||
	Type watch.EventType
 | 
			
		||||
 | 
			
		||||
	// For added or modified objects, this is the new object; for deleted objects,
 | 
			
		||||
	// it's the state of the object immediately prior to its deletion.
 | 
			
		||||
	Object runtime.EmbeddedObject
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,12 +14,10 @@ See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package v1beta1
 | 
			
		||||
package v1beta3
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
	"github.com/fsouza/go-dockerclient"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -55,8 +53,8 @@ type ContainerManifest struct {
 | 
			
		||||
	// Required: This must be a DNS_SUBDOMAIN.
 | 
			
		||||
	// TODO: ID on Manifest is deprecated and will be removed in the future.
 | 
			
		||||
	ID string `yaml:"id" json:"id"`
 | 
			
		||||
	// TODO: UUID on Manifext is deprecated in the future once we are done
 | 
			
		||||
	// with the API refactory. It is required for now to determine the instance
 | 
			
		||||
	// TODO: UUID on Manifest is deprecated in the future once we are done
 | 
			
		||||
	// with the API refactoring. It is required for now to determine the instance
 | 
			
		||||
	// of a Pod.
 | 
			
		||||
	UUID          string        `yaml:"uuid,omitempty" json:"uuid,omitempty"`
 | 
			
		||||
	Volumes       []Volume      `yaml:"volumes" json:"volumes"`
 | 
			
		||||
@@ -124,22 +122,13 @@ type VolumeMount struct {
 | 
			
		||||
	// Optional: Defaults to false (read-write).
 | 
			
		||||
	ReadOnly bool `yaml:"readOnly,omitempty" json:"readOnly,omitempty"`
 | 
			
		||||
	// Required.
 | 
			
		||||
	// Exactly one of the following must be set.  If both are set, prefer MountPath.
 | 
			
		||||
	// DEPRECATED: Path will be removed in a future version of the API.
 | 
			
		||||
	MountPath string `yaml:"mountPath,omitempty" json:"mountPath,omitempty"`
 | 
			
		||||
	Path      string `yaml:"path,omitempty" json:"path,omitempty"`
 | 
			
		||||
	// One of: "LOCAL" (local volume) or "HOST" (external mount from the host). Default: LOCAL.
 | 
			
		||||
	// DEPRECATED: MountType will be removed in a future version of the API.
 | 
			
		||||
	MountType string `yaml:"mountType,omitempty" json:"mountType,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnvVar represents an environment variable present in a Container.
 | 
			
		||||
type EnvVar struct {
 | 
			
		||||
	// Required: This must be a C_IDENTIFIER.
 | 
			
		||||
	// Exactly one of the following must be set.  If both are set, prefer Name.
 | 
			
		||||
	// DEPRECATED: EnvVar.Key will be removed in a future version of the API.
 | 
			
		||||
	Name string `yaml:"name" json:"name"`
 | 
			
		||||
	Key  string `yaml:"key,omitempty" json:"key,omitempty"`
 | 
			
		||||
	// Optional: defaults to "".
 | 
			
		||||
	Value string `yaml:"value,omitempty" json:"value,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
@@ -166,7 +155,6 @@ type ExecAction struct {
 | 
			
		||||
	// command  is root ('/') in the container's filesystem.  The command is simply exec'd, it is
 | 
			
		||||
	// not run inside a shell, so traditional shell instructions ('|', etc) won't work.  To use
 | 
			
		||||
	// a shell, you need to explicitly call out to that shell.
 | 
			
		||||
	// A return code of zero is treated as 'Healthy', non-zero is 'Unhealthy'
 | 
			
		||||
	Command []string `yaml:"command,omitempty" json:"command,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -210,7 +198,6 @@ type Container struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handler defines a specific action that should be taken
 | 
			
		||||
// TODO: merge this with liveness probing?
 | 
			
		||||
// TODO: pass structured data to these actions, and document that data here.
 | 
			
		||||
type Handler struct {
 | 
			
		||||
	// One and only one of the following should be specified.
 | 
			
		||||
@@ -252,8 +239,6 @@ type JSONBase struct {
 | 
			
		||||
	APIVersion        string    `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*JSONBase) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
// PodStatus represents a status of a pod.
 | 
			
		||||
type PodStatus string
 | 
			
		||||
 | 
			
		||||
@@ -303,18 +288,19 @@ type ContainerStatus struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PodInfo contains one entry for every container with available info.
 | 
			
		||||
// TODO(dchen1107): Replace docker.Container below with ContainerStatus defined above.
 | 
			
		||||
type PodInfo map[string]docker.Container
 | 
			
		||||
 | 
			
		||||
type RestartPolicyAlways struct{}
 | 
			
		||||
 | 
			
		||||
// TODO(dchen1107): Define what kinds of failures should restart
 | 
			
		||||
// TODO(dchen1107): Define what kinds of failures should restart.
 | 
			
		||||
// TODO(dchen1107): Decide whether to support policy knobs, and, if so, which ones.
 | 
			
		||||
type RestartPolicyOnFailure struct{}
 | 
			
		||||
 | 
			
		||||
type RestartPolicyNever struct{}
 | 
			
		||||
 | 
			
		||||
type RestartPolicy struct {
 | 
			
		||||
	// Only one of the following restart policy may be specified.
 | 
			
		||||
	// Only one of the following restart policies may be specified.
 | 
			
		||||
	// If none of the following policies is specified, the default one
 | 
			
		||||
	// is RestartPolicyAlways.
 | 
			
		||||
	Always    *RestartPolicyAlways    `json:"always,omitempty" yaml:"always,omitempty"`
 | 
			
		||||
@@ -333,9 +319,9 @@ type PodState struct {
 | 
			
		||||
	// The key of this map is the *name* of the container within the manifest; it has one
 | 
			
		||||
	// entry per container in the manifest. The value of this map is currently the output
 | 
			
		||||
	// of `docker inspect`. This output format is *not* final and should not be relied
 | 
			
		||||
	// upon. To allow marshalling/unmarshalling, we copied the client's structs and added
 | 
			
		||||
	// json/yaml tags.
 | 
			
		||||
	// TODO: Make real decisions about what our info should look like.
 | 
			
		||||
	// upon.
 | 
			
		||||
	// TODO: Make real decisions about what our info should look like. Re-enable fuzz test
 | 
			
		||||
	// when we have done this.
 | 
			
		||||
	Info PodInfo `json:"info,omitempty" yaml:"info,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -451,10 +437,7 @@ func (*Minion) IsAnAPIObject() {}
 | 
			
		||||
// MinionList is a list of minions.
 | 
			
		||||
type MinionList struct {
 | 
			
		||||
	JSONBase `json:",inline" yaml:",inline"`
 | 
			
		||||
	// DEPRECATED: the below Minions is due to a naming mistake and
 | 
			
		||||
	// will be replaced with Items in the future.
 | 
			
		||||
	Minions []Minion `json:"minions,omitempty" yaml:"minions,omitempty"`
 | 
			
		||||
	Items   []Minion `json:"items,omitempty" yaml:"items,omitempty"`
 | 
			
		||||
	Items    []Minion `json:"items,omitempty" yaml:"items,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*MinionList) IsAnAPIObject() {}
 | 
			
		||||
@@ -550,14 +533,14 @@ const (
 | 
			
		||||
	//                   resource.
 | 
			
		||||
	//   "id"   string - the identifier of the missing resource
 | 
			
		||||
	// Status code 404
 | 
			
		||||
	StatusReasonNotFound StatusReason = "notFound"
 | 
			
		||||
	StatusReasonNotFound StatusReason = "not_found"
 | 
			
		||||
 | 
			
		||||
	// StatusReasonAlreadyExists means the resource you are creating already exists.
 | 
			
		||||
	// Details (optional):
 | 
			
		||||
	//   "kind" string - the kind attribute of the conflicting resource
 | 
			
		||||
	//   "id"   string - the identifier of the conflicting resource
 | 
			
		||||
	// Status code 409
 | 
			
		||||
	StatusReasonAlreadyExists StatusReason = "alreadyExists"
 | 
			
		||||
	StatusReasonAlreadyExists StatusReason = "already_exists"
 | 
			
		||||
 | 
			
		||||
	// StatusReasonConflict means the requested update operation cannot be completed
 | 
			
		||||
	// due to a conflict in the operation. The client may need to alter the request.
 | 
			
		||||
@@ -565,6 +548,19 @@ const (
 | 
			
		||||
	// conflict.
 | 
			
		||||
	// Status code 409
 | 
			
		||||
	StatusReasonConflict StatusReason = "conflict"
 | 
			
		||||
 | 
			
		||||
	// StatusReasonInvalid means the requested create or update operation cannot be
 | 
			
		||||
	// completed due to invalid data provided as part of the request. The client may
 | 
			
		||||
	// need to alter the request. When set, the client may use the StatusDetails
 | 
			
		||||
	// message field as a summary of the issues encountered.
 | 
			
		||||
	// Details (optional):
 | 
			
		||||
	//   "kind" string - the kind attribute of the invalid resource
 | 
			
		||||
	//   "id"   string - the identifier of the invalid resource
 | 
			
		||||
	//   "causes"      - one or more StatusCause entries indicating the data in the
 | 
			
		||||
	//                   provided resource that was invalid.  The code, message, and
 | 
			
		||||
	//                   field attributes will be set.
 | 
			
		||||
	// Status code 422
 | 
			
		||||
	StatusReasonInvalid StatusReason = "invalid"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// StatusCause provides more information about an api.Status failure, including
 | 
			
		||||
@@ -625,13 +621,3 @@ type ServerOpList struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*ServerOpList) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
// WatchEvent objects are streamed from the api server in response to a watch request.
 | 
			
		||||
type WatchEvent struct {
 | 
			
		||||
	// The type of the watch event; added, modified, or deleted.
 | 
			
		||||
	Type watch.EventType
 | 
			
		||||
 | 
			
		||||
	// For added or modified objects, this is the new object; for deleted objects,
 | 
			
		||||
	// it's the state of the object immediately prior to its deletion.
 | 
			
		||||
	Object runtime.EmbeddedObject
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								pkg/api/watch.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								pkg/api/watch.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// WatchEvent objects are streamed from the api server in response to a watch request.
 | 
			
		||||
// These are not API objects and are unversioned today.
 | 
			
		||||
type WatchEvent struct {
 | 
			
		||||
	// The type of the watch event; added, modified, or deleted.
 | 
			
		||||
	Type watch.EventType
 | 
			
		||||
 | 
			
		||||
	// For added or modified objects, this is the new object; for deleted objects,
 | 
			
		||||
	// it's the state of the object immediately prior to its deletion.
 | 
			
		||||
	Object EmbeddedObject
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// watchSerialization defines the JSON wire equivalent of watch.Event
 | 
			
		||||
type watchSerialization struct {
 | 
			
		||||
	Type   watch.EventType
 | 
			
		||||
	Object json.RawMessage
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewJSONWatcHEvent returns an object that will serialize to JSON and back
 | 
			
		||||
// to a WatchEvent.
 | 
			
		||||
func NewJSONWatchEvent(codec runtime.Codec, event watch.Event) (interface{}, error) {
 | 
			
		||||
	obj, ok := event.Object.(runtime.Object)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, fmt.Errorf("The event object cannot be safely converted to JSON: %v", reflect.TypeOf(event.Object).Name())
 | 
			
		||||
	}
 | 
			
		||||
	data, err := codec.Encode(obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &watchSerialization{event.Type, json.RawMessage(data)}, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								pkg/api/watch_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkg/api/watch_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestEmbeddedDefaultSerialization(t *testing.T) {
 | 
			
		||||
	expected := WatchEvent{
 | 
			
		||||
		Type:   "foo",
 | 
			
		||||
		Object: EmbeddedObject{&Pod{}},
 | 
			
		||||
	}
 | 
			
		||||
	data, err := json.Marshal(expected)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	actual := WatchEvent{}
 | 
			
		||||
	if err := json.Unmarshal(data, &actual); err != nil {
 | 
			
		||||
		t.Fatalf("Unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !reflect.DeepEqual(actual, expected) {
 | 
			
		||||
		t.Errorf("Expected %#v, Got %#v", expected, actual)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -32,6 +32,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
@@ -46,8 +47,8 @@ func convert(obj runtime.Object) (runtime.Object, error) {
 | 
			
		||||
var codec = latest.Codec
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	latest.Codec.AddKnownTypes("", &Simple{}, &SimpleList{})
 | 
			
		||||
	latest.Codec.AddKnownTypes("v1beta1", &Simple{}, &SimpleList{})
 | 
			
		||||
	api.Scheme.AddKnownTypes("", &Simple{}, &SimpleList{})
 | 
			
		||||
	api.Scheme.AddKnownTypes(latest.Version, &Simple{}, &SimpleList{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Simple struct {
 | 
			
		||||
@@ -95,7 +96,7 @@ func (storage *SimpleRESTStorage) List(labels.Selector) (runtime.Object, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (storage *SimpleRESTStorage) Get(id string) (runtime.Object, error) {
 | 
			
		||||
	return latest.Codec.CopyOrDie(&storage.item), storage.errors["get"]
 | 
			
		||||
	return api.Scheme.CopyOrDie(&storage.item), storage.errors["get"]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (storage *SimpleRESTStorage) Delete(id string) (<-chan runtime.Object, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,7 @@ func (h *WatchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
 | 
			
		||||
		// TODO: This is one watch per connection. We want to multiplex, so that
 | 
			
		||||
		// multiple watches of the same thing don't create two watches downstream.
 | 
			
		||||
		watchServer := &WatchServer{watching}
 | 
			
		||||
		watchServer := &WatchServer{watching, h.codec}
 | 
			
		||||
		if req.Header.Get("Connection") == "Upgrade" && req.Header.Get("Upgrade") == "websocket" {
 | 
			
		||||
			websocket.Handler(watchServer.HandleWS).ServeHTTP(httplog.Unlogged(w), req)
 | 
			
		||||
		} else {
 | 
			
		||||
@@ -89,6 +89,7 @@ func (h *WatchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
// WatchServer serves a watch.Interface over a websocket or vanilla HTTP.
 | 
			
		||||
type WatchServer struct {
 | 
			
		||||
	watching watch.Interface
 | 
			
		||||
	codec    runtime.Codec
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleWS implements a websocket handler.
 | 
			
		||||
@@ -111,15 +112,17 @@ func (w *WatchServer) HandleWS(ws *websocket.Conn) {
 | 
			
		||||
				// End of results.
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			err := websocket.JSON.Send(ws, &api.WatchEvent{
 | 
			
		||||
				Type:   event.Type,
 | 
			
		||||
				Object: runtime.EmbeddedObject{event.Object},
 | 
			
		||||
			})
 | 
			
		||||
			obj, err := api.NewJSONWatchEvent(w.codec, event)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				// Client disconnect.
 | 
			
		||||
				w.watching.Stop()
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			if err := websocket.JSON.Send(ws, obj); err != nil {
 | 
			
		||||
				// Client disconnect.
 | 
			
		||||
				w.watching.Stop()
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -158,15 +161,17 @@ func (self *WatchServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
				// End of results.
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			err := encoder.Encode(&api.WatchEvent{
 | 
			
		||||
				Type:   event.Type,
 | 
			
		||||
				Object: runtime.EmbeddedObject{event.Object},
 | 
			
		||||
			})
 | 
			
		||||
			obj, err := api.NewJSONWatchEvent(self.codec, event)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				// Client disconnect.
 | 
			
		||||
				self.watching.Stop()
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			if err := encoder.Encode(obj); err != nil {
 | 
			
		||||
				// Client disconnect.
 | 
			
		||||
				self.watching.Stop()
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			flusher.Flush()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -114,26 +114,22 @@ func TestWatchHTTP(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	decoder := json.NewDecoder(response.Body)
 | 
			
		||||
 | 
			
		||||
	try := func(action watch.EventType, object runtime.Object) {
 | 
			
		||||
	for i, item := range watchTestTable {
 | 
			
		||||
		// Send
 | 
			
		||||
		simpleStorage.fakeWatch.Action(action, object)
 | 
			
		||||
		simpleStorage.fakeWatch.Action(item.t, item.obj)
 | 
			
		||||
		// Test receive
 | 
			
		||||
		var got api.WatchEvent
 | 
			
		||||
		err := decoder.Decode(&got)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("Unexpected error: %v", err)
 | 
			
		||||
			t.Fatalf("%d: Unexpected error: %v", i, err)
 | 
			
		||||
		}
 | 
			
		||||
		if got.Type != action {
 | 
			
		||||
			t.Errorf("Unexpected type: %v", got.Type)
 | 
			
		||||
		if got.Type != item.t {
 | 
			
		||||
			t.Errorf("%d: Unexpected type: %v", i, got.Type)
 | 
			
		||||
		}
 | 
			
		||||
		if e, a := object, got.Object.Object; !reflect.DeepEqual(e, a) {
 | 
			
		||||
			t.Errorf("Expected %v, got %v", e, a)
 | 
			
		||||
		if e, a := item.obj, got.Object.Object; !reflect.DeepEqual(e, a) {
 | 
			
		||||
			t.Errorf("%d: Expected %v, got %v", i, e, a)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, item := range watchTestTable {
 | 
			
		||||
		try(item.t, item.obj)
 | 
			
		||||
	}
 | 
			
		||||
	simpleStorage.fakeWatch.Stop()
 | 
			
		||||
 | 
			
		||||
	var got api.WatchEvent
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ package client
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
)
 | 
			
		||||
@@ -44,7 +43,7 @@ type Fake struct {
 | 
			
		||||
 | 
			
		||||
func (c *Fake) ListPods(selector labels.Selector) (*api.PodList, error) {
 | 
			
		||||
	c.Actions = append(c.Actions, FakeAction{Action: "list-pods"})
 | 
			
		||||
	return runtime.DefaultScheme.CopyOrDie(&c.Pods).(*api.PodList), nil
 | 
			
		||||
	return api.Scheme.CopyOrDie(&c.Pods).(*api.PodList), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Fake) GetPod(name string) (*api.Pod, error) {
 | 
			
		||||
@@ -74,7 +73,7 @@ func (c *Fake) ListReplicationControllers(selector labels.Selector) (*api.Replic
 | 
			
		||||
 | 
			
		||||
func (c *Fake) GetReplicationController(name string) (*api.ReplicationController, error) {
 | 
			
		||||
	c.Actions = append(c.Actions, FakeAction{Action: "get-controller", Value: name})
 | 
			
		||||
	return runtime.DefaultScheme.CopyOrDie(&c.Ctrl).(*api.ReplicationController), nil
 | 
			
		||||
	return api.Scheme.CopyOrDie(&c.Ctrl).(*api.ReplicationController), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Fake) CreateReplicationController(controller *api.ReplicationController) (*api.ReplicationController, error) {
 | 
			
		||||
@@ -129,7 +128,7 @@ func (c *Fake) WatchServices(label, field labels.Selector, resourceVersion uint6
 | 
			
		||||
 | 
			
		||||
func (c *Fake) ListEndpoints(selector labels.Selector) (*api.EndpointsList, error) {
 | 
			
		||||
	c.Actions = append(c.Actions, FakeAction{Action: "list-endpoints"})
 | 
			
		||||
	return runtime.DefaultScheme.CopyOrDie(&c.EndpointsList).(*api.EndpointsList), c.Err
 | 
			
		||||
	return api.Scheme.CopyOrDie(&c.EndpointsList).(*api.EndpointsList), c.Err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Fake) WatchEndpoints(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -28,9 +28,9 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	cwatch "github.com/GoogleCloudPlatform/kubernetes/pkg/client/watch"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
@@ -269,7 +269,7 @@ func (r *Request) Watch() (watch.Interface, error) {
 | 
			
		||||
	if response.StatusCode != http.StatusOK {
 | 
			
		||||
		return nil, fmt.Errorf("Got status: %v", response.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
	return watch.NewStreamWatcher(tools.NewAPIEventDecoder(response.Body)), nil
 | 
			
		||||
	return watch.NewStreamWatcher(cwatch.NewAPIEventDecoder(response.Body)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Do formats and executes the request. Returns the API object received, or an error.
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
@@ -401,7 +402,13 @@ func TestWatch(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
		encoder := json.NewEncoder(w)
 | 
			
		||||
		for _, item := range table {
 | 
			
		||||
			encoder.Encode(&api.WatchEvent{item.t, runtime.EmbeddedObject{item.obj}})
 | 
			
		||||
			data, err := api.NewJSONWatchEvent(latest.Codec, watch.Event{item.t, item.obj})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
			if err := encoder.Encode(data); err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
			flusher.Flush()
 | 
			
		||||
		}
 | 
			
		||||
	}))
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package tools
 | 
			
		||||
package watch
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
@@ -28,6 +28,8 @@ import (
 | 
			
		||||
 | 
			
		||||
// APIEventDecoder implements the watch.Decoder interface for io.ReadClosers that
 | 
			
		||||
// have contents which consist of a series of api.WatchEvent objects encoded via JSON.
 | 
			
		||||
// It will decode any object which is registered to convert to api.WatchEvent via
 | 
			
		||||
// api.Scheme
 | 
			
		||||
type APIEventDecoder struct {
 | 
			
		||||
	stream  io.ReadCloser
 | 
			
		||||
	decoder *json.Decoder
 | 
			
		||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package tools
 | 
			
		||||
package watch
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
@@ -24,29 +24,37 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type watchSerialization struct {
 | 
			
		||||
	Type   watch.EventType
 | 
			
		||||
	Object json.RawMessage
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDecoder(t *testing.T) {
 | 
			
		||||
	out, in := io.Pipe()
 | 
			
		||||
	encoder := json.NewEncoder(in)
 | 
			
		||||
	decoder := NewAPIEventDecoder(out)
 | 
			
		||||
 | 
			
		||||
	expect := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
	encoder := json.NewEncoder(in)
 | 
			
		||||
	go func() {
 | 
			
		||||
		err := encoder.Encode(api.WatchEvent{watch.Added, runtime.EmbeddedObject{expect}})
 | 
			
		||||
		data, err := v1beta1.Codec.Encode(expect)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("Unexpected error %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if err := encoder.Encode(&watchSerialization{watch.Added, json.RawMessage(data)}); err != nil {
 | 
			
		||||
			t.Errorf("Unexpected error %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		in.Close()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	done := make(chan struct{})
 | 
			
		||||
	go func() {
 | 
			
		||||
		action, got, err := decoder.Decode()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("Unexpected error %v", err)
 | 
			
		||||
			t.Fatalf("Unexpected error %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if e, a := watch.Added, action; e != a {
 | 
			
		||||
			t.Errorf("Expected %v, got %v", e, a)
 | 
			
		||||
@@ -54,17 +62,12 @@ func TestDecoder(t *testing.T) {
 | 
			
		||||
		if e, a := expect, got; !reflect.DeepEqual(e, a) {
 | 
			
		||||
			t.Errorf("Expected %v, got %v", e, a)
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("Exited read")
 | 
			
		||||
		close(done)
 | 
			
		||||
	}()
 | 
			
		||||
	select {
 | 
			
		||||
	case <-done:
 | 
			
		||||
		break
 | 
			
		||||
	case <-time.After(10 * time.Second):
 | 
			
		||||
		t.Error("Timeout")
 | 
			
		||||
	}
 | 
			
		||||
	<-done
 | 
			
		||||
 | 
			
		||||
	done = make(chan struct{})
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		_, _, err := decoder.Decode()
 | 
			
		||||
		if err == nil {
 | 
			
		||||
@@ -72,15 +75,9 @@ func TestDecoder(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
		close(done)
 | 
			
		||||
	}()
 | 
			
		||||
	<-done
 | 
			
		||||
 | 
			
		||||
	decoder.Close()
 | 
			
		||||
 | 
			
		||||
	select {
 | 
			
		||||
	case <-done:
 | 
			
		||||
		break
 | 
			
		||||
	case <-time.After(10 * time.Second):
 | 
			
		||||
		t.Error("Timeout")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDecoder_SourceClose(t *testing.T) {
 | 
			
		||||
@@ -27,6 +27,8 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
@@ -169,7 +171,7 @@ func TestSyncReplicationControllerCreates(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCreateReplica(t *testing.T) {
 | 
			
		||||
	body, _ := latest.Codec.Encode(&api.Pod{})
 | 
			
		||||
	body, _ := v1beta1.Codec.Encode(&api.Pod{})
 | 
			
		||||
	fakeHandler := util.FakeHandler{
 | 
			
		||||
		StatusCode:   200,
 | 
			
		||||
		ResponseBody: string(body),
 | 
			
		||||
@@ -209,7 +211,7 @@ func TestCreateReplica(t *testing.T) {
 | 
			
		||||
	expectedPod := api.Pod{
 | 
			
		||||
		JSONBase: api.JSONBase{
 | 
			
		||||
			Kind:       "Pod",
 | 
			
		||||
			APIVersion: "v1beta1",
 | 
			
		||||
			APIVersion: latest.Version,
 | 
			
		||||
		},
 | 
			
		||||
		Labels:       controllerSpec.DesiredState.PodTemplate.Labels,
 | 
			
		||||
		DesiredState: controllerSpec.DesiredState.PodTemplate.DesiredState,
 | 
			
		||||
@@ -287,12 +289,12 @@ func TestSyncronize(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	fakePodHandler := util.FakeHandler{
 | 
			
		||||
		StatusCode:   200,
 | 
			
		||||
		ResponseBody: "{\"apiVersion\": \"v1beta1\", \"kind\": \"PodList\"}",
 | 
			
		||||
		ResponseBody: "{\"apiVersion\": \"" + latest.Version + "\", \"kind\": \"PodList\"}",
 | 
			
		||||
		T:            t,
 | 
			
		||||
	}
 | 
			
		||||
	fakeControllerHandler := util.FakeHandler{
 | 
			
		||||
		StatusCode: 200,
 | 
			
		||||
		ResponseBody: latest.Codec.EncodeOrDie(&api.ReplicationControllerList{
 | 
			
		||||
		ResponseBody: runtime.EncodeOrDie(latest.Codec, &api.ReplicationControllerList{
 | 
			
		||||
			Items: []api.ReplicationController{
 | 
			
		||||
				controllerSpec1,
 | 
			
		||||
				controllerSpec2,
 | 
			
		||||
 
 | 
			
		||||
@@ -25,14 +25,14 @@ import (
 | 
			
		||||
// Decode converts a YAML or JSON string back into a pointer to an api object.
 | 
			
		||||
// Deduces the type based upon the fields added by the MetaInsertionFactory
 | 
			
		||||
// technique. The object will be converted, if necessary, into the
 | 
			
		||||
// s.InternalVersion type before being returned. Decode will refuse to decode
 | 
			
		||||
// objects without a version, because that's probably an error.
 | 
			
		||||
// s.InternalVersion type before being returned. Decode will not decode
 | 
			
		||||
// objects without version set unless InternalVersion is also "".
 | 
			
		||||
func (s *Scheme) Decode(data []byte) (interface{}, error) {
 | 
			
		||||
	version, kind, err := s.DataVersionAndKind(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if version == "" {
 | 
			
		||||
	if version == "" && s.InternalVersion != "" {
 | 
			
		||||
		return nil, fmt.Errorf("version not set in '%s'", string(data))
 | 
			
		||||
	}
 | 
			
		||||
	obj, err := s.NewObject(version, kind)
 | 
			
		||||
 
 | 
			
		||||
@@ -21,16 +21,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
 | 
			
		||||
func (s *Scheme) EncodeOrDie(obj interface{}) string {
 | 
			
		||||
	bytes, err := s.Encode(obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return string(bytes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encode turns the given api object into an appropriate JSON string.
 | 
			
		||||
// EncodeToVersion turns the given api object into an appropriate JSON string.
 | 
			
		||||
// Obj may be a pointer to a struct, or a struct. If a struct, a copy
 | 
			
		||||
// will be made, therefore it's recommended to pass a pointer to a
 | 
			
		||||
// struct. The type must have been registered.
 | 
			
		||||
@@ -58,11 +49,6 @@ func (s *Scheme) EncodeOrDie(obj interface{}) string {
 | 
			
		||||
// objects, whether they be in our storage layer (e.g., etcd), or in user's
 | 
			
		||||
// config files.
 | 
			
		||||
//
 | 
			
		||||
func (s *Scheme) Encode(obj interface{}) (data []byte, err error) {
 | 
			
		||||
	return s.EncodeToVersion(obj, s.ExternalVersion)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeToVersion is like Encode, but you may choose the version.
 | 
			
		||||
func (s *Scheme) EncodeToVersion(obj interface{}, destVersion string) (data []byte, err error) {
 | 
			
		||||
	obj = maybeCopy(obj)
 | 
			
		||||
	v, _ := enforcePtr(obj) // maybeCopy guarantees a pointer
 | 
			
		||||
 
 | 
			
		||||
@@ -66,9 +66,6 @@ type Scheme struct {
 | 
			
		||||
	// you use "" for the internal version.
 | 
			
		||||
	InternalVersion string
 | 
			
		||||
 | 
			
		||||
	// ExternalVersion is the default external version.
 | 
			
		||||
	ExternalVersion string
 | 
			
		||||
 | 
			
		||||
	// MetaInsertionFactory is used to create an object to store and retrieve
 | 
			
		||||
	// the version and kind information for all objects. The default uses the
 | 
			
		||||
	// keys "version" and "kind" respectively.
 | 
			
		||||
@@ -83,7 +80,6 @@ func NewScheme() *Scheme {
 | 
			
		||||
		typeToKind:           map[reflect.Type]string{},
 | 
			
		||||
		converter:            NewConverter(),
 | 
			
		||||
		InternalVersion:      "",
 | 
			
		||||
		ExternalVersion:      "v1",
 | 
			
		||||
		MetaInsertionFactory: metaInsertion{},
 | 
			
		||||
	}
 | 
			
		||||
	s.converter.NameFunc = s.nameFunc
 | 
			
		||||
@@ -146,6 +142,19 @@ func (s *Scheme) AddKnownTypeWithName(version, kind string, obj interface{}) {
 | 
			
		||||
	s.typeToKind[t] = kind
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// KnownTypes returns an array of the types that are known for a particular version.
 | 
			
		||||
func (s *Scheme) KnownTypes(version string) map[string]reflect.Type {
 | 
			
		||||
	all, ok := s.versionMap[version]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return map[string]reflect.Type{}
 | 
			
		||||
	}
 | 
			
		||||
	types := make(map[string]reflect.Type)
 | 
			
		||||
	for k, v := range all {
 | 
			
		||||
		types[k] = v
 | 
			
		||||
	}
 | 
			
		||||
	return types
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewObject returns a new object of the given version and name,
 | 
			
		||||
// or an error if it hasn't been registered.
 | 
			
		||||
func (s *Scheme) NewObject(versionName, typeName string) (interface{}, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -125,7 +125,6 @@ func GetTestScheme() *Scheme {
 | 
			
		||||
	s.AddKnownTypes("v1", &ExternalInternalSame{})
 | 
			
		||||
	s.AddKnownTypeWithName("v1", "TestType1", &ExternalTestType1{})
 | 
			
		||||
	s.AddKnownTypeWithName("v1", "TestType2", &ExternalTestType2{})
 | 
			
		||||
	s.ExternalVersion = "v1"
 | 
			
		||||
	s.InternalVersion = ""
 | 
			
		||||
	s.MetaInsertionFactory = testMetaInsertionFactory{}
 | 
			
		||||
	return s
 | 
			
		||||
@@ -178,7 +177,7 @@ func runTest(t *testing.T, source interface{}) {
 | 
			
		||||
	TestObjectFuzzer.Fuzz(source)
 | 
			
		||||
 | 
			
		||||
	s := GetTestScheme()
 | 
			
		||||
	data, err := s.Encode(source)
 | 
			
		||||
	data, err := s.EncodeToVersion(source, "v1")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("%v: %v (%#v)", name, err, source)
 | 
			
		||||
		return
 | 
			
		||||
@@ -221,7 +220,7 @@ func TestEncode_NonPtr(t *testing.T) {
 | 
			
		||||
	s := GetTestScheme()
 | 
			
		||||
	tt := TestType1{A: "I'm not a pointer object"}
 | 
			
		||||
	obj := interface{}(tt)
 | 
			
		||||
	data, err := s.Encode(obj)
 | 
			
		||||
	data, err := s.EncodeToVersion(obj, "v1")
 | 
			
		||||
	obj2, err2 := s.Decode(data)
 | 
			
		||||
	if err != nil || err2 != nil {
 | 
			
		||||
		t.Fatalf("Failure: '%v' '%v'", err, err2)
 | 
			
		||||
@@ -238,7 +237,7 @@ func TestEncode_Ptr(t *testing.T) {
 | 
			
		||||
	s := GetTestScheme()
 | 
			
		||||
	tt := &TestType1{A: "I am a pointer object"}
 | 
			
		||||
	obj := interface{}(tt)
 | 
			
		||||
	data, err := s.Encode(obj)
 | 
			
		||||
	data, err := s.EncodeToVersion(obj, "v1")
 | 
			
		||||
	obj2, err2 := s.Decode(data)
 | 
			
		||||
	if err != nil || err2 != nil {
 | 
			
		||||
		t.Fatalf("Failure: '%v' '%v'", err, err2)
 | 
			
		||||
@@ -255,7 +254,6 @@ func TestBadJSONRejection(t *testing.T) {
 | 
			
		||||
	s := GetTestScheme()
 | 
			
		||||
	badJSONs := [][]byte{
 | 
			
		||||
		[]byte(`{"myVersionKey":"v1"}`),                          // Missing kind
 | 
			
		||||
		[]byte(`{"myKindKey":"TestType1"}`),                      // Missing version
 | 
			
		||||
		[]byte(`{"myVersionKey":"v1","myKindKey":"bar"}`),        // Unknown kind
 | 
			
		||||
		[]byte(`{"myVersionKey":"bar","myKindKey":"TestType1"}`), // Unknown version
 | 
			
		||||
	}
 | 
			
		||||
@@ -270,6 +268,23 @@ func TestBadJSONRejection(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBadJSONRejectionForSetInternalVersion(t *testing.T) {
 | 
			
		||||
	s := GetTestScheme()
 | 
			
		||||
	s.InternalVersion = "v1"
 | 
			
		||||
	badJSONs := [][]byte{
 | 
			
		||||
		[]byte(`{"myKindKey":"TestType1"}`), // Missing version
 | 
			
		||||
	}
 | 
			
		||||
	for _, b := range badJSONs {
 | 
			
		||||
		if _, err := s.Decode(b); err == nil {
 | 
			
		||||
			t.Errorf("Did not reject bad json: %s", string(b))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	badJSONKindMismatch := []byte(`{"myVersionKey":"v1","myKindKey":"ExternalInternalSame"}`)
 | 
			
		||||
	if err := s.DecodeInto(badJSONKindMismatch, &TestType1{}); err == nil {
 | 
			
		||||
		t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMetaValues(t *testing.T) {
 | 
			
		||||
	type InternalSimple struct {
 | 
			
		||||
		Version    string `json:"version,omitempty" yaml:"version,omitempty"`
 | 
			
		||||
@@ -283,7 +298,6 @@ func TestMetaValues(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
	s := NewScheme()
 | 
			
		||||
	s.InternalVersion = ""
 | 
			
		||||
	s.ExternalVersion = "externalVersion"
 | 
			
		||||
	s.AddKnownTypeWithName("", "Simple", &InternalSimple{})
 | 
			
		||||
	s.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
 | 
			
		||||
 | 
			
		||||
@@ -373,7 +387,6 @@ func TestMetaValuesUnregisteredConvert(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
	s := NewScheme()
 | 
			
		||||
	s.InternalVersion = ""
 | 
			
		||||
	s.ExternalVersion = "externalVersion"
 | 
			
		||||
	// We deliberately don't register the types.
 | 
			
		||||
 | 
			
		||||
	internalToExternalCalls := 0
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,6 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func validateAction(expectedAction, actualAction client.FakeAction, t *testing.T) {
 | 
			
		||||
@@ -94,7 +93,7 @@ func TestUpdateWithNewImage(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
	validateAction(client.FakeAction{Action: "get-controller", Value: "foo"}, fakeClient.Actions[0], t)
 | 
			
		||||
 | 
			
		||||
	newCtrl := runtime.DefaultScheme.CopyOrDie(&fakeClient.Ctrl).(*api.ReplicationController)
 | 
			
		||||
	newCtrl := api.Scheme.CopyOrDie(&fakeClient.Ctrl).(*api.ReplicationController)
 | 
			
		||||
	newCtrl.DesiredState.PodTemplate.DesiredState.Manifest.Containers[0].Image = "fooImage:2"
 | 
			
		||||
	validateAction(client.FakeAction{Action: "update-controller", Value: newCtrl}, fakeClient.Actions[1], t)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,8 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"gopkg.in/v1/yaml"
 | 
			
		||||
)
 | 
			
		||||
@@ -125,8 +127,9 @@ type TestParseType struct {
 | 
			
		||||
func (*TestParseType) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
func TestParseCustomType(t *testing.T) {
 | 
			
		||||
	latest.Codec.AddKnownTypes("", &TestParseType{})
 | 
			
		||||
	latest.Codec.AddKnownTypes("v1beta1", &TestParseType{})
 | 
			
		||||
	api.Scheme.AddKnownTypes("", &TestParseType{})
 | 
			
		||||
	api.Scheme.AddKnownTypes("v1beta1", &TestParseType{})
 | 
			
		||||
	api.Scheme.AddKnownTypes("v1beta2", &TestParseType{})
 | 
			
		||||
	parser := NewParser(map[string]runtime.Object{
 | 
			
		||||
		"custom": &TestParseType{},
 | 
			
		||||
	})
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,8 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ import (
 | 
			
		||||
	"text/template"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"gopkg.in/v1/yaml"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,8 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
@@ -48,7 +47,7 @@ func NewSourceEtcd(key string, client tools.EtcdClient, updates chan<- interface
 | 
			
		||||
	helper := tools.EtcdHelper{
 | 
			
		||||
		client,
 | 
			
		||||
		latest.Codec,
 | 
			
		||||
		runtime.DefaultResourceVersioner,
 | 
			
		||||
		latest.ResourceVersioner,
 | 
			
		||||
	}
 | 
			
		||||
	source := &SourceEtcd{
 | 
			
		||||
		key:     key,
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
 | 
			
		||||
@@ -136,5 +136,5 @@ func (m *Master) API_v1beta1() (map[string]apiserver.RESTStorage, runtime.Codec)
 | 
			
		||||
	for k, v := range m.storage {
 | 
			
		||||
		storage[k] = v
 | 
			
		||||
	}
 | 
			
		||||
	return storage, runtime.DefaultCodec
 | 
			
		||||
	return storage, v1beta1.Codec
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/coreos/go-etcd/etcd"
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,8 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestNewREST(t *testing.T) {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,10 +26,10 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestListControllersError(t *testing.T) {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	etcderr "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors/etcd"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/constraint"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
@@ -46,7 +47,7 @@ func NewRegistry(client tools.EtcdClient) *Registry {
 | 
			
		||||
		EtcdHelper: tools.EtcdHelper{
 | 
			
		||||
			client,
 | 
			
		||||
			latest.Codec,
 | 
			
		||||
			runtime.DefaultResourceVersioner,
 | 
			
		||||
			latest.ResourceVersioner,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	registry.manifestFactory = &BasicManifestFactory{
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
@@ -41,7 +41,7 @@ func NewTestEtcdRegistry(client tools.EtcdClient) *Registry {
 | 
			
		||||
 | 
			
		||||
func TestEtcdGetPod(t *testing.T) {
 | 
			
		||||
	fakeClient := tools.NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.Set("/registry/pods/foo", latest.Codec.EncodeOrDie(&api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/pods/foo", runtime.EncodeOrDie(latest.Codec, &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	pod, err := registry.GetPod("foo")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -77,7 +77,7 @@ func TestEtcdCreatePod(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		E: tools.EtcdErrorNotFound,
 | 
			
		||||
	}
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", latest.Codec.EncodeOrDie(&api.ContainerManifestList{}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(latest.Codec, &api.ContainerManifestList{}), 0)
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	err := registry.CreatePod(&api.Pod{
 | 
			
		||||
		JSONBase: api.JSONBase{
 | 
			
		||||
@@ -133,7 +133,7 @@ func TestEtcdCreatePodAlreadyExisting(t *testing.T) {
 | 
			
		||||
	fakeClient.Data["/registry/pods/foo"] = tools.EtcdResponseWithError{
 | 
			
		||||
		R: &etcd.Response{
 | 
			
		||||
			Node: &etcd.Node{
 | 
			
		||||
				Value: latest.Codec.EncodeOrDie(&api.Pod{JSONBase: api.JSONBase{ID: "foo"}}),
 | 
			
		||||
				Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		E: nil,
 | 
			
		||||
@@ -264,7 +264,7 @@ func TestEtcdCreatePodWithExistingContainers(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		E: tools.EtcdErrorNotFound,
 | 
			
		||||
	}
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", latest.Codec.EncodeOrDie(&api.ContainerManifestList{
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(latest.Codec, &api.ContainerManifestList{
 | 
			
		||||
		Items: []api.ContainerManifest{
 | 
			
		||||
			{ID: "bar"},
 | 
			
		||||
		},
 | 
			
		||||
@@ -325,11 +325,11 @@ func TestEtcdDeletePod(t *testing.T) {
 | 
			
		||||
	fakeClient.TestIndex = true
 | 
			
		||||
 | 
			
		||||
	key := "/registry/pods/foo"
 | 
			
		||||
	fakeClient.Set(key, latest.Codec.EncodeOrDie(&api.Pod{
 | 
			
		||||
	fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{
 | 
			
		||||
		JSONBase:     api.JSONBase{ID: "foo"},
 | 
			
		||||
		DesiredState: api.PodState{Host: "machine"},
 | 
			
		||||
	}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", latest.Codec.EncodeOrDie(&api.ContainerManifestList{
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(latest.Codec, &api.ContainerManifestList{
 | 
			
		||||
		Items: []api.ContainerManifest{
 | 
			
		||||
			{ID: "foo"},
 | 
			
		||||
		},
 | 
			
		||||
@@ -361,11 +361,11 @@ func TestEtcdDeletePodMultipleContainers(t *testing.T) {
 | 
			
		||||
	fakeClient.TestIndex = true
 | 
			
		||||
 | 
			
		||||
	key := "/registry/pods/foo"
 | 
			
		||||
	fakeClient.Set(key, latest.Codec.EncodeOrDie(&api.Pod{
 | 
			
		||||
	fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Pod{
 | 
			
		||||
		JSONBase:     api.JSONBase{ID: "foo"},
 | 
			
		||||
		DesiredState: api.PodState{Host: "machine"},
 | 
			
		||||
	}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", latest.Codec.EncodeOrDie(&api.ContainerManifestList{
 | 
			
		||||
	fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(latest.Codec, &api.ContainerManifestList{
 | 
			
		||||
		Items: []api.ContainerManifest{
 | 
			
		||||
			{ID: "foo"},
 | 
			
		||||
			{ID: "bar"},
 | 
			
		||||
@@ -445,13 +445,13 @@ func TestEtcdListPods(t *testing.T) {
 | 
			
		||||
			Node: &etcd.Node{
 | 
			
		||||
				Nodes: []*etcd.Node{
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.Pod{
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{
 | 
			
		||||
							JSONBase:     api.JSONBase{ID: "foo"},
 | 
			
		||||
							DesiredState: api.PodState{Host: "machine"},
 | 
			
		||||
						}),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.Pod{
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{
 | 
			
		||||
							JSONBase:     api.JSONBase{ID: "bar"},
 | 
			
		||||
							DesiredState: api.PodState{Host: "machine"},
 | 
			
		||||
						}),
 | 
			
		||||
@@ -520,10 +520,10 @@ func TestEtcdListControllers(t *testing.T) {
 | 
			
		||||
			Node: &etcd.Node{
 | 
			
		||||
				Nodes: []*etcd.Node{
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}),
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "bar"}}),
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{JSONBase: api.JSONBase{ID: "bar"}}),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -543,7 +543,7 @@ func TestEtcdListControllers(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestEtcdGetController(t *testing.T) {
 | 
			
		||||
	fakeClient := tools.NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.Set("/registry/controllers/foo", latest.Codec.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	ctrl, err := registry.GetController("foo")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -619,7 +619,7 @@ func TestEtcdCreateController(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
 | 
			
		||||
	fakeClient := tools.NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.Set("/registry/controllers/foo", latest.Codec.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	err := registry.CreateController(&api.ReplicationController{
 | 
			
		||||
@@ -636,7 +636,7 @@ func TestEtcdUpdateController(t *testing.T) {
 | 
			
		||||
	fakeClient := tools.NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.TestIndex = true
 | 
			
		||||
 | 
			
		||||
	resp, _ := fakeClient.Set("/registry/controllers/foo", latest.Codec.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	resp, _ := fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(latest.Codec, &api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	err := registry.UpdateController(&api.ReplicationController{
 | 
			
		||||
		JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex},
 | 
			
		||||
@@ -662,10 +662,10 @@ func TestEtcdListServices(t *testing.T) {
 | 
			
		||||
			Node: &etcd.Node{
 | 
			
		||||
				Nodes: []*etcd.Node{
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "foo"}}),
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.Service{JSONBase: api.JSONBase{ID: "foo"}}),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "bar"}}),
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.Service{JSONBase: api.JSONBase{ID: "bar"}}),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -711,7 +711,7 @@ func TestEtcdCreateService(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
 | 
			
		||||
	fakeClient := tools.NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.Set("/registry/services/specs/foo", latest.Codec.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(latest.Codec, &api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	err := registry.CreateService(&api.Service{
 | 
			
		||||
		JSONBase: api.JSONBase{ID: "foo"},
 | 
			
		||||
@@ -723,7 +723,7 @@ func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestEtcdGetService(t *testing.T) {
 | 
			
		||||
	fakeClient := tools.NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.Set("/registry/services/specs/foo", latest.Codec.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(latest.Codec, &api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	service, err := registry.GetService("foo")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -775,7 +775,7 @@ func TestEtcdUpdateService(t *testing.T) {
 | 
			
		||||
	fakeClient := tools.NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.TestIndex = true
 | 
			
		||||
 | 
			
		||||
	resp, _ := fakeClient.Set("/registry/services/specs/foo", latest.Codec.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	resp, _ := fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(latest.Codec, &api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
	registry := NewTestEtcdRegistry(fakeClient)
 | 
			
		||||
	testService := api.Service{
 | 
			
		||||
		JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex},
 | 
			
		||||
@@ -812,10 +812,10 @@ func TestEtcdListEndpoints(t *testing.T) {
 | 
			
		||||
			Node: &etcd.Node{
 | 
			
		||||
				Nodes: []*etcd.Node{
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:8345"}}),
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:8345"}}),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Value: latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "bar"}}),
 | 
			
		||||
						Value: runtime.EncodeOrDie(latest.Codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "bar"}}),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -841,7 +841,7 @@ func TestEtcdGetEndpoints(t *testing.T) {
 | 
			
		||||
		Endpoints: []string{"127.0.0.1:34855"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fakeClient.Set("/registry/services/endpoints/foo", latest.Codec.EncodeOrDie(endpoints), 0)
 | 
			
		||||
	fakeClient.Set("/registry/services/endpoints/foo", runtime.EncodeOrDie(latest.Codec, endpoints), 0)
 | 
			
		||||
 | 
			
		||||
	got, err := registry.GetEndpoints("foo")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -862,7 +862,7 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
 | 
			
		||||
		Endpoints: []string{"baz", "bar"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fakeClient.Set("/registry/services/endpoints/foo", latest.Codec.EncodeOrDie(&api.Endpoints{}), 0)
 | 
			
		||||
	fakeClient.Set("/registry/services/endpoints/foo", runtime.EncodeOrDie(latest.Codec, &api.Endpoints{}), 0)
 | 
			
		||||
 | 
			
		||||
	err := registry.UpdateEndpoints(&endpoints)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
 | 
			
		||||
 
 | 
			
		||||
@@ -20,42 +20,80 @@ import (
 | 
			
		||||
	"gopkg.in/v1/yaml"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// EmbeddedObject must have an appropriate encoder and decoder functions, such that on the
 | 
			
		||||
// wire, it's stored as a []byte, but in memory, the contained object is accessable as an
 | 
			
		||||
// Object via the Get() function. Only valid API objects may be stored via EmbeddedObject.
 | 
			
		||||
// The purpose of this is to allow an API object of type known only at runtime to be
 | 
			
		||||
// embedded within other API objects.
 | 
			
		||||
//
 | 
			
		||||
// Define a Codec variable in your package and import the runtime package and
 | 
			
		||||
// then use the commented section below
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
// EmbeddedObject implements a Codec specific version of an
 | 
			
		||||
// embedded object.
 | 
			
		||||
type EmbeddedObject struct {
 | 
			
		||||
	runtime.Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSON implements the json.Unmarshaler interface.
 | 
			
		||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
 | 
			
		||||
	obj, err := runtime.CodecUnmarshalJSON(Codec, b)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON implements the json.Marshaler interface.
 | 
			
		||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return runtime.CodecMarshalJSON(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetYAML implements the yaml.Setter interface.
 | 
			
		||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
 | 
			
		||||
	obj, ok := runtime.CodecSetYAML(Codec, tag, value)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetYAML implements the yaml.Getter interface.
 | 
			
		||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
 | 
			
		||||
	return runtime.CodecGetYAML(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// Encode()/Decode() are the canonical way of converting an API object to/from
 | 
			
		||||
// wire format. This file provides utility functions which permit doing so
 | 
			
		||||
// recursively, such that API objects of types known only at run time can be
 | 
			
		||||
// embedded within other API types.
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSON implements the json.Unmarshaler interface.
 | 
			
		||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
 | 
			
		||||
func CodecUnmarshalJSON(codec Codec, b []byte) (Object, error) {
 | 
			
		||||
	// Handle JSON's "null": Decode() doesn't expect it.
 | 
			
		||||
	if len(b) == 4 && string(b) == "null" {
 | 
			
		||||
		a.Object = nil
 | 
			
		||||
		return nil
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obj, err := DefaultCodec.Decode(b)
 | 
			
		||||
	obj, err := codec.Decode(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return nil
 | 
			
		||||
	return obj, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON implements the json.Marshaler interface.
 | 
			
		||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	if a.Object == nil {
 | 
			
		||||
func CodecMarshalJSON(codec Codec, obj Object) ([]byte, error) {
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		// Encode unset/nil objects as JSON's "null".
 | 
			
		||||
		return []byte("null"), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return DefaultCodec.Encode(a.Object)
 | 
			
		||||
	return codec.Encode(obj)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetYAML implements the yaml.Setter interface.
 | 
			
		||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
 | 
			
		||||
func CodecSetYAML(codec Codec, tag string, value interface{}) (Object, bool) {
 | 
			
		||||
	if value == nil {
 | 
			
		||||
		a.Object = nil
 | 
			
		||||
		return true
 | 
			
		||||
		return nil, true
 | 
			
		||||
	}
 | 
			
		||||
	// Why does the yaml package send value as a map[interface{}]interface{}?
 | 
			
		||||
	// It's especially frustrating because encoding/json does the right thing
 | 
			
		||||
@@ -67,22 +105,21 @@ func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic("yaml can't reverse its own object")
 | 
			
		||||
	}
 | 
			
		||||
	obj, err := DefaultCodec.Decode(b)
 | 
			
		||||
	obj, err := codec.Decode(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return true
 | 
			
		||||
	return obj, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetYAML implements the yaml.Getter interface.
 | 
			
		||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
 | 
			
		||||
	if a.Object == nil {
 | 
			
		||||
func CodecGetYAML(codec Codec, obj Object) (tag string, value interface{}) {
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		value = "null"
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// Encode returns JSON, which is conveniently a subset of YAML.
 | 
			
		||||
	v, err := DefaultCodec.Encode(a.Object)
 | 
			
		||||
	v, err := codec.Encode(obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic("impossible to encode API object!")
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,38 +14,72 @@ See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package runtime
 | 
			
		||||
package runtime_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var scheme = runtime.NewScheme()
 | 
			
		||||
var Codec = runtime.CodecFor(scheme, "v1test")
 | 
			
		||||
 | 
			
		||||
// EmbeddedObject implements a Codec specific version of an
 | 
			
		||||
// embedded object.
 | 
			
		||||
type EmbeddedObject struct {
 | 
			
		||||
	runtime.Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSON implements the json.Unmarshaler interface.
 | 
			
		||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
 | 
			
		||||
	obj, err := runtime.CodecUnmarshalJSON(Codec, b)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON implements the json.Marshaler interface.
 | 
			
		||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return runtime.CodecMarshalJSON(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetYAML implements the yaml.Setter interface.
 | 
			
		||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
 | 
			
		||||
	obj, ok := runtime.CodecSetYAML(Codec, tag, value)
 | 
			
		||||
	a.Object = obj
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetYAML implements the yaml.Getter interface.
 | 
			
		||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
 | 
			
		||||
	return runtime.CodecGetYAML(Codec, a.Object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type EmbeddedTest struct {
 | 
			
		||||
	JSONBase    `yaml:",inline" json:",inline"`
 | 
			
		||||
	Object      EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"`
 | 
			
		||||
	EmptyObject EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
 | 
			
		||||
	runtime.JSONBase `yaml:",inline" json:",inline"`
 | 
			
		||||
	Object           EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"`
 | 
			
		||||
	EmptyObject      EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*EmbeddedTest) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
func TestEmbeddedObject(t *testing.T) {
 | 
			
		||||
	// TODO(dbsmith) fix EmbeddedObject to not use DefaultScheme.
 | 
			
		||||
	s := DefaultScheme
 | 
			
		||||
	s := scheme
 | 
			
		||||
	s.AddKnownTypes("", &EmbeddedTest{})
 | 
			
		||||
	s.AddKnownTypes("v1beta1", &EmbeddedTest{})
 | 
			
		||||
	s.AddKnownTypes("v1test", &EmbeddedTest{})
 | 
			
		||||
 | 
			
		||||
	outer := &EmbeddedTest{
 | 
			
		||||
		JSONBase: JSONBase{ID: "outer"},
 | 
			
		||||
		JSONBase: runtime.JSONBase{ID: "outer"},
 | 
			
		||||
		Object: EmbeddedObject{
 | 
			
		||||
			&EmbeddedTest{
 | 
			
		||||
				JSONBase: JSONBase{ID: "inner"},
 | 
			
		||||
				JSONBase: runtime.JSONBase{ID: "inner"},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wire, err := s.Encode(outer)
 | 
			
		||||
	wire, err := s.EncodeToVersion(outer, "v1test")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Unexpected encode error '%v'", err)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,13 +16,23 @@ limitations under the License.
 | 
			
		||||
 | 
			
		||||
package runtime
 | 
			
		||||
 | 
			
		||||
// Codec defines methods for serializing and deserializing API objects.
 | 
			
		||||
type Codec interface {
 | 
			
		||||
	Encode(obj Object) (data []byte, err error)
 | 
			
		||||
// Decoder defines methods for deserializing API objects into a given type
 | 
			
		||||
type Decoder interface {
 | 
			
		||||
	Decode(data []byte) (Object, error)
 | 
			
		||||
	DecodeInto(data []byte, obj Object) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encoder defines methods for serializing API objects into bytes
 | 
			
		||||
type Encoder interface {
 | 
			
		||||
	Encode(obj Object) (data []byte, err error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Codec defines methods for serializing and deserializing API objects.
 | 
			
		||||
type Codec interface {
 | 
			
		||||
	Decoder
 | 
			
		||||
	Encoder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResourceVersioner provides methods for setting and retrieving
 | 
			
		||||
// the resource version from an API object.
 | 
			
		||||
type ResourceVersioner interface {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,16 +17,40 @@ limitations under the License.
 | 
			
		||||
package runtime
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"gopkg.in/v1/yaml"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var DefaultResourceVersioner ResourceVersioner = NewJSONBaseResourceVersioner()
 | 
			
		||||
var DefaultScheme = NewScheme("", "v1beta1")
 | 
			
		||||
var DefaultCodec Codec = DefaultScheme
 | 
			
		||||
// codecWrapper implements encoding to an alternative
 | 
			
		||||
// default version for a scheme.
 | 
			
		||||
type codecWrapper struct {
 | 
			
		||||
	*Scheme
 | 
			
		||||
	version string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encode implements Codec
 | 
			
		||||
func (c *codecWrapper) Encode(obj Object) ([]byte, error) {
 | 
			
		||||
	return c.Scheme.EncodeToVersion(obj, c.version)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CodecFor returns a Codec that invokes Encode with the provided version.
 | 
			
		||||
func CodecFor(scheme *Scheme, version string) Codec {
 | 
			
		||||
	return &codecWrapper{scheme, version}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
 | 
			
		||||
func EncodeOrDie(codec Codec, obj Object) string {
 | 
			
		||||
	bytes, err := codec.Encode(obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return string(bytes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Scheme defines methods for serializing and deserializing API objects. It
 | 
			
		||||
// is an adaptation of conversion's Scheme for our API objects.
 | 
			
		||||
@@ -36,21 +60,13 @@ type Scheme struct {
 | 
			
		||||
 | 
			
		||||
// fromScope gets the input version, desired output version, and desired Scheme
 | 
			
		||||
// from a conversion.Scope.
 | 
			
		||||
func fromScope(s conversion.Scope) (inVersion, outVersion string, scheme *Scheme) {
 | 
			
		||||
	scheme = DefaultScheme
 | 
			
		||||
func (self *Scheme) fromScope(s conversion.Scope) (inVersion, outVersion string, scheme *Scheme) {
 | 
			
		||||
	scheme = self
 | 
			
		||||
	inVersion = s.Meta().SrcVersion
 | 
			
		||||
	outVersion = s.Meta().DestVersion
 | 
			
		||||
	return inVersion, outVersion, scheme
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	// Set up a generic mapping between RawExtension and EmbeddedObject.
 | 
			
		||||
	DefaultScheme.AddConversionFuncs(
 | 
			
		||||
		embeddedObjectToRawExtension,
 | 
			
		||||
		rawExtensionToEmbeddedObject,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// emptyPlugin is used to copy the Kind field to and from plugin objects.
 | 
			
		||||
type emptyPlugin struct {
 | 
			
		||||
	PluginBase `json:",inline" yaml:",inline"`
 | 
			
		||||
@@ -59,14 +75,14 @@ type emptyPlugin struct {
 | 
			
		||||
// embeddedObjectToRawExtension does the conversion you would expect from the name, using the information
 | 
			
		||||
// given in conversion.Scope. It's placed in the DefaultScheme as a ConversionFunc to enable plugins;
 | 
			
		||||
// see the comment for RawExtension.
 | 
			
		||||
func embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExtension, s conversion.Scope) error {
 | 
			
		||||
func (self *Scheme) embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExtension, s conversion.Scope) error {
 | 
			
		||||
	if in.Object == nil {
 | 
			
		||||
		out.RawJSON = []byte("null")
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Figure out the type and kind of the output object.
 | 
			
		||||
	_, outVersion, scheme := fromScope(s)
 | 
			
		||||
	_, outVersion, scheme := self.fromScope(s)
 | 
			
		||||
	_, kind, err := scheme.raw.ObjectVersionAndKind(in.Object)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@@ -107,13 +123,13 @@ func embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExtension, s conve
 | 
			
		||||
// rawExtensionToEmbeddedObject does the conversion you would expect from the name, using the information
 | 
			
		||||
// given in conversion.Scope. It's placed in the DefaultScheme as a ConversionFunc to enable plugins;
 | 
			
		||||
// see the comment for RawExtension.
 | 
			
		||||
func rawExtensionToEmbeddedObject(in *RawExtension, out *EmbeddedObject, s conversion.Scope) error {
 | 
			
		||||
func (self *Scheme) rawExtensionToEmbeddedObject(in *RawExtension, out *EmbeddedObject, s conversion.Scope) error {
 | 
			
		||||
	if len(in.RawJSON) == 4 && string(in.RawJSON) == "null" {
 | 
			
		||||
		out.Object = nil
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	// Figure out the type and kind of the output object.
 | 
			
		||||
	inVersion, outVersion, scheme := fromScope(s)
 | 
			
		||||
	inVersion, outVersion, scheme := self.fromScope(s)
 | 
			
		||||
	_, kind, err := scheme.raw.DataVersionAndKind(in.RawJSON)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@@ -153,13 +169,15 @@ func rawExtensionToEmbeddedObject(in *RawExtension, out *EmbeddedObject, s conve
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewScheme creates a new Scheme. A default scheme is provided and accessible
 | 
			
		||||
// as the "DefaultScheme" variable.
 | 
			
		||||
func NewScheme(internalVersion, externalVersion string) *Scheme {
 | 
			
		||||
// NewScheme creates a new Scheme. This scheme is pluggable by default.
 | 
			
		||||
func NewScheme() *Scheme {
 | 
			
		||||
	s := &Scheme{conversion.NewScheme()}
 | 
			
		||||
	s.raw.InternalVersion = internalVersion
 | 
			
		||||
	s.raw.ExternalVersion = externalVersion
 | 
			
		||||
	s.raw.InternalVersion = ""
 | 
			
		||||
	s.raw.MetaInsertionFactory = metaInsertion{}
 | 
			
		||||
	s.raw.AddConversionFuncs(
 | 
			
		||||
		s.embeddedObjectToRawExtension,
 | 
			
		||||
		s.rawExtensionToEmbeddedObject,
 | 
			
		||||
	)
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -180,6 +198,10 @@ func (s *Scheme) AddKnownTypeWithName(version, kind string, obj Object) {
 | 
			
		||||
	s.raw.AddKnownTypeWithName(version, kind, obj)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Scheme) KnownTypes(version string) map[string]reflect.Type {
 | 
			
		||||
	return s.raw.KnownTypes(version)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// New returns a new API object of the given version ("" for internal
 | 
			
		||||
// representation) and name, or an error if it hasn't been registered.
 | 
			
		||||
func (s *Scheme) New(versionName, typeName string) (Object, error) {
 | 
			
		||||
@@ -236,12 +258,7 @@ func FindJSONBase(obj Object) (JSONBaseInterface, error) {
 | 
			
		||||
	return g, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
 | 
			
		||||
func (s *Scheme) EncodeOrDie(obj Object) string {
 | 
			
		||||
	return s.raw.EncodeOrDie(obj)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encode turns the given api object into an appropriate JSON string.
 | 
			
		||||
// EncodeToVersion turns the given api object into an appropriate JSON string.
 | 
			
		||||
// Will return an error if the object doesn't have an embedded JSONBase.
 | 
			
		||||
// Obj may be a pointer to a struct, or a struct. If a struct, a copy
 | 
			
		||||
// must be made. If a pointer, the object may be modified before encoding,
 | 
			
		||||
@@ -269,17 +286,6 @@ func (s *Scheme) EncodeOrDie(obj Object) string {
 | 
			
		||||
// change the memory format yet not break compatibility with any stored
 | 
			
		||||
// objects, whether they be in our storage layer (e.g., etcd), or in user's
 | 
			
		||||
// config files.
 | 
			
		||||
//
 | 
			
		||||
// TODO/next steps: When we add our second versioned type, this package will
 | 
			
		||||
// need a version of Encode that lets you choose the wire version. A configurable
 | 
			
		||||
// default will be needed, to allow operating in clusters that haven't yet
 | 
			
		||||
// upgraded.
 | 
			
		||||
//
 | 
			
		||||
func (s *Scheme) Encode(obj Object) (data []byte, err error) {
 | 
			
		||||
	return s.raw.Encode(obj)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeToVersion is like Encode, but lets you specify the destination version.
 | 
			
		||||
func (s *Scheme) EncodeToVersion(obj Object, destVersion string) (data []byte, err error) {
 | 
			
		||||
	return s.raw.EncodeToVersion(obj, destVersion)
 | 
			
		||||
}
 | 
			
		||||
@@ -332,10 +338,10 @@ func (s *Scheme) DecodeInto(data []byte, obj Object) error {
 | 
			
		||||
	return s.raw.DecodeInto(data, obj)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Does a deep copy of an API object.  Useful mostly for tests.
 | 
			
		||||
// Copy does a deep copy of an API object.  Useful mostly for tests.
 | 
			
		||||
// TODO(dbsmith): implement directly instead of via Encode/Decode
 | 
			
		||||
func (s *Scheme) Copy(obj Object) (Object, error) {
 | 
			
		||||
	data, err := s.Encode(obj)
 | 
			
		||||
	data, err := s.EncodeToVersion(obj, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -350,6 +356,26 @@ func (s *Scheme) CopyOrDie(obj Object) Object {
 | 
			
		||||
	return newObj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ObjectDiff(a, b Object) string {
 | 
			
		||||
	ab, err := json.Marshal(a)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(fmt.Sprintf("a: %v", err))
 | 
			
		||||
	}
 | 
			
		||||
	bb, err := json.Marshal(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(fmt.Sprintf("b: %v", err))
 | 
			
		||||
	}
 | 
			
		||||
	return util.StringDiff(string(ab), string(bb))
 | 
			
		||||
 | 
			
		||||
	// An alternate diff attempt, in case json isn't showing you
 | 
			
		||||
	// the difference. (reflect.DeepEqual makes a distinction between
 | 
			
		||||
	// nil and empty slices, for example.)
 | 
			
		||||
	return util.StringDiff(
 | 
			
		||||
		fmt.Sprintf("%#v", a),
 | 
			
		||||
		fmt.Sprintf("%#v", b),
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// metaInsertion implements conversion.MetaInsertionFactory, which lets the conversion
 | 
			
		||||
// package figure out how to encode our object's types and versions. These fields are
 | 
			
		||||
// located in our JSONBase.
 | 
			
		||||
 
 | 
			
		||||
@@ -43,14 +43,15 @@ func (*InternalSimple) IsAnAPIObject() {}
 | 
			
		||||
func (*ExternalSimple) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
func TestScheme(t *testing.T) {
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
 | 
			
		||||
	scheme := runtime.NewScheme()
 | 
			
		||||
	scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
 | 
			
		||||
	scheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
 | 
			
		||||
 | 
			
		||||
	internalToExternalCalls := 0
 | 
			
		||||
	externalToInternalCalls := 0
 | 
			
		||||
 | 
			
		||||
	// Register functions to verify that scope.Meta() gets set correctly.
 | 
			
		||||
	err := runtime.DefaultScheme.AddConversionFuncs(
 | 
			
		||||
	err := scheme.AddConversionFuncs(
 | 
			
		||||
		func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error {
 | 
			
		||||
			if e, a := "", scope.Meta().SrcVersion; e != a {
 | 
			
		||||
				t.Errorf("Expected '%v', got '%v'", e, a)
 | 
			
		||||
@@ -85,10 +86,10 @@ func TestScheme(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	// Test Encode, Decode, and DecodeInto
 | 
			
		||||
	obj := runtime.Object(simple)
 | 
			
		||||
	data, err := runtime.DefaultScheme.EncodeToVersion(obj, "externalVersion")
 | 
			
		||||
	obj2, err2 := runtime.DefaultScheme.Decode(data)
 | 
			
		||||
	data, err := scheme.EncodeToVersion(obj, "externalVersion")
 | 
			
		||||
	obj2, err2 := scheme.Decode(data)
 | 
			
		||||
	obj3 := &InternalSimple{}
 | 
			
		||||
	err3 := runtime.DefaultScheme.DecodeInto(data, obj3)
 | 
			
		||||
	err3 := scheme.DecodeInto(data, obj3)
 | 
			
		||||
	if err != nil || err2 != nil {
 | 
			
		||||
		t.Fatalf("Failure: '%v' '%v' '%v'", err, err2, err3)
 | 
			
		||||
	}
 | 
			
		||||
@@ -104,7 +105,7 @@ func TestScheme(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	// Test Convert
 | 
			
		||||
	external := &ExternalSimple{}
 | 
			
		||||
	err = runtime.DefaultScheme.Convert(simple, external)
 | 
			
		||||
	err = scheme.Convert(simple, external)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -123,12 +124,13 @@ func TestScheme(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBadJSONRejection(t *testing.T) {
 | 
			
		||||
	scheme := runtime.NewScheme()
 | 
			
		||||
	badJSONMissingKind := []byte(`{ }`)
 | 
			
		||||
	if _, err := runtime.DefaultScheme.Decode(badJSONMissingKind); err == nil {
 | 
			
		||||
	if _, err := scheme.Decode(badJSONMissingKind); err == nil {
 | 
			
		||||
		t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind)
 | 
			
		||||
	}
 | 
			
		||||
	badJSONUnknownType := []byte(`{"kind": "bar"}`)
 | 
			
		||||
	if _, err1 := runtime.DefaultScheme.Decode(badJSONUnknownType); err1 == nil {
 | 
			
		||||
	if _, err1 := scheme.Decode(badJSONUnknownType); err1 == nil {
 | 
			
		||||
		t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
 | 
			
		||||
	}
 | 
			
		||||
	/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)
 | 
			
		||||
@@ -163,12 +165,13 @@ func (*ExternalExtensionType) IsAnAPIObject() {}
 | 
			
		||||
func (*InternalExtensionType) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
func TestExtensionMapping(t *testing.T) {
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("", "ExtensionType", &InternalExtensionType{})
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("", "A", &ExtensionA{})
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("", "B", &ExtensionB{})
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("testExternal", "ExtensionType", &ExternalExtensionType{})
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("testExternal", "A", &ExtensionA{})
 | 
			
		||||
	runtime.DefaultScheme.AddKnownTypeWithName("testExternal", "B", &ExtensionB{})
 | 
			
		||||
	scheme := runtime.NewScheme()
 | 
			
		||||
	scheme.AddKnownTypeWithName("", "ExtensionType", &InternalExtensionType{})
 | 
			
		||||
	scheme.AddKnownTypeWithName("", "A", &ExtensionA{})
 | 
			
		||||
	scheme.AddKnownTypeWithName("", "B", &ExtensionB{})
 | 
			
		||||
	scheme.AddKnownTypeWithName("testExternal", "ExtensionType", &ExternalExtensionType{})
 | 
			
		||||
	scheme.AddKnownTypeWithName("testExternal", "A", &ExtensionA{})
 | 
			
		||||
	scheme.AddKnownTypeWithName("testExternal", "B", &ExtensionB{})
 | 
			
		||||
 | 
			
		||||
	table := []struct {
 | 
			
		||||
		obj     runtime.Object
 | 
			
		||||
@@ -187,14 +190,14 @@ func TestExtensionMapping(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, item := range table {
 | 
			
		||||
		gotEncoded, err := runtime.DefaultScheme.EncodeToVersion(item.obj, "testExternal")
 | 
			
		||||
		gotEncoded, err := scheme.EncodeToVersion(item.obj, "testExternal")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error '%v' (%#v)", err, item.obj)
 | 
			
		||||
		} else if e, a := item.encoded, string(gotEncoded); e != a {
 | 
			
		||||
			t.Errorf("expected %v, got %v", e, a)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		gotDecoded, err := runtime.DefaultScheme.Decode([]byte(item.encoded))
 | 
			
		||||
		gotDecoded, err := scheme.Decode([]byte(item.encoded))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("unexpected error '%v' (%v)", err, item.encoded)
 | 
			
		||||
		} else if e, a := item.obj, gotDecoded; !reflect.DeepEqual(e, a) {
 | 
			
		||||
@@ -209,3 +212,25 @@ func TestExtensionMapping(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEncode(t *testing.T) {
 | 
			
		||||
	scheme := runtime.NewScheme()
 | 
			
		||||
	scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
 | 
			
		||||
	scheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
 | 
			
		||||
	codec := runtime.CodecFor(scheme, "externalVersion")
 | 
			
		||||
	test := &InternalSimple{
 | 
			
		||||
		TestString: "I'm the same",
 | 
			
		||||
	}
 | 
			
		||||
	obj := runtime.Object(test)
 | 
			
		||||
	data, err := codec.Encode(obj)
 | 
			
		||||
	obj2, err2 := codec.Decode(data)
 | 
			
		||||
	if err != nil || err2 != nil {
 | 
			
		||||
		t.Fatalf("Failure: '%v' '%v'", err, err2)
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := obj2.(*InternalSimple); !ok {
 | 
			
		||||
		t.Fatalf("Got wrong type")
 | 
			
		||||
	}
 | 
			
		||||
	if !reflect.DeepEqual(obj2, test) {
 | 
			
		||||
		t.Errorf("Expected:\n %#v,\n Got:\n %#v", &test, obj2)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
			
		||||
	"github.com/coreos/go-etcd/etcd"
 | 
			
		||||
@@ -42,13 +43,14 @@ type TestResource struct {
 | 
			
		||||
func (*TestResource) IsAnAPIObject() {}
 | 
			
		||||
 | 
			
		||||
var scheme *runtime.Scheme
 | 
			
		||||
var codec = latest.Codec
 | 
			
		||||
var versioner = runtime.DefaultResourceVersioner
 | 
			
		||||
var codec runtime.Codec
 | 
			
		||||
var versioner = runtime.NewJSONBaseResourceVersioner()
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	scheme = runtime.NewScheme("", "v1beta1")
 | 
			
		||||
	scheme = runtime.NewScheme()
 | 
			
		||||
	scheme.AddKnownTypes("", &TestResource{})
 | 
			
		||||
	scheme.AddKnownTypes("v1beta1", &TestResource{})
 | 
			
		||||
	codec = runtime.CodecFor(scheme, "v1beta1")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIsEtcdNotFound(t *testing.T) {
 | 
			
		||||
@@ -93,7 +95,7 @@ func TestExtractList(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var got []api.Pod
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, versioner}
 | 
			
		||||
	helper := EtcdHelper{fakeClient, latest.Codec, versioner}
 | 
			
		||||
	resourceVersion := uint64(0)
 | 
			
		||||
	err := helper.ExtractList("/some/key", &got, &resourceVersion)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -114,7 +116,7 @@ func TestExtractObj(t *testing.T) {
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
	expect := api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
	fakeClient.Set("/some/key", util.EncodeJSON(expect), 0)
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, versioner}
 | 
			
		||||
	helper := EtcdHelper{fakeClient, latest.Codec, versioner}
 | 
			
		||||
	var got api.Pod
 | 
			
		||||
	err := helper.ExtractObj("/some/key", &got, false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -168,12 +170,12 @@ func TestExtractObjNotFoundErr(t *testing.T) {
 | 
			
		||||
func TestSetObj(t *testing.T) {
 | 
			
		||||
	obj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, versioner}
 | 
			
		||||
	helper := EtcdHelper{fakeClient, latest.Codec, versioner}
 | 
			
		||||
	err := helper.SetObj("/some/key", obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unexpected error %#v", err)
 | 
			
		||||
	}
 | 
			
		||||
	data, err := codec.Encode(obj)
 | 
			
		||||
	data, err := latest.Codec.Encode(obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unexpected error %#v", err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -191,18 +193,18 @@ func TestSetObjWithVersion(t *testing.T) {
 | 
			
		||||
	fakeClient.Data["/some/key"] = EtcdResponseWithError{
 | 
			
		||||
		R: &etcd.Response{
 | 
			
		||||
			Node: &etcd.Node{
 | 
			
		||||
				Value:         latest.Codec.EncodeOrDie(obj),
 | 
			
		||||
				Value:         runtime.EncodeOrDie(latest.Codec, obj),
 | 
			
		||||
				ModifiedIndex: 1,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, versioner}
 | 
			
		||||
	helper := EtcdHelper{fakeClient, latest.Codec, versioner}
 | 
			
		||||
	err := helper.SetObj("/some/key", obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Unexpected error %#v", err)
 | 
			
		||||
	}
 | 
			
		||||
	data, err := codec.Encode(obj)
 | 
			
		||||
	data, err := latest.Codec.Encode(obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Unexpected error %#v", err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -216,12 +218,12 @@ func TestSetObjWithVersion(t *testing.T) {
 | 
			
		||||
func TestSetObjWithoutResourceVersioner(t *testing.T) {
 | 
			
		||||
	obj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, nil}
 | 
			
		||||
	helper := EtcdHelper{fakeClient, latest.Codec, nil}
 | 
			
		||||
	err := helper.SetObj("/some/key", obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unexpected error %#v", err)
 | 
			
		||||
	}
 | 
			
		||||
	data, err := codec.Encode(obj)
 | 
			
		||||
	data, err := latest.Codec.Encode(obj)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unexpected error %#v", err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -235,7 +237,6 @@ func TestSetObjWithoutResourceVersioner(t *testing.T) {
 | 
			
		||||
func TestAtomicUpdate(t *testing.T) {
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.TestIndex = true
 | 
			
		||||
	codec := scheme
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, runtime.NewJSONBaseResourceVersioner()}
 | 
			
		||||
 | 
			
		||||
	// Create a new node.
 | 
			
		||||
@@ -290,7 +291,7 @@ func TestAtomicUpdate(t *testing.T) {
 | 
			
		||||
func TestAtomicUpdateNoChange(t *testing.T) {
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.TestIndex = true
 | 
			
		||||
	helper := EtcdHelper{fakeClient, scheme, runtime.NewJSONBaseResourceVersioner()}
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, runtime.NewJSONBaseResourceVersioner()}
 | 
			
		||||
 | 
			
		||||
	// Create a new node.
 | 
			
		||||
	fakeClient.ExpectNotFoundGet("/some/key")
 | 
			
		||||
@@ -321,7 +322,6 @@ func TestAtomicUpdateNoChange(t *testing.T) {
 | 
			
		||||
func TestAtomicUpdate_CreateCollision(t *testing.T) {
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.TestIndex = true
 | 
			
		||||
	codec := scheme
 | 
			
		||||
	helper := EtcdHelper{fakeClient, codec, runtime.NewJSONBaseResourceVersioner()}
 | 
			
		||||
 | 
			
		||||
	fakeClient.ExpectNotFoundGet("/some/key")
 | 
			
		||||
 
 | 
			
		||||
@@ -23,12 +23,14 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
	"github.com/coreos/go-etcd/etcd"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestWatchInterpretations(t *testing.T) {
 | 
			
		||||
	codec := latest.Codec
 | 
			
		||||
	// Declare some pods to make the test cases compact.
 | 
			
		||||
	podFoo := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
	podBar := &api.Pod{JSONBase: api.JSONBase{ID: "bar"}}
 | 
			
		||||
@@ -48,62 +50,62 @@ func TestWatchInterpretations(t *testing.T) {
 | 
			
		||||
	}{
 | 
			
		||||
		"create": {
 | 
			
		||||
			actions:      []string{"create", "get"},
 | 
			
		||||
			nodeValue:    latest.Codec.EncodeOrDie(podBar),
 | 
			
		||||
			nodeValue:    runtime.EncodeOrDie(codec, podBar),
 | 
			
		||||
			expectEmit:   true,
 | 
			
		||||
			expectType:   watch.Added,
 | 
			
		||||
			expectObject: podBar,
 | 
			
		||||
		},
 | 
			
		||||
		"create but filter blocks": {
 | 
			
		||||
			actions:    []string{"create", "get"},
 | 
			
		||||
			nodeValue:  latest.Codec.EncodeOrDie(podFoo),
 | 
			
		||||
			nodeValue:  runtime.EncodeOrDie(codec, podFoo),
 | 
			
		||||
			expectEmit: false,
 | 
			
		||||
		},
 | 
			
		||||
		"delete": {
 | 
			
		||||
			actions:       []string{"delete"},
 | 
			
		||||
			prevNodeValue: latest.Codec.EncodeOrDie(podBar),
 | 
			
		||||
			prevNodeValue: runtime.EncodeOrDie(codec, podBar),
 | 
			
		||||
			expectEmit:    true,
 | 
			
		||||
			expectType:    watch.Deleted,
 | 
			
		||||
			expectObject:  podBar,
 | 
			
		||||
		},
 | 
			
		||||
		"delete but filter blocks": {
 | 
			
		||||
			actions:    []string{"delete"},
 | 
			
		||||
			nodeValue:  latest.Codec.EncodeOrDie(podFoo),
 | 
			
		||||
			nodeValue:  runtime.EncodeOrDie(codec, podFoo),
 | 
			
		||||
			expectEmit: false,
 | 
			
		||||
		},
 | 
			
		||||
		"modify appears to create 1": {
 | 
			
		||||
			actions:      []string{"set", "compareAndSwap"},
 | 
			
		||||
			nodeValue:    latest.Codec.EncodeOrDie(podBar),
 | 
			
		||||
			nodeValue:    runtime.EncodeOrDie(codec, podBar),
 | 
			
		||||
			expectEmit:   true,
 | 
			
		||||
			expectType:   watch.Added,
 | 
			
		||||
			expectObject: podBar,
 | 
			
		||||
		},
 | 
			
		||||
		"modify appears to create 2": {
 | 
			
		||||
			actions:       []string{"set", "compareAndSwap"},
 | 
			
		||||
			prevNodeValue: latest.Codec.EncodeOrDie(podFoo),
 | 
			
		||||
			nodeValue:     latest.Codec.EncodeOrDie(podBar),
 | 
			
		||||
			prevNodeValue: runtime.EncodeOrDie(codec, podFoo),
 | 
			
		||||
			nodeValue:     runtime.EncodeOrDie(codec, podBar),
 | 
			
		||||
			expectEmit:    true,
 | 
			
		||||
			expectType:    watch.Added,
 | 
			
		||||
			expectObject:  podBar,
 | 
			
		||||
		},
 | 
			
		||||
		"modify appears to delete": {
 | 
			
		||||
			actions:       []string{"set", "compareAndSwap"},
 | 
			
		||||
			prevNodeValue: latest.Codec.EncodeOrDie(podBar),
 | 
			
		||||
			nodeValue:     latest.Codec.EncodeOrDie(podFoo),
 | 
			
		||||
			prevNodeValue: runtime.EncodeOrDie(codec, podBar),
 | 
			
		||||
			nodeValue:     runtime.EncodeOrDie(codec, podFoo),
 | 
			
		||||
			expectEmit:    true,
 | 
			
		||||
			expectType:    watch.Deleted,
 | 
			
		||||
			expectObject:  podBar, // Should return last state that passed the filter!
 | 
			
		||||
		},
 | 
			
		||||
		"modify modifies": {
 | 
			
		||||
			actions:       []string{"set", "compareAndSwap"},
 | 
			
		||||
			prevNodeValue: latest.Codec.EncodeOrDie(podBar),
 | 
			
		||||
			nodeValue:     latest.Codec.EncodeOrDie(podBaz),
 | 
			
		||||
			prevNodeValue: runtime.EncodeOrDie(codec, podBar),
 | 
			
		||||
			nodeValue:     runtime.EncodeOrDie(codec, podBaz),
 | 
			
		||||
			expectEmit:    true,
 | 
			
		||||
			expectType:    watch.Modified,
 | 
			
		||||
			expectObject:  podBaz,
 | 
			
		||||
		},
 | 
			
		||||
		"modify ignores": {
 | 
			
		||||
			actions:    []string{"set", "compareAndSwap"},
 | 
			
		||||
			nodeValue:  latest.Codec.EncodeOrDie(podFoo),
 | 
			
		||||
			nodeValue:  runtime.EncodeOrDie(codec, podFoo),
 | 
			
		||||
			expectEmit: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
@@ -197,6 +199,7 @@ func TestWatchInterpretation_ResponseBadData(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWatch(t *testing.T) {
 | 
			
		||||
	codec := latest.Codec
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
	fakeClient.expectNotFoundGetSet["/some/key"] = struct{}{}
 | 
			
		||||
	h := EtcdHelper{fakeClient, codec, versioner}
 | 
			
		||||
@@ -243,6 +246,7 @@ func TestWatch(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWatchEtcdState(t *testing.T) {
 | 
			
		||||
	codec := latest.Codec
 | 
			
		||||
	type T struct {
 | 
			
		||||
		Type      watch.EventType
 | 
			
		||||
		Endpoints []string
 | 
			
		||||
@@ -259,7 +263,7 @@ func TestWatchEtcdState(t *testing.T) {
 | 
			
		||||
				{
 | 
			
		||||
					Action: "create",
 | 
			
		||||
					Node: &etcd.Node{
 | 
			
		||||
						Value: string(latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
						Value: string(runtime.EncodeOrDie(codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -273,12 +277,12 @@ func TestWatchEtcdState(t *testing.T) {
 | 
			
		||||
				{
 | 
			
		||||
					Action: "compareAndSwap",
 | 
			
		||||
					Node: &etcd.Node{
 | 
			
		||||
						Value:         string(latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
 | 
			
		||||
						Value:         string(runtime.EncodeOrDie(codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
 | 
			
		||||
						CreatedIndex:  1,
 | 
			
		||||
						ModifiedIndex: 2,
 | 
			
		||||
					},
 | 
			
		||||
					PrevNode: &etcd.Node{
 | 
			
		||||
						Value:         string(latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
						Value:         string(runtime.EncodeOrDie(codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
						CreatedIndex:  1,
 | 
			
		||||
						ModifiedIndex: 1,
 | 
			
		||||
					},
 | 
			
		||||
@@ -295,7 +299,7 @@ func TestWatchEtcdState(t *testing.T) {
 | 
			
		||||
					R: &etcd.Response{
 | 
			
		||||
						Action: "get",
 | 
			
		||||
						Node: &etcd.Node{
 | 
			
		||||
							Value:         string(latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
							Value:         string(runtime.EncodeOrDie(codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
							CreatedIndex:  1,
 | 
			
		||||
							ModifiedIndex: 1,
 | 
			
		||||
						},
 | 
			
		||||
@@ -308,12 +312,12 @@ func TestWatchEtcdState(t *testing.T) {
 | 
			
		||||
				{
 | 
			
		||||
					Action: "compareAndSwap",
 | 
			
		||||
					Node: &etcd.Node{
 | 
			
		||||
						Value:         string(latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
 | 
			
		||||
						Value:         string(runtime.EncodeOrDie(codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
 | 
			
		||||
						CreatedIndex:  1,
 | 
			
		||||
						ModifiedIndex: 2,
 | 
			
		||||
					},
 | 
			
		||||
					PrevNode: &etcd.Node{
 | 
			
		||||
						Value:         string(latest.Codec.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
						Value:         string(runtime.EncodeOrDie(codec, &api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
 | 
			
		||||
						CreatedIndex:  1,
 | 
			
		||||
						ModifiedIndex: 1,
 | 
			
		||||
					},
 | 
			
		||||
@@ -359,6 +363,7 @@ func TestWatchEtcdState(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWatchFromZeroIndex(t *testing.T) {
 | 
			
		||||
	codec := latest.Codec
 | 
			
		||||
	pod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
 | 
			
		||||
	testCases := map[string]struct {
 | 
			
		||||
@@ -370,7 +375,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
 | 
			
		||||
			EtcdResponseWithError{
 | 
			
		||||
				R: &etcd.Response{
 | 
			
		||||
					Node: &etcd.Node{
 | 
			
		||||
						Value:         latest.Codec.EncodeOrDie(pod),
 | 
			
		||||
						Value:         runtime.EncodeOrDie(codec, pod),
 | 
			
		||||
						CreatedIndex:  1,
 | 
			
		||||
						ModifiedIndex: 1,
 | 
			
		||||
					},
 | 
			
		||||
@@ -385,7 +390,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
 | 
			
		||||
			EtcdResponseWithError{
 | 
			
		||||
				R: &etcd.Response{
 | 
			
		||||
					Node: &etcd.Node{
 | 
			
		||||
						Value:         latest.Codec.EncodeOrDie(pod),
 | 
			
		||||
						Value:         runtime.EncodeOrDie(codec, pod),
 | 
			
		||||
						CreatedIndex:  1,
 | 
			
		||||
						ModifiedIndex: 2,
 | 
			
		||||
					},
 | 
			
		||||
@@ -434,6 +439,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWatchListFromZeroIndex(t *testing.T) {
 | 
			
		||||
	codec := latest.Codec
 | 
			
		||||
	pod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
 | 
			
		||||
	fakeClient := NewFakeEtcdClient(t)
 | 
			
		||||
@@ -443,13 +449,13 @@ func TestWatchListFromZeroIndex(t *testing.T) {
 | 
			
		||||
				Dir: true,
 | 
			
		||||
				Nodes: etcd.Nodes{
 | 
			
		||||
					&etcd.Node{
 | 
			
		||||
						Value:         latest.Codec.EncodeOrDie(pod),
 | 
			
		||||
						Value:         runtime.EncodeOrDie(codec, pod),
 | 
			
		||||
						CreatedIndex:  1,
 | 
			
		||||
						ModifiedIndex: 1,
 | 
			
		||||
						Nodes:         etcd.Nodes{},
 | 
			
		||||
					},
 | 
			
		||||
					&etcd.Node{
 | 
			
		||||
						Value:         latest.Codec.EncodeOrDie(pod),
 | 
			
		||||
						Value:         runtime.EncodeOrDie(codec, pod),
 | 
			
		||||
						CreatedIndex:  2,
 | 
			
		||||
						ModifiedIndex: 2,
 | 
			
		||||
						Nodes:         etcd.Nodes{},
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
@@ -113,7 +114,7 @@ func TestPollMinions(t *testing.T) {
 | 
			
		||||
		ml := &api.MinionList{Items: item.minions}
 | 
			
		||||
		handler := util.FakeHandler{
 | 
			
		||||
			StatusCode:   200,
 | 
			
		||||
			ResponseBody: latest.Codec.EncodeOrDie(ml),
 | 
			
		||||
			ResponseBody: runtime.EncodeOrDie(latest.Codec, ml),
 | 
			
		||||
			T:            t,
 | 
			
		||||
		}
 | 
			
		||||
		mux := http.NewServeMux()
 | 
			
		||||
@@ -140,7 +141,7 @@ func TestDefaultErrorFunc(t *testing.T) {
 | 
			
		||||
	testPod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
 | 
			
		||||
	handler := util.FakeHandler{
 | 
			
		||||
		StatusCode:   200,
 | 
			
		||||
		ResponseBody: latest.Codec.EncodeOrDie(testPod),
 | 
			
		||||
		ResponseBody: runtime.EncodeOrDie(latest.Codec, testPod),
 | 
			
		||||
		T:            t,
 | 
			
		||||
	}
 | 
			
		||||
	mux := http.NewServeMux()
 | 
			
		||||
@@ -259,7 +260,7 @@ func TestBind(t *testing.T) {
 | 
			
		||||
			t.Errorf("Unexpected error: %v", err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		expectedBody := latest.Codec.EncodeOrDie(item.binding)
 | 
			
		||||
		expectedBody := runtime.EncodeOrDie(latest.Codec, item.binding)
 | 
			
		||||
		handler.ValidateRequest(t, "/api/v1beta1/bindings", "POST", &expectedBody)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,8 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
			
		||||
@@ -90,9 +92,9 @@ func TestExtractObj(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestWatch(t *testing.T) {
 | 
			
		||||
	client := newEtcdClient()
 | 
			
		||||
	helper := tools.EtcdHelper{Client: client, Codec: latest.Codec, ResourceVersioner: runtime.DefaultResourceVersioner}
 | 
			
		||||
	helper := tools.EtcdHelper{Client: client, Codec: latest.Codec, ResourceVersioner: latest.ResourceVersioner}
 | 
			
		||||
	withEtcdKey(func(key string) {
 | 
			
		||||
		resp, err := client.Set(key, latest.Codec.EncodeOrDie(&api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
		resp, err := client.Set(key, runtime.EncodeOrDie(v1beta1.Codec, &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user