Merge pull request #1202 from lavalamp/fixApi3
Please expedite: the rarely attempted interface{} -> runtime.Object rename
This commit is contained in:
@@ -179,7 +179,7 @@ func runReplicationControllerTest(c *client.Client) {
|
||||
}
|
||||
|
||||
glog.Infof("Creating replication controllers")
|
||||
if _, err := c.CreateReplicationController(controllerRequest); err != nil {
|
||||
if _, err := c.CreateReplicationController(&controllerRequest); err != nil {
|
||||
glog.Fatalf("Unexpected error: %#v", err)
|
||||
}
|
||||
glog.Infof("Done creating replication controllers")
|
||||
@@ -194,7 +194,7 @@ func runReplicationControllerTest(c *client.Client) {
|
||||
if err != nil {
|
||||
glog.Fatalf("FAILED: unable to get pods to list: %v", err)
|
||||
}
|
||||
if err := wait.Poll(time.Second, time.Second*10, podsOnMinions(c, pods)); err != nil {
|
||||
if err := wait.Poll(time.Second, time.Second*10, podsOnMinions(c, *pods)); err != nil {
|
||||
glog.Fatalf("FAILED: pods never started running %v", err)
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ func runReplicationControllerTest(c *client.Client) {
|
||||
func runAtomicPutTest(c *client.Client) {
|
||||
var svc api.Service
|
||||
err := c.Post().Path("services").Body(
|
||||
api.Service{
|
||||
&api.Service{
|
||||
JSONBase: api.JSONBase{ID: "atomicservice", APIVersion: "v1beta1"},
|
||||
Port: 12345,
|
||||
Labels: map[string]string{
|
||||
|
||||
@@ -58,11 +58,11 @@ var (
|
||||
imageName = flag.String("image", "", "Image used when updating a replicationController. Will apply to the first container in the pod template.")
|
||||
)
|
||||
|
||||
var parser = kubecfg.NewParser(map[string]interface{}{
|
||||
"pods": api.Pod{},
|
||||
"services": api.Service{},
|
||||
"replicationControllers": api.ReplicationController{},
|
||||
"minions": api.Minion{},
|
||||
var parser = kubecfg.NewParser(map[string]runtime.Object{
|
||||
"pods": &api.Pod{},
|
||||
"services": &api.Service{},
|
||||
"replicationControllers": &api.ReplicationController{},
|
||||
"minions": &api.Minion{},
|
||||
})
|
||||
|
||||
func usage() {
|
||||
@@ -266,7 +266,7 @@ func executeAPIRequest(method string, c *client.Client) bool {
|
||||
if setBody {
|
||||
if version != 0 {
|
||||
data := readConfig(storage)
|
||||
obj, err := runtime.Decode(data)
|
||||
obj, err := runtime.DefaultCodec.Decode(data)
|
||||
if err != nil {
|
||||
glog.Fatalf("error setting resource version: %v", err)
|
||||
}
|
||||
@@ -275,7 +275,7 @@ func executeAPIRequest(method string, c *client.Client) bool {
|
||||
glog.Fatalf("error setting resource version: %v", err)
|
||||
}
|
||||
jsonBase.SetResourceVersion(version)
|
||||
data, err = runtime.Encode(obj)
|
||||
data, err = runtime.DefaultCodec.Encode(obj)
|
||||
if err != nil {
|
||||
glog.Fatalf("error setting resource version: %v", err)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func validateObject(obj interface{}) (errors []error) {
|
||||
func validateObject(obj runtime.Object) (errors []error) {
|
||||
switch t := obj.(type) {
|
||||
case *api.ReplicationController:
|
||||
errors = validation.ValidateManifest(&t.DesiredState.PodTemplate.DesiredState.Manifest)
|
||||
@@ -85,7 +85,7 @@ func walkJSONFiles(inDir string, fn func(name, path string, data []byte)) error
|
||||
}
|
||||
|
||||
func TestApiExamples(t *testing.T) {
|
||||
expected := map[string]interface{}{
|
||||
expected := map[string]runtime.Object{
|
||||
"controller": &api.ReplicationController{},
|
||||
"controller-list": &api.ReplicationControllerList{},
|
||||
"pod": &api.Pod{},
|
||||
@@ -103,7 +103,7 @@ func TestApiExamples(t *testing.T) {
|
||||
return
|
||||
}
|
||||
tested += 1
|
||||
if err := runtime.DecodeInto(data, expectedType); err != nil {
|
||||
if err := runtime.DefaultCodec.DecodeInto(data, expectedType); err != nil {
|
||||
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
|
||||
return
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func TestApiExamples(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestExamples(t *testing.T) {
|
||||
expected := map[string]interface{}{
|
||||
expected := map[string]runtime.Object{
|
||||
"frontend-controller": &api.ReplicationController{},
|
||||
"redis-slave-controller": &api.ReplicationController{},
|
||||
"redis-master": &api.Pod{},
|
||||
@@ -137,7 +137,7 @@ func TestExamples(t *testing.T) {
|
||||
return
|
||||
}
|
||||
tested += 1
|
||||
if err := runtime.DecodeInto(data, expectedType); err != nil {
|
||||
if err := runtime.DefaultCodec.DecodeInto(data, expectedType); err != nil {
|
||||
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
|
||||
return
|
||||
}
|
||||
@@ -168,14 +168,14 @@ func TestReadme(t *testing.T) {
|
||||
}
|
||||
for _, json := range match[1:] {
|
||||
expectedType := &api.Pod{}
|
||||
if err := runtime.DecodeInto([]byte(json), expectedType); err != nil {
|
||||
if err := runtime.DefaultCodec.DecodeInto([]byte(json), expectedType); err != nil {
|
||||
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
|
||||
return
|
||||
}
|
||||
if errors := validateObject(expectedType); len(errors) > 0 {
|
||||
t.Errorf("%s did not validate correctly: %v", path, errors)
|
||||
}
|
||||
encoded, err := runtime.Encode(expectedType)
|
||||
encoded, err := runtime.DefaultCodec.Encode(expectedType)
|
||||
if err != nil {
|
||||
t.Errorf("Could not encode object: %v", err)
|
||||
continue
|
||||
|
||||
@@ -21,21 +21,21 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.AddKnownTypes("",
|
||||
PodList{},
|
||||
Pod{},
|
||||
ReplicationControllerList{},
|
||||
ReplicationController{},
|
||||
ServiceList{},
|
||||
Service{},
|
||||
MinionList{},
|
||||
Minion{},
|
||||
Status{},
|
||||
ServerOpList{},
|
||||
ServerOp{},
|
||||
ContainerManifestList{},
|
||||
Endpoints{},
|
||||
EndpointsList{},
|
||||
Binding{},
|
||||
runtime.DefaultScheme.AddKnownTypes("",
|
||||
&PodList{},
|
||||
&Pod{},
|
||||
&ReplicationControllerList{},
|
||||
&ReplicationController{},
|
||||
&ServiceList{},
|
||||
&Service{},
|
||||
&MinionList{},
|
||||
&Minion{},
|
||||
&Status{},
|
||||
&ServerOpList{},
|
||||
&ServerOp{},
|
||||
&ContainerManifestList{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
&Binding{},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
|
||||
},
|
||||
)
|
||||
|
||||
func objDiff(a, b interface{}) string {
|
||||
func objDiff(a, b runtime.Object) string {
|
||||
ab, err := json.Marshal(a)
|
||||
if err != nil {
|
||||
panic("a")
|
||||
@@ -105,7 +105,7 @@ func objDiff(a, b interface{}) string {
|
||||
)
|
||||
}
|
||||
|
||||
func runTest(t *testing.T, source interface{}) {
|
||||
func runTest(t *testing.T, source runtime.Object) {
|
||||
name := reflect.TypeOf(source).Elem().Name()
|
||||
apiObjectFuzzer.Fuzz(source)
|
||||
j, err := runtime.FindJSONBase(source)
|
||||
@@ -115,13 +115,13 @@ func runTest(t *testing.T, source interface{}) {
|
||||
j.SetKind("")
|
||||
j.SetAPIVersion("")
|
||||
|
||||
data, err := runtime.Encode(source)
|
||||
data, err := runtime.DefaultCodec.Encode(source)
|
||||
if err != nil {
|
||||
t.Errorf("%v: %v (%#v)", name, err, source)
|
||||
return
|
||||
}
|
||||
|
||||
obj2, err := runtime.Decode(data)
|
||||
obj2, err := runtime.DefaultCodec.Decode(data)
|
||||
if err != nil {
|
||||
t.Errorf("%v: %v", name, err)
|
||||
return
|
||||
@@ -131,8 +131,8 @@ func runTest(t *testing.T, source interface{}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface()
|
||||
err = runtime.DecodeInto(data, obj3)
|
||||
obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface().(runtime.Object)
|
||||
err = runtime.DefaultCodec.DecodeInto(data, obj3)
|
||||
if err != nil {
|
||||
t.Errorf("2: %v: %v", name, err)
|
||||
return
|
||||
@@ -145,7 +145,7 @@ func runTest(t *testing.T, source interface{}) {
|
||||
}
|
||||
|
||||
func TestTypes(t *testing.T) {
|
||||
table := []interface{}{
|
||||
table := []runtime.Object{
|
||||
&api.PodList{},
|
||||
&api.Pod{},
|
||||
&api.ServiceList{},
|
||||
@@ -169,31 +169,13 @@ func TestTypes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode_NonPtr(t *testing.T) {
|
||||
pod := api.Pod{
|
||||
Labels: map[string]string{"name": "foo"},
|
||||
}
|
||||
obj := interface{}(pod)
|
||||
data, err := runtime.Encode(obj)
|
||||
obj2, err2 := runtime.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
}
|
||||
if _, ok := obj2.(*api.Pod); !ok {
|
||||
t.Fatalf("Got wrong type")
|
||||
}
|
||||
if !reflect.DeepEqual(obj2, &pod) {
|
||||
t.Errorf("Expected:\n %#v,\n Got:\n %#v", &pod, obj2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode_Ptr(t *testing.T) {
|
||||
pod := &api.Pod{
|
||||
Labels: map[string]string{"name": "foo"},
|
||||
}
|
||||
obj := interface{}(pod)
|
||||
data, err := runtime.Encode(obj)
|
||||
obj2, err2 := runtime.Decode(data)
|
||||
obj := runtime.Object(pod)
|
||||
data, err := runtime.DefaultCodec.Encode(obj)
|
||||
obj2, err2 := runtime.DefaultCodec.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
}
|
||||
@@ -207,11 +189,11 @@ func TestEncode_Ptr(t *testing.T) {
|
||||
|
||||
func TestBadJSONRejection(t *testing.T) {
|
||||
badJSONMissingKind := []byte(`{ }`)
|
||||
if _, err := runtime.Decode(badJSONMissingKind); err == nil {
|
||||
if _, err := runtime.DefaultCodec.Decode(badJSONMissingKind); err == nil {
|
||||
t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind)
|
||||
}
|
||||
badJSONUnknownType := []byte(`{"kind": "bar"}`)
|
||||
if _, err1 := runtime.Decode(badJSONUnknownType); err1 == nil {
|
||||
if _, err1 := runtime.DefaultCodec.Decode(badJSONUnknownType); err1 == nil {
|
||||
t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
|
||||
}
|
||||
/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)
|
||||
|
||||
@@ -65,6 +65,8 @@ type ContainerManifestList struct {
|
||||
Items []ContainerManifest `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ContainerManifestList) IsAnAPIObject() {}
|
||||
|
||||
// Volume represents a named volume in a pod that may be accessed by any containers in the pod.
|
||||
type Volume struct {
|
||||
// Required: This must be a DNS_LABEL. Each volume in a pod must have
|
||||
@@ -287,6 +289,8 @@ type PodList struct {
|
||||
Items []Pod `json:"items" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*PodList) IsAnAPIObject() {}
|
||||
|
||||
// Pod is a collection of containers, used as either input (create, update) or as output (list, get).
|
||||
type Pod struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@@ -295,6 +299,8 @@ type Pod struct {
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
|
||||
type ReplicationControllerState struct {
|
||||
Replicas int `json:"replicas" yaml:"replicas"`
|
||||
@@ -308,6 +314,8 @@ type ReplicationControllerList struct {
|
||||
Items []ReplicationController `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationControllerList) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationController represents the configuration of a replication controller.
|
||||
type ReplicationController struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@@ -315,6 +323,8 @@ type ReplicationController struct {
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationController) IsAnAPIObject() {}
|
||||
|
||||
// PodTemplate holds the information used for creating pods.
|
||||
type PodTemplate struct {
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
@@ -327,6 +337,8 @@ type ServiceList struct {
|
||||
Items []Service `json:"items" yaml:"items"`
|
||||
}
|
||||
|
||||
func (*ServiceList) IsAnAPIObject() {}
|
||||
|
||||
// Service is a named abstraction of software service (for example, mysql) consisting of local port
|
||||
// (for example 3306) that the proxy listens on, and the selector that determines which pods
|
||||
// will answer requests sent through the proxy.
|
||||
@@ -346,6 +358,8 @@ type Service struct {
|
||||
ContainerPort util.IntOrString `json:"containerPort,omitempty" yaml:"containerPort,omitempty"`
|
||||
}
|
||||
|
||||
func (*Service) IsAnAPIObject() {}
|
||||
|
||||
// Endpoints is a collection of endpoints that implement the actual service, for example:
|
||||
// Name: "mysql", Endpoints: ["10.10.1.1:1909", "10.10.2.2:8834"]
|
||||
type Endpoints struct {
|
||||
@@ -353,12 +367,16 @@ type Endpoints struct {
|
||||
Endpoints []string `json:"endpoints,omitempty" yaml:"endpoints,omitempty"`
|
||||
}
|
||||
|
||||
func (*Endpoints) IsAnAPIObject() {}
|
||||
|
||||
// EndpointsList is a list of endpoints.
|
||||
type EndpointsList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
Items []Endpoints `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*EndpointsList) IsAnAPIObject() {}
|
||||
|
||||
// Minion is a worker node in Kubernetenes.
|
||||
// The name of the minion according to etcd is in JSONBase.ID.
|
||||
type Minion struct {
|
||||
@@ -367,12 +385,16 @@ type Minion struct {
|
||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||
}
|
||||
|
||||
func (*Minion) IsAnAPIObject() {}
|
||||
|
||||
// MinionList is a list of minions.
|
||||
type MinionList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
Items []Minion `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
|
||||
// Binding is written by a scheduler to cause a pod to be bound to a host.
|
||||
type Binding struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@@ -380,6 +402,8 @@ type Binding struct {
|
||||
Host string `json:"host" yaml:"host"`
|
||||
}
|
||||
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
|
||||
// Status is a return value for calls that don't return other objects.
|
||||
// TODO: this could go in apiserver, but I'm including it here so clients needn't
|
||||
// import both.
|
||||
@@ -403,6 +427,8 @@ type Status struct {
|
||||
Code int `json:"code,omitempty" yaml:"code,omitempty"`
|
||||
}
|
||||
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
|
||||
// StatusDetails is a set of additional properties that MAY be set by the
|
||||
// server to provide additional information about a response. The Reason
|
||||
// field of a Status object defines what attributes will be set. Clients
|
||||
@@ -539,12 +565,16 @@ type ServerOp struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
|
||||
func (*ServerOp) IsAnAPIObject() {}
|
||||
|
||||
// ServerOpList is a list of operations, as delivered to API clients.
|
||||
type ServerOpList struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Items []ServerOp `yaml:"items,omitempty" json:"items,omitempty"`
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@@ -19,22 +19,20 @@ 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() {
|
||||
// Shortcut for sub-conversions. TODO: This should possibly be refactored
|
||||
// such that this convert function is passed to each conversion func.
|
||||
Convert := runtime.Convert
|
||||
runtime.AddConversionFuncs(
|
||||
runtime.DefaultScheme.AddConversionFuncs(
|
||||
// EnvVar's Key is deprecated in favor of Name.
|
||||
func(in *newer.EnvVar, out *EnvVar) error {
|
||||
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) error {
|
||||
func(in *EnvVar, out *newer.EnvVar, s conversion.Scope) error {
|
||||
out.Value = in.Value
|
||||
if in.Name != "" {
|
||||
out.Name = in.Name
|
||||
@@ -45,7 +43,7 @@ func init() {
|
||||
},
|
||||
|
||||
// Path & MountType are deprecated.
|
||||
func(in *newer.VolumeMount, out *VolumeMount) error {
|
||||
func(in *newer.VolumeMount, out *VolumeMount, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.ReadOnly = in.ReadOnly
|
||||
out.MountPath = in.MountPath
|
||||
@@ -53,7 +51,7 @@ func init() {
|
||||
out.MountType = "" // MountType is ignored.
|
||||
return nil
|
||||
},
|
||||
func(in *VolumeMount, out *newer.VolumeMount) error {
|
||||
func(in *VolumeMount, out *newer.VolumeMount, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.ReadOnly = in.ReadOnly
|
||||
if in.MountPath == "" {
|
||||
@@ -65,18 +63,18 @@ func init() {
|
||||
},
|
||||
|
||||
// MinionList.Items had a wrong name in v1beta1
|
||||
func(in *newer.MinionList, out *MinionList) error {
|
||||
Convert(&in.JSONBase, &out.JSONBase)
|
||||
Convert(&in.Items, &out.Items)
|
||||
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) error {
|
||||
Convert(&in.JSONBase, &out.JSONBase)
|
||||
func(in *MinionList, out *newer.MinionList, s conversion.Scope) error {
|
||||
s.Convert(&in.JSONBase, &out.JSONBase, 0)
|
||||
if len(in.Items) == 0 {
|
||||
Convert(&in.Minions, &out.Items)
|
||||
s.Convert(&in.Minions, &out.Items, 0)
|
||||
} else {
|
||||
Convert(&in.Items, &out.Items)
|
||||
s.Convert(&in.Items, &out.Items, 0)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
var Convert = runtime.Convert
|
||||
var Convert = runtime.DefaultScheme.Convert
|
||||
|
||||
func TestEnvConversion(t *testing.T) {
|
||||
nonCanonical := []v1beta1.EnvVar{
|
||||
|
||||
@@ -21,21 +21,21 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.AddKnownTypes("v1beta1",
|
||||
PodList{},
|
||||
Pod{},
|
||||
ReplicationControllerList{},
|
||||
ReplicationController{},
|
||||
ServiceList{},
|
||||
Service{},
|
||||
MinionList{},
|
||||
Minion{},
|
||||
Status{},
|
||||
ServerOpList{},
|
||||
ServerOp{},
|
||||
ContainerManifestList{},
|
||||
Endpoints{},
|
||||
EndpointsList{},
|
||||
Binding{},
|
||||
runtime.DefaultScheme.AddKnownTypes("v1beta1",
|
||||
&PodList{},
|
||||
&Pod{},
|
||||
&ReplicationControllerList{},
|
||||
&ReplicationController{},
|
||||
&ServiceList{},
|
||||
&Service{},
|
||||
&MinionList{},
|
||||
&Minion{},
|
||||
&Status{},
|
||||
&ServerOpList{},
|
||||
&ServerOp{},
|
||||
&ContainerManifestList{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
&Binding{},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ type ContainerManifestList struct {
|
||||
Items []ContainerManifest `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ContainerManifestList) IsAnAPIObject() {}
|
||||
|
||||
// Volume represents a named volume in a pod that may be accessed by any containers in the pod.
|
||||
type Volume struct {
|
||||
// Required: This must be a DNS_LABEL. Each volume in a pod must have
|
||||
@@ -243,6 +245,8 @@ type JSONBase struct {
|
||||
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
|
||||
}
|
||||
|
||||
func (*JSONBase) IsAnAPIObject() {}
|
||||
|
||||
// PodStatus represents a status of a pod.
|
||||
type PodStatus string
|
||||
|
||||
@@ -298,6 +302,8 @@ type PodList struct {
|
||||
Items []Pod `json:"items" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*PodList) IsAnAPIObject() {}
|
||||
|
||||
// Pod is a collection of containers, used as either input (create, update) or as output (list, get).
|
||||
type Pod struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@@ -306,6 +312,8 @@ type Pod struct {
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
|
||||
type ReplicationControllerState struct {
|
||||
Replicas int `json:"replicas" yaml:"replicas"`
|
||||
@@ -319,6 +327,8 @@ type ReplicationControllerList struct {
|
||||
Items []ReplicationController `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationControllerList) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationController represents the configuration of a replication controller.
|
||||
type ReplicationController struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@@ -326,6 +336,8 @@ type ReplicationController struct {
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationController) IsAnAPIObject() {}
|
||||
|
||||
// PodTemplate holds the information used for creating pods.
|
||||
type PodTemplate struct {
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
@@ -338,6 +350,8 @@ type ServiceList struct {
|
||||
Items []Service `json:"items" yaml:"items"`
|
||||
}
|
||||
|
||||
func (*ServiceList) IsAnAPIObject() {}
|
||||
|
||||
// Service is a named abstraction of software service (for example, mysql) consisting of local port
|
||||
// (for example 3306) that the proxy listens on, and the selector that determines which pods
|
||||
// will answer requests sent through the proxy.
|
||||
@@ -357,6 +371,8 @@ type Service struct {
|
||||
ContainerPort util.IntOrString `json:"containerPort,omitempty" yaml:"containerPort,omitempty"`
|
||||
}
|
||||
|
||||
func (*Service) IsAnAPIObject() {}
|
||||
|
||||
// Endpoints is a collection of endpoints that implement the actual service, for example:
|
||||
// Name: "mysql", Endpoints: ["10.10.1.1:1909", "10.10.2.2:8834"]
|
||||
type Endpoints struct {
|
||||
@@ -364,12 +380,16 @@ type Endpoints struct {
|
||||
Endpoints []string `json:"endpoints,omitempty" yaml:"endpoints,omitempty"`
|
||||
}
|
||||
|
||||
func (*Endpoints) IsAnAPIObject() {}
|
||||
|
||||
// EndpointsList is a list of endpoints.
|
||||
type EndpointsList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
Items []Endpoints `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*EndpointsList) IsAnAPIObject() {}
|
||||
|
||||
// Minion is a worker node in Kubernetenes.
|
||||
// The name of the minion according to etcd is in JSONBase.ID.
|
||||
type Minion struct {
|
||||
@@ -378,6 +398,8 @@ type Minion struct {
|
||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||
}
|
||||
|
||||
func (*Minion) IsAnAPIObject() {}
|
||||
|
||||
// MinionList is a list of minions.
|
||||
type MinionList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@@ -387,6 +409,8 @@ type MinionList struct {
|
||||
Items []Minion `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
|
||||
// Binding is written by a scheduler to cause a pod to be bound to a host.
|
||||
type Binding struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@@ -394,6 +418,8 @@ type Binding struct {
|
||||
Host string `json:"host" yaml:"host"`
|
||||
}
|
||||
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
|
||||
// Status is a return value for calls that don't return other objects.
|
||||
// TODO: this could go in apiserver, but I'm including it here so clients needn't
|
||||
// import both.
|
||||
@@ -417,6 +443,8 @@ type Status struct {
|
||||
Code int `json:"code,omitempty" yaml:"code,omitempty"`
|
||||
}
|
||||
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
|
||||
// StatusDetails is a set of additional properties that MAY be set by the
|
||||
// server to provide additional information about a response. The Reason
|
||||
// field of a Status object defines what attributes will be set. Clients
|
||||
@@ -540,12 +568,16 @@ type ServerOp struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
|
||||
func (*ServerOp) IsAnAPIObject() {}
|
||||
|
||||
// ServerOpList is a list of operations, as delivered to API clients.
|
||||
type ServerOpList struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Items []ServerOp `yaml:"items,omitempty" json:"items,omitempty"`
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@@ -27,17 +27,11 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/healthz"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// Codec defines methods for serializing and deserializing API objects.
|
||||
type Codec interface {
|
||||
Encode(obj interface{}) (data []byte, err error)
|
||||
Decode(data []byte) (interface{}, error)
|
||||
DecodeInto(data []byte, obj interface{}) error
|
||||
}
|
||||
|
||||
// mux is an object that can register http handlers.
|
||||
type mux interface {
|
||||
Handle(pattern string, handler http.Handler)
|
||||
@@ -53,7 +47,7 @@ type defaultAPIServer struct {
|
||||
// Handle returns a Handler function that expose the provided storage interfaces
|
||||
// as RESTful resources at prefix, serialized by codec, and also includes the support
|
||||
// http resources.
|
||||
func Handle(storage map[string]RESTStorage, codec Codec, prefix string) http.Handler {
|
||||
func Handle(storage map[string]RESTStorage, codec runtime.Codec, prefix string) http.Handler {
|
||||
group := NewAPIGroup(storage, codec)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
@@ -78,7 +72,7 @@ type APIGroup struct {
|
||||
// This is a helper method for registering multiple sets of REST handlers under different
|
||||
// prefixes onto a server.
|
||||
// TODO: add multitype codec serialization
|
||||
func NewAPIGroup(storage map[string]RESTStorage, codec Codec) *APIGroup {
|
||||
func NewAPIGroup(storage map[string]RESTStorage, codec runtime.Codec) *APIGroup {
|
||||
return &APIGroup{RESTHandler{
|
||||
storage: storage,
|
||||
codec: codec,
|
||||
@@ -147,7 +141,7 @@ func handleVersion(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
// writeJSON renders an object as JSON to the response.
|
||||
func writeJSON(statusCode int, codec Codec, object interface{}, w http.ResponseWriter) {
|
||||
func writeJSON(statusCode int, codec runtime.Codec, object runtime.Object, w http.ResponseWriter) {
|
||||
output, err := codec.Encode(object)
|
||||
if err != nil {
|
||||
errorJSON(err, codec, w)
|
||||
@@ -159,7 +153,7 @@ func writeJSON(statusCode int, codec Codec, object interface{}, w http.ResponseW
|
||||
}
|
||||
|
||||
// errorJSON renders an error to the response.
|
||||
func errorJSON(err error, codec Codec, w http.ResponseWriter) {
|
||||
func errorJSON(err error, codec runtime.Codec, w http.ResponseWriter) {
|
||||
status := errToAPIStatus(err)
|
||||
writeJSON(status.Code, codec, status, w)
|
||||
}
|
||||
|
||||
@@ -38,15 +38,15 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
func convert(obj interface{}) (interface{}, error) {
|
||||
func convert(obj runtime.Object) (runtime.Object, error) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
var codec = runtime.Codec
|
||||
var codec = runtime.DefaultCodec
|
||||
|
||||
func init() {
|
||||
runtime.AddKnownTypes("", Simple{}, SimpleList{})
|
||||
runtime.AddKnownTypes("v1beta1", Simple{}, SimpleList{})
|
||||
runtime.DefaultScheme.AddKnownTypes("", &Simple{}, &SimpleList{})
|
||||
runtime.DefaultScheme.AddKnownTypes("v1beta1", &Simple{}, &SimpleList{})
|
||||
}
|
||||
|
||||
type Simple struct {
|
||||
@@ -54,11 +54,15 @@ type Simple struct {
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (*Simple) IsAnAPIObject() {}
|
||||
|
||||
type SimpleList struct {
|
||||
api.JSONBase `yaml:",inline" json:",inline"`
|
||||
Items []Simple `yaml:"items,omitempty" json:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*SimpleList) IsAnAPIObject() {}
|
||||
|
||||
type SimpleRESTStorage struct {
|
||||
errors map[string]error
|
||||
list []Simple
|
||||
@@ -78,43 +82,43 @@ type SimpleRESTStorage struct {
|
||||
|
||||
// If non-nil, called inside the WorkFunc when answering update, delete, create.
|
||||
// obj receives the original input to the update, delete, or create call.
|
||||
injectedFunction func(obj interface{}) (returnObj interface{}, err error)
|
||||
injectedFunction func(obj runtime.Object) (returnObj runtime.Object, err error)
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) List(labels.Selector) (interface{}, error) {
|
||||
func (storage *SimpleRESTStorage) List(labels.Selector) (runtime.Object, error) {
|
||||
result := &SimpleList{
|
||||
Items: storage.list,
|
||||
}
|
||||
return result, storage.errors["list"]
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) Get(id string) (interface{}, error) {
|
||||
return storage.item, storage.errors["get"]
|
||||
func (storage *SimpleRESTStorage) Get(id string) (runtime.Object, error) {
|
||||
return runtime.DefaultScheme.CopyOrDie(&storage.item), storage.errors["get"]
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) Delete(id string) (<-chan interface{}, error) {
|
||||
func (storage *SimpleRESTStorage) Delete(id string) (<-chan runtime.Object, error) {
|
||||
storage.deleted = id
|
||||
if err := storage.errors["delete"]; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return MakeAsync(func() (interface{}, error) {
|
||||
return MakeAsync(func() (runtime.Object, error) {
|
||||
if storage.injectedFunction != nil {
|
||||
return storage.injectedFunction(id)
|
||||
return storage.injectedFunction(&Simple{JSONBase: api.JSONBase{ID: id}})
|
||||
}
|
||||
return &api.Status{Status: api.StatusSuccess}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) New() interface{} {
|
||||
func (storage *SimpleRESTStorage) New() runtime.Object {
|
||||
return &Simple{}
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
func (storage *SimpleRESTStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
storage.created = obj.(*Simple)
|
||||
if err := storage.errors["create"]; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return MakeAsync(func() (interface{}, error) {
|
||||
return MakeAsync(func() (runtime.Object, error) {
|
||||
if storage.injectedFunction != nil {
|
||||
return storage.injectedFunction(obj)
|
||||
}
|
||||
@@ -122,12 +126,12 @@ func (storage *SimpleRESTStorage) Create(obj interface{}) (<-chan interface{}, e
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) Update(obj interface{}) (<-chan interface{}, error) {
|
||||
func (storage *SimpleRESTStorage) Update(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
storage.updated = obj.(*Simple)
|
||||
if err := storage.errors["update"]; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return MakeAsync(func() (interface{}, error) {
|
||||
return MakeAsync(func() (runtime.Object, error) {
|
||||
if storage.injectedFunction != nil {
|
||||
return storage.injectedFunction(obj)
|
||||
}
|
||||
@@ -156,7 +160,7 @@ func (storage *SimpleRESTStorage) ResourceLocation(id string) (string, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func extractBody(response *http.Response, object interface{}) (string, error) {
|
||||
func extractBody(response *http.Response, object runtime.Object) (string, error) {
|
||||
defer response.Body.Close()
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
@@ -398,7 +402,7 @@ func TestUpdate(t *testing.T) {
|
||||
handler := Handle(storage, codec, "/prefix/version")
|
||||
server := httptest.NewServer(handler)
|
||||
|
||||
item := Simple{
|
||||
item := &Simple{
|
||||
Name: "bar",
|
||||
}
|
||||
body, err := codec.Encode(item)
|
||||
@@ -428,7 +432,7 @@ func TestUpdateMissing(t *testing.T) {
|
||||
handler := Handle(storage, codec, "/prefix/version")
|
||||
server := httptest.NewServer(handler)
|
||||
|
||||
item := Simple{
|
||||
item := &Simple{
|
||||
Name: "bar",
|
||||
}
|
||||
body, err := codec.Encode(item)
|
||||
@@ -457,7 +461,7 @@ func TestCreate(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
client := http.Client{}
|
||||
|
||||
simple := Simple{
|
||||
simple := &Simple{
|
||||
Name: "foo",
|
||||
}
|
||||
data, _ := codec.Encode(simple)
|
||||
@@ -497,7 +501,7 @@ func TestCreateNotFound(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
client := http.Client{}
|
||||
|
||||
simple := Simple{Name: "foo"}
|
||||
simple := &Simple{Name: "foo"}
|
||||
data, _ := codec.Encode(simple)
|
||||
request, err := http.NewRequest("POST", server.URL+"/prefix/version/simple", bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
@@ -528,7 +532,7 @@ func TestParseTimeout(t *testing.T) {
|
||||
|
||||
func TestSyncCreate(t *testing.T) {
|
||||
storage := SimpleRESTStorage{
|
||||
injectedFunction: func(obj interface{}) (interface{}, error) {
|
||||
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
return obj, nil
|
||||
},
|
||||
@@ -539,7 +543,7 @@ func TestSyncCreate(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
client := http.Client{}
|
||||
|
||||
simple := Simple{
|
||||
simple := &Simple{
|
||||
Name: "foo",
|
||||
}
|
||||
data, _ := codec.Encode(simple)
|
||||
@@ -566,7 +570,7 @@ func TestSyncCreate(t *testing.T) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(itemOut, simple) {
|
||||
if !reflect.DeepEqual(&itemOut, simple) {
|
||||
t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simple, string(body))
|
||||
}
|
||||
if response.StatusCode != http.StatusOK {
|
||||
@@ -600,7 +604,7 @@ func expectApiStatus(t *testing.T, method, url string, data []byte, code int) *a
|
||||
|
||||
func TestAsyncDelayReturnsError(t *testing.T) {
|
||||
storage := SimpleRESTStorage{
|
||||
injectedFunction: func(obj interface{}) (interface{}, error) {
|
||||
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
||||
return nil, apierrs.NewAlreadyExists("foo", "bar")
|
||||
},
|
||||
}
|
||||
@@ -617,7 +621,7 @@ func TestAsyncDelayReturnsError(t *testing.T) {
|
||||
func TestAsyncCreateError(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
storage := SimpleRESTStorage{
|
||||
injectedFunction: func(obj interface{}) (interface{}, error) {
|
||||
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
||||
<-ch
|
||||
return nil, apierrs.NewAlreadyExists("foo", "bar")
|
||||
},
|
||||
@@ -626,7 +630,7 @@ func TestAsyncCreateError(t *testing.T) {
|
||||
handler.(*defaultAPIServer).group.handler.asyncOpWait = 0
|
||||
server := httptest.NewServer(handler)
|
||||
|
||||
simple := Simple{Name: "foo"}
|
||||
simple := &Simple{Name: "foo"}
|
||||
data, _ := codec.Encode(simple)
|
||||
|
||||
status := expectApiStatus(t, "POST", fmt.Sprintf("%s/prefix/version/foo", server.URL), data, http.StatusAccepted)
|
||||
@@ -662,18 +666,21 @@ func TestAsyncCreateError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type UnregisteredAPIObject struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
func (*UnregisteredAPIObject) IsAnAPIObject() {}
|
||||
|
||||
func TestWriteJSONDecodeError(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
type T struct {
|
||||
Value string
|
||||
}
|
||||
writeJSON(http.StatusOK, runtime.Codec, &T{"Undecodable"}, w)
|
||||
writeJSON(http.StatusOK, runtime.DefaultCodec, &UnregisteredAPIObject{"Undecodable"}, w)
|
||||
}))
|
||||
status := expectApiStatus(t, "GET", server.URL, nil, http.StatusInternalServerError)
|
||||
if status.Reason != api.StatusReasonUnknown {
|
||||
t.Errorf("unexpected reason %#v", status)
|
||||
}
|
||||
if !strings.Contains(status.Message, "type apiserver.T is not registered") {
|
||||
if !strings.Contains(status.Message, "type apiserver.UnregisteredAPIObject is not registered") {
|
||||
t.Errorf("unexpected message %#v", status)
|
||||
}
|
||||
}
|
||||
@@ -705,7 +712,7 @@ func TestSyncCreateTimeout(t *testing.T) {
|
||||
testOver := make(chan struct{})
|
||||
defer close(testOver)
|
||||
storage := SimpleRESTStorage{
|
||||
injectedFunction: func(obj interface{}) (interface{}, error) {
|
||||
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
||||
// Eliminate flakes by ensuring the create operation takes longer than this test.
|
||||
<-testOver
|
||||
return obj, nil
|
||||
@@ -716,7 +723,7 @@ func TestSyncCreateTimeout(t *testing.T) {
|
||||
}, codec, "/prefix/version")
|
||||
server := httptest.NewServer(handler)
|
||||
|
||||
simple := Simple{Name: "foo"}
|
||||
simple := &Simple{Name: "foo"}
|
||||
data, _ := codec.Encode(simple)
|
||||
itemOut := expectApiStatus(t, "POST", server.URL+"/prefix/version/foo?sync=true&timeout=4ms", data, http.StatusAccepted)
|
||||
if itemOut.Status != api.StatusWorking || itemOut.Details == nil || itemOut.Details.ID == "" {
|
||||
|
||||
@@ -17,18 +17,19 @@ limitations under the License.
|
||||
package apiserver
|
||||
|
||||
import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
// WorkFunc is used to perform any time consuming work for an api call, after
|
||||
// the input has been validated. Pass one of these to MakeAsync to create an
|
||||
// appropriate return value for the Update, Delete, and Create methods.
|
||||
type WorkFunc func() (result interface{}, err error)
|
||||
type WorkFunc func() (result runtime.Object, err error)
|
||||
|
||||
// MakeAsync takes a function and executes it, delivering the result in the way required
|
||||
// by RESTStorage's Update, Delete, and Create methods.
|
||||
func MakeAsync(fn WorkFunc) <-chan interface{} {
|
||||
channel := make(chan interface{})
|
||||
func MakeAsync(fn WorkFunc) <-chan runtime.Object {
|
||||
channel := make(chan runtime.Object)
|
||||
go func() {
|
||||
defer util.HandleCrash()
|
||||
obj, err := fn()
|
||||
|
||||
@@ -18,6 +18,7 @@ package apiserver
|
||||
|
||||
import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
@@ -25,25 +26,25 @@ import (
|
||||
// Resources which are exported to the RESTful API of apiserver need to implement this interface.
|
||||
type RESTStorage interface {
|
||||
// New returns an empty object that can be used with Create and Update after request data has been put into it.
|
||||
// This object must be a pointer type for use with Codec.DecodeInto([]byte, interface{})
|
||||
New() interface{}
|
||||
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
|
||||
New() runtime.Object
|
||||
|
||||
// List selects resources in the storage which match to the selector.
|
||||
// TODO: add field selector in addition to label selector.
|
||||
List(labels.Selector) (interface{}, error)
|
||||
List(labels.Selector) (runtime.Object, error)
|
||||
|
||||
// Get finds a resource in the storage by id and returns it.
|
||||
// Although it can return an arbitrary error value, IsNotFound(err) is true for the
|
||||
// returned error value err when the specified resource is not found.
|
||||
Get(id string) (interface{}, error)
|
||||
Get(id string) (runtime.Object, error)
|
||||
|
||||
// Delete finds a resource in the storage and deletes it.
|
||||
// Although it can return an arbitrary error value, IsNotFound(err) is true for the
|
||||
// returned error value err when the specified resource is not found.
|
||||
Delete(id string) (<-chan interface{}, error)
|
||||
Delete(id string) (<-chan runtime.Object, error)
|
||||
|
||||
Create(interface{}) (<-chan interface{}, error)
|
||||
Update(interface{}) (<-chan interface{}, error)
|
||||
Create(runtime.Object) (<-chan runtime.Object, error)
|
||||
Update(runtime.Object) (<-chan runtime.Object, error)
|
||||
}
|
||||
|
||||
// ResourceWatcher should be implemented by all RESTStorage objects that
|
||||
|
||||
@@ -25,12 +25,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
type OperationHandler struct {
|
||||
ops *Operations
|
||||
codec Codec
|
||||
codec runtime.Codec
|
||||
}
|
||||
|
||||
func (h *OperationHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
@@ -63,8 +64,8 @@ func (h *OperationHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
// Operation represents an ongoing action which the server is performing.
|
||||
type Operation struct {
|
||||
ID string
|
||||
result interface{}
|
||||
awaiting <-chan interface{}
|
||||
result runtime.Object
|
||||
awaiting <-chan runtime.Object
|
||||
finished *time.Time
|
||||
lock sync.Mutex
|
||||
notify chan struct{}
|
||||
@@ -90,7 +91,7 @@ func NewOperations() *Operations {
|
||||
}
|
||||
|
||||
// NewOperation adds a new operation. It is lock-free.
|
||||
func (ops *Operations) NewOperation(from <-chan interface{}) *Operation {
|
||||
func (ops *Operations) NewOperation(from <-chan runtime.Object) *Operation {
|
||||
id := atomic.AddInt64(&ops.lastID, 1)
|
||||
op := &Operation{
|
||||
ID: strconv.FormatInt(id, 10),
|
||||
@@ -110,7 +111,7 @@ func (ops *Operations) insert(op *Operation) {
|
||||
}
|
||||
|
||||
// List lists operations for an API client.
|
||||
func (ops *Operations) List() api.ServerOpList {
|
||||
func (ops *Operations) List() *api.ServerOpList {
|
||||
ops.lock.Lock()
|
||||
defer ops.lock.Unlock()
|
||||
|
||||
@@ -119,7 +120,7 @@ func (ops *Operations) List() api.ServerOpList {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
sort.StringSlice(ids).Sort()
|
||||
ol := api.ServerOpList{}
|
||||
ol := &api.ServerOpList{}
|
||||
for _, id := range ids {
|
||||
ol.Items = append(ol.Items, api.ServerOp{JSONBase: api.JSONBase{ID: id}})
|
||||
}
|
||||
@@ -185,7 +186,7 @@ func (op *Operation) expired(limitTime time.Time) bool {
|
||||
|
||||
// StatusOrResult returns status information or the result of the operation if it is complete,
|
||||
// with a bool indicating true in the latter case.
|
||||
func (op *Operation) StatusOrResult() (description interface{}, finished bool) {
|
||||
func (op *Operation) StatusOrResult() (description runtime.Object, finished bool) {
|
||||
op.lock.Lock()
|
||||
defer op.lock.Unlock()
|
||||
|
||||
|
||||
@@ -28,12 +28,13 @@ import (
|
||||
// TODO: remove dependency on api, apiserver should be generic
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func TestOperation(t *testing.T) {
|
||||
ops := NewOperations()
|
||||
|
||||
c := make(chan interface{})
|
||||
c := make(chan runtime.Object)
|
||||
op := ops.NewOperation(c)
|
||||
// Allow context switch, so that op's ID can get added to the map and Get will work.
|
||||
// This is just so we can test Get. Ordinary users have no need to call Get immediately
|
||||
@@ -41,7 +42,7 @@ func TestOperation(t *testing.T) {
|
||||
time.Sleep(time.Millisecond)
|
||||
go func() {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
c <- "All done"
|
||||
c <- &Simple{JSONBase: api.JSONBase{ID: "All done"}}
|
||||
}()
|
||||
|
||||
if op.expired(time.Now().Add(-time.Minute)) {
|
||||
@@ -89,7 +90,7 @@ func TestOperation(t *testing.T) {
|
||||
t.Errorf("expire failed to remove the operation %#v", ops)
|
||||
}
|
||||
|
||||
if op.result.(string) != "All done" {
|
||||
if op.result.(*Simple).ID != "All done" {
|
||||
t.Errorf("Got unexpected result: %#v", op.result)
|
||||
}
|
||||
}
|
||||
@@ -98,7 +99,7 @@ func TestOperationsList(t *testing.T) {
|
||||
testOver := make(chan struct{})
|
||||
defer close(testOver)
|
||||
simpleStorage := &SimpleRESTStorage{
|
||||
injectedFunction: func(obj interface{}) (interface{}, error) {
|
||||
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
||||
// Eliminate flakes by ensuring the create operation takes longer than this test.
|
||||
<-testOver
|
||||
return obj, nil
|
||||
@@ -111,7 +112,7 @@ func TestOperationsList(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
client := http.Client{}
|
||||
|
||||
simple := Simple{
|
||||
simple := &Simple{
|
||||
Name: "foo",
|
||||
}
|
||||
data, err := codec.Encode(simple)
|
||||
@@ -154,7 +155,7 @@ func TestOpGet(t *testing.T) {
|
||||
testOver := make(chan struct{})
|
||||
defer close(testOver)
|
||||
simpleStorage := &SimpleRESTStorage{
|
||||
injectedFunction: func(obj interface{}) (interface{}, error) {
|
||||
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
||||
// Eliminate flakes by ensuring the create operation takes longer than this test.
|
||||
<-testOver
|
||||
return obj, nil
|
||||
@@ -167,7 +168,7 @@ func TestOpGet(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
client := http.Client{}
|
||||
|
||||
simple := Simple{
|
||||
simple := &Simple{
|
||||
Name: "foo",
|
||||
}
|
||||
data, err := codec.Encode(simple)
|
||||
|
||||
@@ -20,11 +20,12 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
type RedirectHandler struct {
|
||||
storage map[string]RESTStorage
|
||||
codec Codec
|
||||
codec runtime.Codec
|
||||
}
|
||||
|
||||
func (r *RedirectHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
@@ -23,11 +23,12 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
type RESTHandler struct {
|
||||
storage map[string]RESTStorage
|
||||
codec Codec
|
||||
codec runtime.Codec
|
||||
ops *Operations
|
||||
asyncOpWait time.Duration
|
||||
}
|
||||
@@ -158,7 +159,7 @@ func (h *RESTHandler) handleRESTStorage(parts []string, req *http.Request, w htt
|
||||
}
|
||||
|
||||
// createOperation creates an operation to process a channel response.
|
||||
func (h *RESTHandler) createOperation(out <-chan interface{}, sync bool, timeout time.Duration) *Operation {
|
||||
func (h *RESTHandler) createOperation(out <-chan runtime.Object, sync bool, timeout time.Duration) *Operation {
|
||||
op := h.ops.NewOperation(out)
|
||||
if sync {
|
||||
op.WaitFor(timeout)
|
||||
@@ -175,11 +176,6 @@ func (h *RESTHandler) finishReq(op *Operation, w http.ResponseWriter) {
|
||||
if complete {
|
||||
status := http.StatusOK
|
||||
switch stat := obj.(type) {
|
||||
case api.Status:
|
||||
httplog.LogOf(w).Addf("programmer error: use *api.Status as a result, not api.Status.")
|
||||
if stat.Code != 0 {
|
||||
status = stat.Code
|
||||
}
|
||||
case *api.Status:
|
||||
if stat.Code != 0 {
|
||||
status = stat.Code
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
|
||||
type WatchHandler struct {
|
||||
storage map[string]RESTStorage
|
||||
codec Codec
|
||||
codec runtime.Codec
|
||||
}
|
||||
|
||||
func getWatchParams(query url.Values) (label, field labels.Selector, resourceVersion uint64) {
|
||||
|
||||
@@ -26,12 +26,13 @@ import (
|
||||
|
||||
"code.google.com/p/go.net/websocket"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
var watchTestTable = []struct {
|
||||
t watch.EventType
|
||||
obj interface{}
|
||||
obj runtime.Object
|
||||
}{
|
||||
{watch.Added, &Simple{Name: "A Name"}},
|
||||
{watch.Modified, &Simple{Name: "Another Name"}},
|
||||
@@ -56,7 +57,7 @@ func TestWatchWebsocket(t *testing.T) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
try := func(action watch.EventType, object interface{}) {
|
||||
try := func(action watch.EventType, object runtime.Object) {
|
||||
// Send
|
||||
simpleStorage.fakeWatch.Action(action, object)
|
||||
// Test receive
|
||||
@@ -113,7 +114,7 @@ func TestWatchHTTP(t *testing.T) {
|
||||
|
||||
decoder := json.NewDecoder(response.Body)
|
||||
|
||||
try := func(action watch.EventType, object interface{}) {
|
||||
try := func(action watch.EventType, object runtime.Object) {
|
||||
// Send
|
||||
simpleStorage.fakeWatch.Action(action, object)
|
||||
// Test receive
|
||||
|
||||
@@ -46,36 +46,36 @@ type Interface interface {
|
||||
|
||||
// PodInterface has methods to work with Pod resources.
|
||||
type PodInterface interface {
|
||||
ListPods(selector labels.Selector) (api.PodList, error)
|
||||
GetPod(id string) (api.Pod, error)
|
||||
ListPods(selector labels.Selector) (*api.PodList, error)
|
||||
GetPod(id string) (*api.Pod, error)
|
||||
DeletePod(id string) error
|
||||
CreatePod(api.Pod) (api.Pod, error)
|
||||
UpdatePod(api.Pod) (api.Pod, error)
|
||||
CreatePod(*api.Pod) (*api.Pod, error)
|
||||
UpdatePod(*api.Pod) (*api.Pod, error)
|
||||
}
|
||||
|
||||
// ReplicationControllerInterface has methods to work with ReplicationController resources.
|
||||
type ReplicationControllerInterface interface {
|
||||
ListReplicationControllers(selector labels.Selector) (api.ReplicationControllerList, error)
|
||||
GetReplicationController(id string) (api.ReplicationController, error)
|
||||
CreateReplicationController(api.ReplicationController) (api.ReplicationController, error)
|
||||
UpdateReplicationController(api.ReplicationController) (api.ReplicationController, error)
|
||||
ListReplicationControllers(selector labels.Selector) (*api.ReplicationControllerList, error)
|
||||
GetReplicationController(id string) (*api.ReplicationController, error)
|
||||
CreateReplicationController(*api.ReplicationController) (*api.ReplicationController, error)
|
||||
UpdateReplicationController(*api.ReplicationController) (*api.ReplicationController, error)
|
||||
DeleteReplicationController(string) error
|
||||
WatchReplicationControllers(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// ServiceInterface has methods to work with Service resources.
|
||||
type ServiceInterface interface {
|
||||
ListServices(selector labels.Selector) (api.ServiceList, error)
|
||||
GetService(id string) (api.Service, error)
|
||||
CreateService(api.Service) (api.Service, error)
|
||||
UpdateService(api.Service) (api.Service, error)
|
||||
ListServices(selector labels.Selector) (*api.ServiceList, error)
|
||||
GetService(id string) (*api.Service, error)
|
||||
CreateService(*api.Service) (*api.Service, error)
|
||||
UpdateService(*api.Service) (*api.Service, error)
|
||||
DeleteService(string) error
|
||||
WatchServices(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// EndpointsInterface has methods to work with Endpoints resources
|
||||
type EndpointsInterface interface {
|
||||
ListEndpoints(selector labels.Selector) (api.EndpointsList, error)
|
||||
ListEndpoints(selector labels.Selector) (*api.EndpointsList, error)
|
||||
WatchEndpoints(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error)
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ type VersionInterface interface {
|
||||
}
|
||||
|
||||
type MinionInterface interface {
|
||||
ListMinions() (api.MinionList, error)
|
||||
ListMinions() (*api.MinionList, error)
|
||||
}
|
||||
|
||||
// Client is the actual implementation of a Kubernetes client.
|
||||
@@ -222,7 +222,7 @@ func (c *RESTClient) doRequest(request *http.Request) ([]byte, error) {
|
||||
// Did the server give us a status response?
|
||||
isStatusResponse := false
|
||||
var status api.Status
|
||||
if err := runtime.DecodeInto(body, &status); err == nil && status.Status != "" {
|
||||
if err := runtime.DefaultCodec.DecodeInto(body, &status); err == nil && status.Status != "" {
|
||||
isStatusResponse = true
|
||||
}
|
||||
|
||||
@@ -247,14 +247,16 @@ func (c *RESTClient) doRequest(request *http.Request) ([]byte, error) {
|
||||
}
|
||||
|
||||
// ListPods takes a selector, and returns the list of pods that match that selector.
|
||||
func (c *Client) ListPods(selector labels.Selector) (result api.PodList, err error) {
|
||||
err = c.Get().Path("pods").SelectorParam("labels", selector).Do().Into(&result)
|
||||
func (c *Client) ListPods(selector labels.Selector) (result *api.PodList, err error) {
|
||||
result = &api.PodList{}
|
||||
err = c.Get().Path("pods").SelectorParam("labels", selector).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// GetPod takes the id of the pod, and returns the corresponding Pod object, and an error if it occurs
|
||||
func (c *Client) GetPod(id string) (result api.Pod, err error) {
|
||||
err = c.Get().Path("pods").Path(id).Do().Into(&result)
|
||||
func (c *Client) GetPod(id string) (result *api.Pod, err error) {
|
||||
result = &api.Pod{}
|
||||
err = c.Get().Path("pods").Path(id).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -264,46 +266,52 @@ func (c *Client) DeletePod(id string) error {
|
||||
}
|
||||
|
||||
// CreatePod takes the representation of a pod. Returns the server's representation of the pod, and an error, if it occurs.
|
||||
func (c *Client) CreatePod(pod api.Pod) (result api.Pod, err error) {
|
||||
err = c.Post().Path("pods").Body(pod).Do().Into(&result)
|
||||
func (c *Client) CreatePod(pod *api.Pod) (result *api.Pod, err error) {
|
||||
result = &api.Pod{}
|
||||
err = c.Post().Path("pods").Body(pod).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdatePod takes the representation of a pod to update. Returns the server's representation of the pod, and an error, if it occurs.
|
||||
func (c *Client) UpdatePod(pod api.Pod) (result api.Pod, err error) {
|
||||
func (c *Client) UpdatePod(pod *api.Pod) (result *api.Pod, err error) {
|
||||
result = &api.Pod{}
|
||||
if pod.ResourceVersion == 0 {
|
||||
err = fmt.Errorf("invalid update object, missing resource version: %v", pod)
|
||||
return
|
||||
}
|
||||
err = c.Put().Path("pods").Path(pod.ID).Body(pod).Do().Into(&result)
|
||||
err = c.Put().Path("pods").Path(pod.ID).Body(pod).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// ListReplicationControllers takes a selector, and returns the list of replication controllers that match that selector.
|
||||
func (c *Client) ListReplicationControllers(selector labels.Selector) (result api.ReplicationControllerList, err error) {
|
||||
err = c.Get().Path("replicationControllers").SelectorParam("labels", selector).Do().Into(&result)
|
||||
func (c *Client) ListReplicationControllers(selector labels.Selector) (result *api.ReplicationControllerList, err error) {
|
||||
result = &api.ReplicationControllerList{}
|
||||
err = c.Get().Path("replicationControllers").SelectorParam("labels", selector).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// GetReplicationController returns information about a particular replication controller.
|
||||
func (c *Client) GetReplicationController(id string) (result api.ReplicationController, err error) {
|
||||
err = c.Get().Path("replicationControllers").Path(id).Do().Into(&result)
|
||||
func (c *Client) GetReplicationController(id string) (result *api.ReplicationController, err error) {
|
||||
result = &api.ReplicationController{}
|
||||
err = c.Get().Path("replicationControllers").Path(id).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateReplicationController creates a new replication controller.
|
||||
func (c *Client) CreateReplicationController(controller api.ReplicationController) (result api.ReplicationController, err error) {
|
||||
err = c.Post().Path("replicationControllers").Body(controller).Do().Into(&result)
|
||||
func (c *Client) CreateReplicationController(controller *api.ReplicationController) (result *api.ReplicationController, err error) {
|
||||
result = &api.ReplicationController{}
|
||||
err = c.Post().Path("replicationControllers").Body(controller).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateReplicationController updates an existing replication controller.
|
||||
func (c *Client) UpdateReplicationController(controller api.ReplicationController) (result api.ReplicationController, err error) {
|
||||
func (c *Client) UpdateReplicationController(controller *api.ReplicationController) (result *api.ReplicationController, err error) {
|
||||
result = &api.ReplicationController{}
|
||||
if controller.ResourceVersion == 0 {
|
||||
err = fmt.Errorf("invalid update object, missing resource version: %v", controller)
|
||||
return
|
||||
}
|
||||
err = c.Put().Path("replicationControllers").Path(controller.ID).Body(controller).Do().Into(&result)
|
||||
err = c.Put().Path("replicationControllers").Path(controller.ID).Body(controller).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -324,30 +332,34 @@ func (c *Client) WatchReplicationControllers(label, field labels.Selector, resou
|
||||
}
|
||||
|
||||
// ListServices takes a selector, and returns the list of services that match that selector
|
||||
func (c *Client) ListServices(selector labels.Selector) (result api.ServiceList, err error) {
|
||||
err = c.Get().Path("services").SelectorParam("labels", selector).Do().Into(&result)
|
||||
func (c *Client) ListServices(selector labels.Selector) (result *api.ServiceList, err error) {
|
||||
result = &api.ServiceList{}
|
||||
err = c.Get().Path("services").SelectorParam("labels", selector).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// GetService returns information about a particular service.
|
||||
func (c *Client) GetService(id string) (result api.Service, err error) {
|
||||
err = c.Get().Path("services").Path(id).Do().Into(&result)
|
||||
func (c *Client) GetService(id string) (result *api.Service, err error) {
|
||||
result = &api.Service{}
|
||||
err = c.Get().Path("services").Path(id).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateService creates a new service.
|
||||
func (c *Client) CreateService(svc api.Service) (result api.Service, err error) {
|
||||
err = c.Post().Path("services").Body(svc).Do().Into(&result)
|
||||
func (c *Client) CreateService(svc *api.Service) (result *api.Service, err error) {
|
||||
result = &api.Service{}
|
||||
err = c.Post().Path("services").Body(svc).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateService updates an existing service.
|
||||
func (c *Client) UpdateService(svc api.Service) (result api.Service, err error) {
|
||||
func (c *Client) UpdateService(svc *api.Service) (result *api.Service, err error) {
|
||||
result = &api.Service{}
|
||||
if svc.ResourceVersion == 0 {
|
||||
err = fmt.Errorf("invalid update object, missing resource version: %v", svc)
|
||||
return
|
||||
}
|
||||
err = c.Put().Path("services").Path(svc.ID).Body(svc).Do().Into(&result)
|
||||
err = c.Put().Path("services").Path(svc.ID).Body(svc).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -368,8 +380,9 @@ func (c *Client) WatchServices(label, field labels.Selector, resourceVersion uin
|
||||
}
|
||||
|
||||
// ListEndpoints takes a selector, and returns the list of endpoints that match that selector
|
||||
func (c *Client) ListEndpoints(selector labels.Selector) (result api.EndpointsList, err error) {
|
||||
err = c.Get().Path("endpoints").SelectorParam("labels", selector).Do().Into(&result)
|
||||
func (c *Client) ListEndpoints(selector labels.Selector) (result *api.EndpointsList, err error) {
|
||||
result = &api.EndpointsList{}
|
||||
err = c.Get().Path("endpoints").SelectorParam("labels", selector).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -399,7 +412,8 @@ func (c *Client) ServerVersion() (*version.Info, error) {
|
||||
}
|
||||
|
||||
// ListMinions lists all the minions in the cluster.
|
||||
func (c *Client) ListMinions() (minionList api.MinionList, err error) {
|
||||
err = c.Get().Path("minions").Do().Into(&minionList)
|
||||
func (c *Client) ListMinions() (result *api.MinionList, err error) {
|
||||
result = &api.MinionList{}
|
||||
err = c.Get().Path("minions").Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func TestValidatesHostParameter(t *testing.T) {
|
||||
func TestListEmptyPods(t *testing.T) {
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "GET", Path: "/pods"},
|
||||
Response: Response{StatusCode: 200, Body: api.PodList{}},
|
||||
Response: Response{StatusCode: 200, Body: &api.PodList{}},
|
||||
}
|
||||
podList, err := c.Setup().ListPods(labels.Everything())
|
||||
c.Validate(t, podList, err)
|
||||
@@ -83,7 +83,7 @@ func TestListPods(t *testing.T) {
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "GET", Path: "/pods"},
|
||||
Response: Response{StatusCode: 200,
|
||||
Body: api.PodList{
|
||||
Body: &api.PodList{
|
||||
Items: []api.Pod{
|
||||
{
|
||||
CurrentState: api.PodState{
|
||||
@@ -113,7 +113,7 @@ func TestListPodsLabels(t *testing.T) {
|
||||
Request: testRequest{Method: "GET", Path: "/pods", Query: url.Values{"labels": []string{"foo=bar,name=baz"}}},
|
||||
Response: Response{
|
||||
StatusCode: 200,
|
||||
Body: api.PodList{
|
||||
Body: &api.PodList{
|
||||
Items: []api.Pod{
|
||||
{
|
||||
CurrentState: api.PodState{
|
||||
@@ -140,7 +140,7 @@ func TestGetPod(t *testing.T) {
|
||||
Request: testRequest{Method: "GET", Path: "/pods/foo"},
|
||||
Response: Response{
|
||||
StatusCode: 200,
|
||||
Body: api.Pod{
|
||||
Body: &api.Pod{
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
},
|
||||
@@ -165,7 +165,7 @@ func TestDeletePod(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreatePod(t *testing.T) {
|
||||
requestPod := api.Pod{
|
||||
requestPod := &api.Pod{
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
},
|
||||
@@ -186,7 +186,7 @@ func TestCreatePod(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdatePod(t *testing.T) {
|
||||
requestPod := api.Pod{
|
||||
requestPod := &api.Pod{
|
||||
JSONBase: api.JSONBase{ID: "foo", ResourceVersion: 1},
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
@@ -208,7 +208,7 @@ func TestListControllers(t *testing.T) {
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "GET", Path: "/replicationControllers"},
|
||||
Response: Response{StatusCode: 200,
|
||||
Body: api.ReplicationControllerList{
|
||||
Body: &api.ReplicationControllerList{
|
||||
Items: []api.ReplicationController{
|
||||
{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
@@ -234,7 +234,7 @@ func TestGetController(t *testing.T) {
|
||||
Request: testRequest{Method: "GET", Path: "/replicationControllers/foo"},
|
||||
Response: Response{
|
||||
StatusCode: 200,
|
||||
Body: api.ReplicationController{
|
||||
Body: &api.ReplicationController{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
DesiredState: api.ReplicationControllerState{
|
||||
Replicas: 2,
|
||||
@@ -251,14 +251,14 @@ func TestGetController(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateController(t *testing.T) {
|
||||
requestController := api.ReplicationController{
|
||||
requestController := &api.ReplicationController{
|
||||
JSONBase: api.JSONBase{ID: "foo", ResourceVersion: 1},
|
||||
}
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "PUT", Path: "/replicationControllers/foo"},
|
||||
Response: Response{
|
||||
StatusCode: 200,
|
||||
Body: api.ReplicationController{
|
||||
Body: &api.ReplicationController{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
DesiredState: api.ReplicationControllerState{
|
||||
Replicas: 2,
|
||||
@@ -284,14 +284,14 @@ func TestDeleteController(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateController(t *testing.T) {
|
||||
requestController := api.ReplicationController{
|
||||
requestController := &api.ReplicationController{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
}
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "POST", Path: "/replicationControllers", Body: requestController},
|
||||
Response: Response{
|
||||
StatusCode: 200,
|
||||
Body: api.ReplicationController{
|
||||
Body: &api.ReplicationController{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
DesiredState: api.ReplicationControllerState{
|
||||
Replicas: 2,
|
||||
@@ -307,9 +307,9 @@ func TestCreateController(t *testing.T) {
|
||||
c.Validate(t, receivedController, err)
|
||||
}
|
||||
|
||||
func body(obj interface{}, raw *string) *string {
|
||||
func body(obj runtime.Object, raw *string) *string {
|
||||
if obj != nil {
|
||||
bs, _ := runtime.Encode(obj)
|
||||
bs, _ := runtime.DefaultCodec.Encode(obj)
|
||||
body := string(bs)
|
||||
return &body
|
||||
}
|
||||
@@ -321,13 +321,13 @@ type testRequest struct {
|
||||
Path string
|
||||
Header string
|
||||
Query url.Values
|
||||
Body interface{}
|
||||
Body runtime.Object
|
||||
RawBody *string
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
StatusCode int
|
||||
Body interface{}
|
||||
Body runtime.Object
|
||||
RawBody *string
|
||||
}
|
||||
|
||||
@@ -338,7 +338,6 @@ type testClient struct {
|
||||
Error bool
|
||||
server *httptest.Server
|
||||
handler *util.FakeHandler
|
||||
Target interface{}
|
||||
// For query args, an optional function to validate the contents
|
||||
// useful when the contents can change but still be correct.
|
||||
// Maps from query arg key to validator.
|
||||
@@ -363,7 +362,23 @@ func (c *testClient) Setup() *testClient {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *testClient) Validate(t *testing.T, received interface{}, err error) {
|
||||
func (c *testClient) Validate(t *testing.T, received runtime.Object, err error) {
|
||||
c.ValidateCommon(t, err)
|
||||
|
||||
if c.Response.Body != nil && !reflect.DeepEqual(c.Response.Body, received) {
|
||||
t.Errorf("bad response for request %#v: expected %s, got %s", c.Request, c.Response.Body, received)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *testClient) ValidateRaw(t *testing.T, received []byte, err error) {
|
||||
c.ValidateCommon(t, err)
|
||||
|
||||
if c.Response.Body != nil && !reflect.DeepEqual(c.Response.Body, received) {
|
||||
t.Errorf("bad response for request %#v: expected %s, got %s", c.Request, c.Response.Body, received)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *testClient) ValidateCommon(t *testing.T, err error) {
|
||||
defer c.server.Close()
|
||||
|
||||
if c.Error {
|
||||
@@ -401,17 +416,13 @@ func (c *testClient) Validate(t *testing.T, received interface{}, err error) {
|
||||
if expected, received := requestBody, c.handler.RequestBody; expected != nil && *expected != received {
|
||||
t.Errorf("bad body for request %#v: expected %s, got %s", c.Request, *expected, received)
|
||||
}
|
||||
|
||||
if c.Response.Body != nil && !reflect.DeepEqual(c.Response.Body, received) {
|
||||
t.Errorf("bad response for request %#v: expected %s, got %s", c.Request, c.Response.Body, received)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListServices(t *testing.T) {
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "GET", Path: "/services"},
|
||||
Response: Response{StatusCode: 200,
|
||||
Body: api.ServiceList{
|
||||
Body: &api.ServiceList{
|
||||
Items: []api.Service{
|
||||
{
|
||||
JSONBase: api.JSONBase{ID: "name"},
|
||||
@@ -435,7 +446,7 @@ func TestListServicesLabels(t *testing.T) {
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "GET", Path: "/services", Query: url.Values{"labels": []string{"foo=bar,name=baz"}}},
|
||||
Response: Response{StatusCode: 200,
|
||||
Body: api.ServiceList{
|
||||
Body: &api.ServiceList{
|
||||
Items: []api.Service{
|
||||
{
|
||||
JSONBase: api.JSONBase{ID: "name"},
|
||||
@@ -464,7 +475,7 @@ func TestGetService(t *testing.T) {
|
||||
Response: Response{StatusCode: 200, Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}},
|
||||
}
|
||||
response, err := c.Setup().GetService("1")
|
||||
c.Validate(t, &response, err)
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestCreateService(t *testing.T) {
|
||||
@@ -472,18 +483,18 @@ func TestCreateService(t *testing.T) {
|
||||
Request: testRequest{Method: "POST", Path: "/services", Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}},
|
||||
Response: Response{StatusCode: 200, Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}},
|
||||
}).Setup()
|
||||
response, err := c.Setup().CreateService(api.Service{JSONBase: api.JSONBase{ID: "service-1"}})
|
||||
c.Validate(t, &response, err)
|
||||
response, err := c.Setup().CreateService(&api.Service{JSONBase: api.JSONBase{ID: "service-1"}})
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestUpdateService(t *testing.T) {
|
||||
svc := api.Service{JSONBase: api.JSONBase{ID: "service-1", ResourceVersion: 1}}
|
||||
svc := &api.Service{JSONBase: api.JSONBase{ID: "service-1", ResourceVersion: 1}}
|
||||
c := &testClient{
|
||||
Request: testRequest{Method: "PUT", Path: "/services/service-1", Body: &svc},
|
||||
Response: Response{StatusCode: 200, Body: &svc},
|
||||
Request: testRequest{Method: "PUT", Path: "/services/service-1", Body: svc},
|
||||
Response: Response{StatusCode: 200, Body: svc},
|
||||
}
|
||||
response, err := c.Setup().UpdateService(svc)
|
||||
c.Validate(t, &response, err)
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestDeleteService(t *testing.T) {
|
||||
@@ -503,8 +514,8 @@ func TestDoRequest(t *testing.T) {
|
||||
{Client: NewOrDie("localhost", &AuthInfo{"foo", "bar"}), Request: testRequest{Method: "GET", Path: "auth", Header: "Authorization"}, Response: Response{StatusCode: 200}},
|
||||
{Client: &Client{&RESTClient{httpClient: http.DefaultClient}}, Request: testRequest{Method: "GET", Path: "nocertificate"}, Error: true},
|
||||
{Request: testRequest{Method: "GET", Path: "error"}, Response: Response{StatusCode: 500}, Error: true},
|
||||
{Request: testRequest{Method: "POST", Path: "faildecode"}, Response: Response{StatusCode: 200, RawBody: &invalid}, Target: &struct{}{}},
|
||||
{Request: testRequest{Method: "GET", Path: "failread"}, Response: Response{StatusCode: 200, RawBody: &invalid}, Target: &struct{}{}},
|
||||
{Request: testRequest{Method: "POST", Path: "faildecode"}, Response: Response{StatusCode: 200, RawBody: &invalid}},
|
||||
{Request: testRequest{Method: "GET", Path: "failread"}, Response: Response{StatusCode: 200, RawBody: &invalid}},
|
||||
}
|
||||
for _, c := range testClients {
|
||||
client := c.Setup()
|
||||
@@ -516,13 +527,13 @@ func TestDoRequest(t *testing.T) {
|
||||
URL: prefix,
|
||||
}
|
||||
response, err := client.doRequest(request)
|
||||
c.Validate(t, response, err)
|
||||
c.ValidateRaw(t, response, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoRequestAccepted(t *testing.T) {
|
||||
status := api.Status{Status: api.StatusWorking}
|
||||
expectedBody, _ := runtime.Encode(status)
|
||||
status := &api.Status{Status: api.StatusWorking}
|
||||
expectedBody, _ := runtime.DefaultCodec.Encode(status)
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 202,
|
||||
ResponseBody: string(expectedBody),
|
||||
@@ -548,7 +559,7 @@ func TestDoRequestAccepted(t *testing.T) {
|
||||
t.Errorf("Unexpected kind of error: %#v", err)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(se.Status, status) {
|
||||
if !reflect.DeepEqual(&se.Status, status) {
|
||||
t.Errorf("Unexpected status: %#v", se.Status)
|
||||
}
|
||||
if body != nil {
|
||||
@@ -558,8 +569,8 @@ func TestDoRequestAccepted(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoRequestAcceptedSuccess(t *testing.T) {
|
||||
status := api.Status{Status: api.StatusSuccess}
|
||||
expectedBody, _ := runtime.Encode(status)
|
||||
status := &api.Status{Status: api.StatusSuccess}
|
||||
expectedBody, _ := runtime.DefaultCodec.Encode(status)
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 202,
|
||||
ResponseBody: string(expectedBody),
|
||||
@@ -579,11 +590,11 @@ func TestDoRequestAcceptedSuccess(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error %#v", err)
|
||||
}
|
||||
statusOut, err := runtime.Decode(body)
|
||||
statusOut, err := runtime.DefaultCodec.Decode(body)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error %#v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(&status, statusOut) {
|
||||
if !reflect.DeepEqual(status, statusOut) {
|
||||
t.Errorf("Unexpected mis-match. Expected %#v. Saw %#v", status, statusOut)
|
||||
}
|
||||
fakeHandler.ValidateRequest(t, "/foo/bar", "GET", nil)
|
||||
@@ -622,5 +633,5 @@ func TestListMinions(t *testing.T) {
|
||||
Response: Response{StatusCode: 200, Body: &api.MinionList{JSONBase: api.JSONBase{ID: "minion-1"}}},
|
||||
}
|
||||
response, err := c.Setup().ListMinions()
|
||||
c.Validate(t, &response, err)
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
@@ -42,14 +42,14 @@ type Fake struct {
|
||||
Watch watch.Interface
|
||||
}
|
||||
|
||||
func (c *Fake) ListPods(selector labels.Selector) (api.PodList, error) {
|
||||
func (c *Fake) ListPods(selector labels.Selector) (*api.PodList, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "list-pods"})
|
||||
return *runtime.CopyOrDie(c.Pods).(*api.PodList), nil
|
||||
return runtime.DefaultScheme.CopyOrDie(&c.Pods).(*api.PodList), nil
|
||||
}
|
||||
|
||||
func (c *Fake) GetPod(name string) (api.Pod, error) {
|
||||
func (c *Fake) GetPod(name string) (*api.Pod, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "get-pod", Value: name})
|
||||
return api.Pod{}, nil
|
||||
return &api.Pod{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) DeletePod(name string) error {
|
||||
@@ -57,34 +57,34 @@ func (c *Fake) DeletePod(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Fake) CreatePod(pod api.Pod) (api.Pod, error) {
|
||||
func (c *Fake) CreatePod(pod *api.Pod) (*api.Pod, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "create-pod"})
|
||||
return api.Pod{}, nil
|
||||
return &api.Pod{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) UpdatePod(pod api.Pod) (api.Pod, error) {
|
||||
func (c *Fake) UpdatePod(pod *api.Pod) (*api.Pod, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "update-pod", Value: pod.ID})
|
||||
return api.Pod{}, nil
|
||||
return &api.Pod{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) ListReplicationControllers(selector labels.Selector) (api.ReplicationControllerList, error) {
|
||||
func (c *Fake) ListReplicationControllers(selector labels.Selector) (*api.ReplicationControllerList, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "list-controllers"})
|
||||
return api.ReplicationControllerList{}, nil
|
||||
return &api.ReplicationControllerList{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) GetReplicationController(name string) (api.ReplicationController, error) {
|
||||
func (c *Fake) GetReplicationController(name string) (*api.ReplicationController, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "get-controller", Value: name})
|
||||
return *runtime.CopyOrDie(c.Ctrl).(*api.ReplicationController), nil
|
||||
return runtime.DefaultScheme.CopyOrDie(&c.Ctrl).(*api.ReplicationController), nil
|
||||
}
|
||||
|
||||
func (c *Fake) CreateReplicationController(controller api.ReplicationController) (api.ReplicationController, error) {
|
||||
func (c *Fake) CreateReplicationController(controller *api.ReplicationController) (*api.ReplicationController, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "create-controller", Value: controller})
|
||||
return api.ReplicationController{}, nil
|
||||
return &api.ReplicationController{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) UpdateReplicationController(controller api.ReplicationController) (api.ReplicationController, error) {
|
||||
func (c *Fake) UpdateReplicationController(controller *api.ReplicationController) (*api.ReplicationController, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "update-controller", Value: controller})
|
||||
return api.ReplicationController{}, nil
|
||||
return &api.ReplicationController{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) DeleteReplicationController(controller string) error {
|
||||
@@ -97,24 +97,24 @@ func (c *Fake) WatchReplicationControllers(label, field labels.Selector, resourc
|
||||
return c.Watch, nil
|
||||
}
|
||||
|
||||
func (c *Fake) ListServices(selector labels.Selector) (api.ServiceList, error) {
|
||||
func (c *Fake) ListServices(selector labels.Selector) (*api.ServiceList, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "list-services"})
|
||||
return c.ServiceList, c.Err
|
||||
return &c.ServiceList, c.Err
|
||||
}
|
||||
|
||||
func (c *Fake) GetService(name string) (api.Service, error) {
|
||||
func (c *Fake) GetService(name string) (*api.Service, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "get-service", Value: name})
|
||||
return api.Service{}, nil
|
||||
return &api.Service{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) CreateService(service api.Service) (api.Service, error) {
|
||||
func (c *Fake) CreateService(service *api.Service) (*api.Service, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "create-service", Value: service})
|
||||
return api.Service{}, nil
|
||||
return &api.Service{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) UpdateService(service api.Service) (api.Service, error) {
|
||||
func (c *Fake) UpdateService(service *api.Service) (*api.Service, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "update-service", Value: service})
|
||||
return api.Service{}, nil
|
||||
return &api.Service{}, nil
|
||||
}
|
||||
|
||||
func (c *Fake) DeleteService(service string) error {
|
||||
@@ -127,9 +127,9 @@ func (c *Fake) WatchServices(label, field labels.Selector, resourceVersion uint6
|
||||
return c.Watch, c.Err
|
||||
}
|
||||
|
||||
func (c *Fake) ListEndpoints(selector labels.Selector) (api.EndpointsList, error) {
|
||||
func (c *Fake) ListEndpoints(selector labels.Selector) (*api.EndpointsList, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "list-endpoints"})
|
||||
return c.EndpointsList, c.Err
|
||||
return runtime.DefaultScheme.CopyOrDie(&c.EndpointsList).(*api.EndpointsList), c.Err
|
||||
}
|
||||
|
||||
func (c *Fake) WatchEndpoints(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error) {
|
||||
@@ -143,7 +143,7 @@ func (c *Fake) ServerVersion() (*version.Info, error) {
|
||||
return &versionInfo, nil
|
||||
}
|
||||
|
||||
func (c *Fake) ListMinions() (api.MinionList, error) {
|
||||
func (c *Fake) ListMinions() (*api.MinionList, error) {
|
||||
c.Actions = append(c.Actions, FakeAction{Action: "list-minions", Value: nil})
|
||||
return api.MinionList{}, nil
|
||||
return &api.MinionList{}, nil
|
||||
}
|
||||
|
||||
@@ -187,7 +187,8 @@ func (r *Request) Timeout(d time.Duration) *Request {
|
||||
// If obj is a string, try to read a file of that name.
|
||||
// If obj is a []byte, send it directly.
|
||||
// If obj is an io.Reader, use it directly.
|
||||
// Otherwise, assume obj is an api type and marshall it correctly.
|
||||
// If obj is a runtime.Object, marshal it correctly.
|
||||
// Otherwise, set an error.
|
||||
func (r *Request) Body(obj interface{}) *Request {
|
||||
if r.err != nil {
|
||||
return r
|
||||
@@ -204,13 +205,15 @@ func (r *Request) Body(obj interface{}) *Request {
|
||||
r.body = bytes.NewBuffer(t)
|
||||
case io.Reader:
|
||||
r.body = t
|
||||
default:
|
||||
data, err := runtime.Encode(obj)
|
||||
case runtime.Object:
|
||||
data, err := runtime.DefaultCodec.Encode(t)
|
||||
if err != nil {
|
||||
r.err = err
|
||||
return r
|
||||
}
|
||||
r.body = bytes.NewBuffer(data)
|
||||
default:
|
||||
r.err = fmt.Errorf("Unknown type used for body: %#v", obj)
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -314,19 +317,19 @@ func (r Result) Raw() ([]byte, error) {
|
||||
}
|
||||
|
||||
// Get returns the result as an object.
|
||||
func (r Result) Get() (interface{}, error) {
|
||||
func (r Result) Get() (runtime.Object, error) {
|
||||
if r.err != nil {
|
||||
return nil, r.err
|
||||
}
|
||||
return runtime.Decode(r.body)
|
||||
return runtime.DefaultCodec.Decode(r.body)
|
||||
}
|
||||
|
||||
// Into stores the result into obj, if possible.
|
||||
func (r Result) Into(obj interface{}) error {
|
||||
func (r Result) Into(obj runtime.Object) error {
|
||||
if r.err != nil {
|
||||
return r.err
|
||||
}
|
||||
return runtime.DecodeInto(r.body, obj)
|
||||
return runtime.DefaultCodec.DecodeInto(r.body, obj)
|
||||
}
|
||||
|
||||
// Error returns the error executing the request, nil if no error occurred.
|
||||
|
||||
@@ -38,7 +38,7 @@ import (
|
||||
func TestDoRequestNewWay(t *testing.T) {
|
||||
reqBody := "request body"
|
||||
expectedObj := &api.Service{Port: 12345}
|
||||
expectedBody, _ := runtime.Encode(expectedObj)
|
||||
expectedBody, _ := runtime.DefaultCodec.Encode(expectedObj)
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(expectedBody),
|
||||
@@ -71,9 +71,9 @@ func TestDoRequestNewWay(t *testing.T) {
|
||||
|
||||
func TestDoRequestNewWayReader(t *testing.T) {
|
||||
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
reqBodyExpected, _ := runtime.Encode(reqObj)
|
||||
reqBodyExpected, _ := runtime.DefaultCodec.Encode(reqObj)
|
||||
expectedObj := &api.Service{Port: 12345}
|
||||
expectedBody, _ := runtime.Encode(expectedObj)
|
||||
expectedBody, _ := runtime.DefaultCodec.Encode(expectedObj)
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(expectedBody),
|
||||
@@ -108,9 +108,9 @@ func TestDoRequestNewWayReader(t *testing.T) {
|
||||
|
||||
func TestDoRequestNewWayObj(t *testing.T) {
|
||||
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
reqBodyExpected, _ := runtime.Encode(reqObj)
|
||||
reqBodyExpected, _ := runtime.DefaultCodec.Encode(reqObj)
|
||||
expectedObj := &api.Service{Port: 12345}
|
||||
expectedBody, _ := runtime.Encode(expectedObj)
|
||||
expectedBody, _ := runtime.DefaultCodec.Encode(expectedObj)
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(expectedBody),
|
||||
@@ -144,7 +144,7 @@ func TestDoRequestNewWayObj(t *testing.T) {
|
||||
|
||||
func TestDoRequestNewWayFile(t *testing.T) {
|
||||
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
reqBodyExpected, err := runtime.Encode(reqObj)
|
||||
reqBodyExpected, err := runtime.DefaultCodec.Encode(reqObj)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func TestDoRequestNewWayFile(t *testing.T) {
|
||||
}
|
||||
|
||||
expectedObj := &api.Service{Port: 12345}
|
||||
expectedBody, _ := runtime.Encode(expectedObj)
|
||||
expectedBody, _ := runtime.DefaultCodec.Encode(expectedObj)
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(expectedBody),
|
||||
@@ -285,7 +285,7 @@ func TestSetPollPeriod(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPolling(t *testing.T) {
|
||||
objects := []interface{}{
|
||||
objects := []runtime.Object{
|
||||
&api.Status{Status: api.StatusWorking, Details: &api.StatusDetails{ID: "1234"}},
|
||||
&api.Status{Status: api.StatusWorking, Details: &api.StatusDetails{ID: "1234"}},
|
||||
&api.Status{Status: api.StatusWorking, Details: &api.StatusDetails{ID: "1234"}},
|
||||
@@ -295,7 +295,7 @@ func TestPolling(t *testing.T) {
|
||||
|
||||
callNumber := 0
|
||||
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := runtime.Encode(objects[callNumber])
|
||||
data, err := runtime.DefaultCodec.Encode(objects[callNumber])
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected encode error")
|
||||
}
|
||||
@@ -380,7 +380,7 @@ func checkAuth(t *testing.T, expect AuthInfo, r *http.Request) {
|
||||
func TestWatch(t *testing.T) {
|
||||
var table = []struct {
|
||||
t watch.EventType
|
||||
obj interface{}
|
||||
obj runtime.Object
|
||||
}{
|
||||
{watch.Added, &api.Pod{JSONBase: api.JSONBase{ID: "first"}}},
|
||||
{watch.Modified, &api.Pod{JSONBase: api.JSONBase{ID: "second"}}},
|
||||
|
||||
@@ -58,7 +58,7 @@ func (r RealPodControl) createReplica(controllerSpec api.ReplicationController)
|
||||
if labels != nil {
|
||||
labels["replicationController"] = controllerSpec.ID
|
||||
}
|
||||
pod := api.Pod{
|
||||
pod := &api.Pod{
|
||||
DesiredState: controllerSpec.DesiredState.PodTemplate.DesiredState,
|
||||
Labels: controllerSpec.DesiredState.PodTemplate.Labels,
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ func newReplicationController(replicas int) api.ReplicationController {
|
||||
}
|
||||
}
|
||||
|
||||
func newPodList(count int) api.PodList {
|
||||
func newPodList(count int) *api.PodList {
|
||||
pods := []api.Pod{}
|
||||
for i := 0; i < count; i++ {
|
||||
pods = append(pods, api.Pod{
|
||||
@@ -94,7 +94,7 @@ func newPodList(count int) api.PodList {
|
||||
},
|
||||
})
|
||||
}
|
||||
return api.PodList{
|
||||
return &api.PodList{
|
||||
Items: pods,
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func validateSyncReplication(t *testing.T, fakePodControl *FakePodControl, expec
|
||||
}
|
||||
|
||||
func TestSyncReplicationControllerDoesNothing(t *testing.T) {
|
||||
body, _ := runtime.Encode(newPodList(2))
|
||||
body, _ := runtime.DefaultCodec.Encode(newPodList(2))
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(body),
|
||||
@@ -129,7 +129,7 @@ func TestSyncReplicationControllerDoesNothing(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSyncReplicationControllerDeletes(t *testing.T) {
|
||||
body, _ := runtime.Encode(newPodList(2))
|
||||
body, _ := runtime.DefaultCodec.Encode(newPodList(2))
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(body),
|
||||
@@ -149,7 +149,7 @@ func TestSyncReplicationControllerDeletes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSyncReplicationControllerCreates(t *testing.T) {
|
||||
body, _ := runtime.Encode(newPodList(0))
|
||||
body, _ := runtime.DefaultCodec.Encode(newPodList(0))
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(body),
|
||||
@@ -169,7 +169,7 @@ func TestSyncReplicationControllerCreates(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateReplica(t *testing.T) {
|
||||
body, _ := runtime.Encode(api.Pod{})
|
||||
body, _ := runtime.DefaultCodec.Encode(&api.Pod{})
|
||||
fakeHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: string(body),
|
||||
@@ -292,7 +292,7 @@ func TestSyncronize(t *testing.T) {
|
||||
}
|
||||
fakeControllerHandler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: runtime.EncodeOrDie(&api.ReplicationControllerList{
|
||||
ResponseBody: runtime.DefaultScheme.EncodeOrDie(&api.ReplicationControllerList{
|
||||
Items: []api.ReplicationController{
|
||||
controllerSpec1,
|
||||
controllerSpec2,
|
||||
|
||||
@@ -37,7 +37,7 @@ type Converter struct {
|
||||
// do the conversion.
|
||||
funcs map[typePair]reflect.Value
|
||||
|
||||
// If true, print helpful debugging info. Quite verbose.
|
||||
// If non-nil, will be called to print helpful debugging info. Quite verbose.
|
||||
Debug DebugLogger
|
||||
}
|
||||
|
||||
@@ -48,29 +48,43 @@ func NewConverter() *Converter {
|
||||
}
|
||||
}
|
||||
|
||||
// Scope is passed to conversion funcs to allow them to continue an ongoing conversion.
|
||||
// If multiple converters exist in the system, Scope will allow you to use the correct one
|
||||
// from a conversion function--that is, the one your conversion function was called by.
|
||||
type Scope interface {
|
||||
// Call Convert to convert sub-objects. Note that if you call it with your own exact
|
||||
// parameters, you'll run out of stack space before anything useful happens.
|
||||
Convert(src, dest interface{}, flags FieldMatchingFlags) error
|
||||
}
|
||||
|
||||
// Register registers a conversion func with the Converter. conversionFunc must take
|
||||
// two parameters, the input and output type. It must take a pointer to each. It must
|
||||
// return an error.
|
||||
// three parameters: a pointer to the input type, a pointer to the output type, and
|
||||
// a conversion.Scope (which should be used if recursive conversion calls are desired).
|
||||
// It must return an error.
|
||||
//
|
||||
// Example:
|
||||
// c.Register(func(in *Pod, out *v1beta1.Pod) error { ... return nil })
|
||||
// c.Register(func(in *Pod, out *v1beta1.Pod, s Scope) error { ... return nil })
|
||||
func (c *Converter) Register(conversionFunc interface{}) error {
|
||||
fv := reflect.ValueOf(conversionFunc)
|
||||
ft := fv.Type()
|
||||
if ft.Kind() != reflect.Func {
|
||||
return fmt.Errorf("expected func, got: %v", ft)
|
||||
}
|
||||
if ft.NumIn() != 2 {
|
||||
return fmt.Errorf("expected two in params, got: %v", ft)
|
||||
if ft.NumIn() != 3 {
|
||||
return fmt.Errorf("expected three 'in' params, got: %v", ft)
|
||||
}
|
||||
if ft.NumOut() != 1 {
|
||||
return fmt.Errorf("expected one out param, got: %v", ft)
|
||||
return fmt.Errorf("expected one 'out' param, got: %v", ft)
|
||||
}
|
||||
if ft.In(0).Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("expected pointer arg for in param 0, got: %v", ft)
|
||||
return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft)
|
||||
}
|
||||
if ft.In(1).Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("expected pointer arg for in param 1, got: %v", ft)
|
||||
return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft)
|
||||
}
|
||||
scopeType := Scope(c)
|
||||
if e, a := reflect.TypeOf(&scopeType).Elem(), ft.In(2); e != a {
|
||||
return fmt.Errorf("expected '%v' arg for 'in' param 2, got '%v' (%v)", e, a, ft)
|
||||
}
|
||||
var forErrorType error
|
||||
// This convolution is necessary, otherwise TypeOf picks up on the fact
|
||||
@@ -138,7 +152,8 @@ func (c *Converter) convert(sv, dv reflect.Value, flags FieldMatchingFlags) erro
|
||||
if c.Debug != nil {
|
||||
c.Debug.Logf("Calling custom conversion of '%v' to '%v'", st, dt)
|
||||
}
|
||||
ret := fv.Call([]reflect.Value{sv.Addr(), dv.Addr()})[0].Interface()
|
||||
args := []reflect.Value{sv.Addr(), dv.Addr(), reflect.ValueOf(Scope(c))}
|
||||
ret := fv.Call(args)[0].Interface()
|
||||
// This convolution is necssary because nil interfaces won't convert
|
||||
// to errors.
|
||||
if ret == nil {
|
||||
|
||||
@@ -27,28 +27,30 @@ import (
|
||||
func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||
type A struct {
|
||||
Foo string
|
||||
Baz int
|
||||
}
|
||||
type B struct {
|
||||
Bar string
|
||||
Baz int
|
||||
}
|
||||
type C struct{}
|
||||
c := NewConverter()
|
||||
err := c.Register(func(in *A, out *B) error {
|
||||
err := c.Register(func(in *A, out *B, s Scope) error {
|
||||
out.Bar = in.Foo
|
||||
return nil
|
||||
return s.Convert(&in.Baz, &out.Baz, 0)
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
err = c.Register(func(in *B, out *A) error {
|
||||
err = c.Register(func(in *B, out *A, s Scope) error {
|
||||
out.Foo = in.Bar
|
||||
return nil
|
||||
return s.Convert(&in.Baz, &out.Baz, 0)
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
x := A{"hello, intrepid test reader!"}
|
||||
x := A{"hello, intrepid test reader!", 3}
|
||||
y := B{}
|
||||
|
||||
err = c.Convert(&x, &y, 0)
|
||||
@@ -58,8 +60,11 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||
if e, a := x.Foo, y.Bar; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := x.Baz, y.Baz; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
z := B{"all your test are belong to us"}
|
||||
z := B{"all your test are belong to us", 42}
|
||||
w := A{}
|
||||
|
||||
err = c.Convert(&z, &w, 0)
|
||||
@@ -69,8 +74,11 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||
if e, a := z.Bar, w.Foo; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := z.Baz, w.Baz; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
err = c.Register(func(in *A, out *C) error {
|
||||
err = c.Register(func(in *A, out *C, s Scope) error {
|
||||
return fmt.Errorf("C can't store an A, silly")
|
||||
})
|
||||
if err != nil {
|
||||
@@ -85,7 +93,7 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||
|
||||
func TestConverter_fuzz(t *testing.T) {
|
||||
newAnonType := func() interface{} {
|
||||
return reflect.New(reflect.TypeOf(externalTypeReturn())).Interface()
|
||||
return reflect.New(reflect.TypeOf(externalTypeReturn()).Elem()).Interface()
|
||||
}
|
||||
// Use the same types from the scheme test.
|
||||
table := []struct {
|
||||
|
||||
@@ -85,8 +85,8 @@ func NewScheme() *Scheme {
|
||||
|
||||
// AddKnownTypes registers all types passed in 'types' as being members of version 'version.
|
||||
// Encode() will refuse objects unless their type has been registered with AddKnownTypes.
|
||||
// All objects passed to types should be structs, not pointers to structs. The name that go
|
||||
// reports for the struct becomes the "kind" field when encoding.
|
||||
// All objects passed to types should be pointers to structs. The name that go reports for
|
||||
// the struct becomes the "kind" field when encoding.
|
||||
func (s *Scheme) AddKnownTypes(version string, types ...interface{}) {
|
||||
knownTypes, found := s.versionMap[version]
|
||||
if !found {
|
||||
@@ -95,8 +95,12 @@ func (s *Scheme) AddKnownTypes(version string, types ...interface{}) {
|
||||
}
|
||||
for _, obj := range types {
|
||||
t := reflect.TypeOf(obj)
|
||||
if t.Kind() != reflect.Ptr {
|
||||
panic("All types must be pointers to structs.")
|
||||
}
|
||||
t = t.Elem()
|
||||
if t.Kind() != reflect.Struct {
|
||||
panic("All types must be structs.")
|
||||
panic("All types must be pointers to structs.")
|
||||
}
|
||||
knownTypes[t.Name()] = t
|
||||
s.typeToVersion[t] = version
|
||||
|
||||
@@ -90,7 +90,7 @@ func externalTypeReturn() interface{} {
|
||||
O *TestType2 `yaml:"O,omitempty" json:"O,omitempty"`
|
||||
P []TestType2 `yaml:"Q,omitempty" json:"Q,omitempty"`
|
||||
}
|
||||
return TestType1{}
|
||||
return &TestType1{}
|
||||
}
|
||||
|
||||
type ExternalInternalSame struct {
|
||||
@@ -124,8 +124,8 @@ var TestObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 100).Funcs(
|
||||
// Returns a new Scheme set up with the test objects.
|
||||
func GetTestScheme() *Scheme {
|
||||
s := NewScheme()
|
||||
s.AddKnownTypes("", TestType1{}, ExternalInternalSame{})
|
||||
s.AddKnownTypes("v1", externalTypeReturn(), ExternalInternalSame{})
|
||||
s.AddKnownTypes("", &TestType1{}, &ExternalInternalSame{})
|
||||
s.AddKnownTypes("v1", externalTypeReturn(), &ExternalInternalSame{})
|
||||
s.ExternalVersion = "v1"
|
||||
s.InternalVersion = ""
|
||||
s.MetaInsertionFactory = testMetaInsertionFactory{}
|
||||
|
||||
@@ -27,6 +27,15 @@ import (
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// Master is used to announce the current elected master.
|
||||
type Master string
|
||||
|
||||
// IsAnAPIObject is used solely so we can work with the watch package.
|
||||
// TODO: Either fix watch so this isn't necessary, or make this a real API Object.
|
||||
// TODO: when it becomes clear how this package will be used, move these declarations to
|
||||
// to the proper place.
|
||||
func (Master) IsAnAPIObject() {}
|
||||
|
||||
// NewEtcdMasterElector returns an implementation of election.MasterElector backed by etcd.
|
||||
func NewEtcdMasterElector(h tools.EtcdGetSet) MasterElector {
|
||||
return &etcdMasterElector{etcd: h}
|
||||
@@ -58,7 +67,7 @@ func (e *etcdMasterElector) run(path, id string) {
|
||||
case m := <-masters:
|
||||
e.events <- watch.Event{
|
||||
Type: watch.Modified,
|
||||
Object: m,
|
||||
Object: Master(m),
|
||||
}
|
||||
case e := <-errors:
|
||||
glog.Errorf("error in election: %v", e)
|
||||
|
||||
@@ -31,7 +31,7 @@ func TestEtcdMasterOther(t *testing.T) {
|
||||
master := NewEtcdMasterElector(etcd)
|
||||
w := master.Elect(path, "bar")
|
||||
result := <-w.ResultChan()
|
||||
if result.Type != watch.Modified || result.Object.(string) != "baz" {
|
||||
if result.Type != watch.Modified || result.Object.(Master) != "baz" {
|
||||
t.Errorf("unexpected event: %#v", result)
|
||||
}
|
||||
w.Stop()
|
||||
@@ -52,7 +52,7 @@ func TestEtcdMasterNoOther(t *testing.T) {
|
||||
master := NewEtcdMasterElector(e)
|
||||
w := master.Elect(path, "bar")
|
||||
result := <-w.ResultChan()
|
||||
if result.Type != watch.Modified || result.Object.(string) != "bar" {
|
||||
if result.Type != watch.Modified || result.Object.(Master) != "bar" {
|
||||
t.Errorf("unexpected event: %#v", result)
|
||||
}
|
||||
w.Stop()
|
||||
@@ -91,7 +91,7 @@ func TestEtcdMasterNoOtherThenConflict(t *testing.T) {
|
||||
master := NewEtcdMasterElector(e)
|
||||
w := master.Elect(path, "bar")
|
||||
result := <-w.ResultChan()
|
||||
if result.Type != watch.Modified || result.Object.(string) != "bar" {
|
||||
if result.Type != watch.Modified || result.Object.(Master) != "bar" {
|
||||
t.Errorf("unexpected event: %#v", result)
|
||||
}
|
||||
w.Stop()
|
||||
|
||||
@@ -174,7 +174,7 @@ func portsFromString(spec string) []api.Port {
|
||||
|
||||
// RunController creates a new replication controller named 'name' which creates 'replicas' pods running 'image'.
|
||||
func RunController(image, name string, replicas int, client client.Interface, portSpec string, servicePort int) error {
|
||||
controller := api.ReplicationController{
|
||||
controller := &api.ReplicationController{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: name,
|
||||
},
|
||||
@@ -227,8 +227,8 @@ func RunController(image, name string, replicas int, client client.Interface, po
|
||||
return nil
|
||||
}
|
||||
|
||||
func createService(name string, port int, client client.Interface) (api.Service, error) {
|
||||
svc := api.Service{
|
||||
func createService(name string, port int, client client.Interface) (*api.Service, error) {
|
||||
svc := &api.Service{
|
||||
JSONBase: api.JSONBase{ID: name},
|
||||
Port: port,
|
||||
Labels: map[string]string{
|
||||
|
||||
@@ -46,7 +46,7 @@ func TestUpdateWithPods(t *testing.T) {
|
||||
}
|
||||
Update("foo", &fakeClient, 0, "")
|
||||
if len(fakeClient.Actions) != 5 {
|
||||
t.Errorf("Unexpected action list %#v", fakeClient.Actions)
|
||||
t.Fatalf("Unexpected action list %#v", fakeClient.Actions)
|
||||
}
|
||||
validateAction(client.FakeAction{Action: "get-controller", Value: "foo"}, fakeClient.Actions[0], t)
|
||||
validateAction(client.FakeAction{Action: "list-pods"}, fakeClient.Actions[1], t)
|
||||
@@ -94,7 +94,7 @@ func TestUpdateWithNewImage(t *testing.T) {
|
||||
}
|
||||
validateAction(client.FakeAction{Action: "get-controller", Value: "foo"}, fakeClient.Actions[0], t)
|
||||
|
||||
newCtrl := *runtime.CopyOrDie(fakeClient.Ctrl).(*api.ReplicationController)
|
||||
newCtrl := runtime.DefaultScheme.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)
|
||||
|
||||
@@ -114,7 +114,7 @@ func TestRunController(t *testing.T) {
|
||||
if len(fakeClient.Actions) != 1 || fakeClient.Actions[0].Action != "create-controller" {
|
||||
t.Errorf("Unexpected actions: %#v", fakeClient.Actions)
|
||||
}
|
||||
controller := fakeClient.Actions[0].Value.(api.ReplicationController)
|
||||
controller := fakeClient.Actions[0].Value.(*api.ReplicationController)
|
||||
if controller.ID != name ||
|
||||
controller.DesiredState.Replicas != replicas ||
|
||||
controller.DesiredState.PodTemplate.DesiredState.Manifest.Containers[0].Image != image {
|
||||
@@ -133,7 +133,7 @@ func TestRunControllerWithService(t *testing.T) {
|
||||
fakeClient.Actions[1].Action != "create-service" {
|
||||
t.Errorf("Unexpected actions: %#v", fakeClient.Actions)
|
||||
}
|
||||
controller := fakeClient.Actions[0].Value.(api.ReplicationController)
|
||||
controller := fakeClient.Actions[0].Value.(*api.ReplicationController)
|
||||
if controller.ID != name ||
|
||||
controller.DesiredState.Replicas != replicas ||
|
||||
controller.DesiredState.PodTemplate.DesiredState.Manifest.Containers[0].Image != image {
|
||||
@@ -152,7 +152,7 @@ func TestStopController(t *testing.T) {
|
||||
fakeClient.Actions[0].Value.(string) != name {
|
||||
t.Errorf("Unexpected Action: %#v", fakeClient.Actions[0])
|
||||
}
|
||||
controller := fakeClient.Actions[1].Value.(api.ReplicationController)
|
||||
controller := fakeClient.Actions[1].Value.(*api.ReplicationController)
|
||||
if fakeClient.Actions[1].Action != "update-controller" ||
|
||||
controller.DesiredState.Replicas != 0 {
|
||||
t.Errorf("Unexpected Action: %#v", fakeClient.Actions[1])
|
||||
@@ -171,7 +171,7 @@ func TestResizeController(t *testing.T) {
|
||||
fakeClient.Actions[0].Value.(string) != name {
|
||||
t.Errorf("Unexpected Action: %#v", fakeClient.Actions[0])
|
||||
}
|
||||
controller := fakeClient.Actions[1].Value.(api.ReplicationController)
|
||||
controller := fakeClient.Actions[1].Value.(*api.ReplicationController)
|
||||
if fakeClient.Actions[1].Action != "update-controller" ||
|
||||
controller.DesiredState.Replicas != 17 {
|
||||
t.Errorf("Unexpected Action: %#v", fakeClient.Actions[1])
|
||||
|
||||
@@ -27,10 +27,11 @@ type Parser struct {
|
||||
storageToType map[string]reflect.Type
|
||||
}
|
||||
|
||||
func NewParser(objectMap map[string]interface{}) *Parser {
|
||||
// NewParser creates a new parser.
|
||||
func NewParser(objectMap map[string]runtime.Object) *Parser {
|
||||
typeMap := make(map[string]reflect.Type)
|
||||
for name, obj := range objectMap {
|
||||
typeMap[name] = reflect.TypeOf(obj)
|
||||
typeMap[name] = reflect.TypeOf(obj).Elem()
|
||||
}
|
||||
return &Parser{typeMap}
|
||||
}
|
||||
@@ -43,12 +44,12 @@ func (p *Parser) ToWireFormat(data []byte, storage string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("unknown storage type: %v", storage)
|
||||
}
|
||||
|
||||
obj := reflect.New(prototypeType).Interface()
|
||||
err := runtime.DecodeInto(data, obj)
|
||||
obj := reflect.New(prototypeType).Interface().(runtime.Object)
|
||||
err := runtime.DefaultCodec.DecodeInto(data, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return runtime.Encode(obj)
|
||||
return runtime.DefaultCodec.Encode(obj)
|
||||
}
|
||||
|
||||
func (p *Parser) SupportedWireStorage() []string {
|
||||
|
||||
@@ -25,15 +25,15 @@ import (
|
||||
)
|
||||
|
||||
func TestParseBadStorage(t *testing.T) {
|
||||
p := NewParser(map[string]interface{}{})
|
||||
p := NewParser(map[string]runtime.Object{})
|
||||
_, err := p.ToWireFormat([]byte("{}"), "badstorage")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, received none")
|
||||
}
|
||||
}
|
||||
|
||||
func DoParseTest(t *testing.T, storage string, obj interface{}, p *Parser) {
|
||||
jsonData, _ := runtime.Encode(obj)
|
||||
func DoParseTest(t *testing.T, storage string, obj runtime.Object, p *Parser) {
|
||||
jsonData, _ := runtime.DefaultCodec.Encode(obj)
|
||||
yamlData, _ := yaml.Marshal(obj)
|
||||
t.Logf("Intermediate yaml:\n%v\n", string(yamlData))
|
||||
t.Logf("Intermediate json:\n%v\n", string(jsonData))
|
||||
@@ -56,14 +56,14 @@ func DoParseTest(t *testing.T, storage string, obj interface{}, p *Parser) {
|
||||
}
|
||||
}
|
||||
|
||||
var testParser = NewParser(map[string]interface{}{
|
||||
"pods": api.Pod{},
|
||||
"services": api.Service{},
|
||||
"replicationControllers": api.ReplicationController{},
|
||||
var testParser = NewParser(map[string]runtime.Object{
|
||||
"pods": &api.Pod{},
|
||||
"services": &api.Service{},
|
||||
"replicationControllers": &api.ReplicationController{},
|
||||
})
|
||||
|
||||
func TestParsePod(t *testing.T) {
|
||||
DoParseTest(t, "pods", api.Pod{
|
||||
DoParseTest(t, "pods", &api.Pod{
|
||||
JSONBase: api.JSONBase{APIVersion: "v1beta1", ID: "test pod", Kind: "Pod"},
|
||||
DesiredState: api.PodState{
|
||||
Manifest: api.ContainerManifest{
|
||||
@@ -80,7 +80,7 @@ func TestParsePod(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseService(t *testing.T) {
|
||||
DoParseTest(t, "services", api.Service{
|
||||
DoParseTest(t, "services", &api.Service{
|
||||
JSONBase: api.JSONBase{APIVersion: "v1beta1", ID: "my service", Kind: "Service"},
|
||||
Port: 8080,
|
||||
Labels: map[string]string{
|
||||
@@ -93,7 +93,7 @@ func TestParseService(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseController(t *testing.T) {
|
||||
DoParseTest(t, "replicationControllers", api.ReplicationController{
|
||||
DoParseTest(t, "replicationControllers", &api.ReplicationController{
|
||||
JSONBase: api.JSONBase{APIVersion: "v1beta1", ID: "my controller", Kind: "ReplicationController"},
|
||||
DesiredState: api.ReplicationControllerState{
|
||||
Replicas: 9001,
|
||||
@@ -119,13 +119,15 @@ type TestParseType struct {
|
||||
Data string `json:"data" yaml:"data"`
|
||||
}
|
||||
|
||||
func (*TestParseType) IsAnAPIObject() {}
|
||||
|
||||
func TestParseCustomType(t *testing.T) {
|
||||
runtime.AddKnownTypes("", TestParseType{})
|
||||
runtime.AddKnownTypes("v1beta1", TestParseType{})
|
||||
parser := NewParser(map[string]interface{}{
|
||||
"custom": TestParseType{},
|
||||
runtime.DefaultScheme.AddKnownTypes("", &TestParseType{})
|
||||
runtime.DefaultScheme.AddKnownTypes("v1beta1", &TestParseType{})
|
||||
parser := NewParser(map[string]runtime.Object{
|
||||
"custom": &TestParseType{},
|
||||
})
|
||||
DoParseTest(t, "custom", TestParseType{
|
||||
DoParseTest(t, "custom", &TestParseType{
|
||||
JSONBase: api.JSONBase{APIVersion: "", ID: "my custom object", Kind: "TestParseType"},
|
||||
Data: "test data",
|
||||
}, parser)
|
||||
|
||||
@@ -53,7 +53,7 @@ func (s *ProxyServer) Serve() error {
|
||||
func (s *ProxyServer) doError(w http.ResponseWriter, err error) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Header().Add("Content-type", "application/json")
|
||||
data, _ := runtime.Encode(api.Status{
|
||||
data, _ := runtime.DefaultCodec.Encode(&api.Status{
|
||||
Status: api.StatusFailure,
|
||||
Message: fmt.Sprintf("internal error: %#v", err),
|
||||
})
|
||||
|
||||
@@ -36,7 +36,7 @@ import (
|
||||
type ResourcePrinter interface {
|
||||
// Print receives an arbitrary JSON body, formats it and prints it to a writer.
|
||||
Print([]byte, io.Writer) error
|
||||
PrintObj(interface{}, io.Writer) error
|
||||
PrintObj(runtime.Object, io.Writer) error
|
||||
}
|
||||
|
||||
// IdentityPrinter is an implementation of ResourcePrinter which simply copies the body out to the output stream.
|
||||
@@ -49,8 +49,8 @@ func (i *IdentityPrinter) Print(data []byte, w io.Writer) error {
|
||||
}
|
||||
|
||||
// PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer.
|
||||
func (i *IdentityPrinter) PrintObj(obj interface{}, output io.Writer) error {
|
||||
data, err := runtime.Encode(obj)
|
||||
func (i *IdentityPrinter) PrintObj(obj runtime.Object, output io.Writer) error {
|
||||
data, err := runtime.DefaultCodec.Encode(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func (y *YAMLPrinter) Print(data []byte, w io.Writer) error {
|
||||
}
|
||||
|
||||
// PrintObj prints the data as YAML.
|
||||
func (y *YAMLPrinter) PrintObj(obj interface{}, w io.Writer) error {
|
||||
func (y *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
|
||||
output, err := yaml.Marshal(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -251,7 +251,7 @@ func printStatus(status *api.Status, w io.Writer) error {
|
||||
// Print parses the data as JSON, then prints the parsed data in a human-friendly
|
||||
// format according to the type of the data.
|
||||
func (h *HumanReadablePrinter) Print(data []byte, output io.Writer) error {
|
||||
var mapObj map[string]interface{}
|
||||
var mapObj map[string]runtime.Object
|
||||
if err := json.Unmarshal([]byte(data), &mapObj); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -260,7 +260,7 @@ func (h *HumanReadablePrinter) Print(data []byte, output io.Writer) error {
|
||||
return fmt.Errorf("unexpected object with no 'kind' field: %s", data)
|
||||
}
|
||||
|
||||
obj, err := runtime.Decode(data)
|
||||
obj, err := runtime.DefaultCodec.Decode(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -268,7 +268,7 @@ func (h *HumanReadablePrinter) Print(data []byte, output io.Writer) error {
|
||||
}
|
||||
|
||||
// PrintObj prints the obj in a human-friendly format according to the type of the obj.
|
||||
func (h *HumanReadablePrinter) PrintObj(obj interface{}, output io.Writer) error {
|
||||
func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error {
|
||||
w := tabwriter.NewWriter(output, 20, 5, 3, ' ', 0)
|
||||
defer w.Flush()
|
||||
if handler := h.handlerMap[reflect.TypeOf(obj)]; handler != nil {
|
||||
@@ -292,7 +292,7 @@ type TemplatePrinter struct {
|
||||
|
||||
// Print parses the data as JSON, and re-formats it with the Go Template.
|
||||
func (t *TemplatePrinter) Print(data []byte, w io.Writer) error {
|
||||
obj, err := runtime.Decode(data)
|
||||
obj, err := runtime.DefaultCodec.Decode(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -300,6 +300,6 @@ func (t *TemplatePrinter) Print(data []byte, w io.Writer) error {
|
||||
}
|
||||
|
||||
// PrintObj formats the obj with the Go Template.
|
||||
func (t *TemplatePrinter) PrintObj(obj interface{}, w io.Writer) error {
|
||||
func (t *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
|
||||
return t.Template.Execute(w, obj)
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func TestYAMLPrinterPrint(t *testing.T) {
|
||||
t.Errorf("Test data and unmarshaled data are not equal: %#v vs %#v", poutput, testData)
|
||||
}
|
||||
|
||||
obj := api.Pod{
|
||||
obj := &api.Pod{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
}
|
||||
buf.Reset()
|
||||
@@ -77,8 +77,8 @@ func TestYAMLPrinterPrint(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Unexpeted error: %#v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(obj, objOut) {
|
||||
t.Errorf("Unexpected inequality: %#v vs %#v", obj, objOut)
|
||||
if !reflect.DeepEqual(obj, &objOut) {
|
||||
t.Errorf("Unexpected inequality: %#v vs %#v", obj, &objOut)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,16 +91,16 @@ func TestIdentityPrinter(t *testing.T) {
|
||||
t.Errorf("Bytes are not equal: %s vs %s", str, buff.String())
|
||||
}
|
||||
|
||||
obj := api.Pod{
|
||||
obj := &api.Pod{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
}
|
||||
buff.Reset()
|
||||
printer.PrintObj(obj, buff)
|
||||
objOut, err := runtime.Decode([]byte(buff.String()))
|
||||
objOut, err := runtime.DefaultCodec.Decode([]byte(buff.String()))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpeted error: %#v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(&obj, objOut) {
|
||||
if !reflect.DeepEqual(obj, objOut) {
|
||||
t.Errorf("Unexpected inequality: %#v vs %#v", obj, objOut)
|
||||
}
|
||||
}
|
||||
@@ -109,8 +109,12 @@ type TestPrintType struct {
|
||||
Data string
|
||||
}
|
||||
|
||||
func (*TestPrintType) IsAnAPIObject() {}
|
||||
|
||||
type TestUnknownType struct{}
|
||||
|
||||
func (*TestUnknownType) IsAnAPIObject() {}
|
||||
|
||||
func PrintCustomType(obj *TestPrintType, w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, "%s", obj.Data)
|
||||
return err
|
||||
|
||||
@@ -47,8 +47,8 @@ type SourceEtcd struct {
|
||||
func NewSourceEtcd(key string, client tools.EtcdClient, updates chan<- interface{}) *SourceEtcd {
|
||||
helper := tools.EtcdHelper{
|
||||
client,
|
||||
runtime.Codec,
|
||||
runtime.ResourceVersioner,
|
||||
runtime.DefaultCodec,
|
||||
runtime.DefaultResourceVersioner,
|
||||
}
|
||||
source := &SourceEtcd{
|
||||
key: key,
|
||||
|
||||
@@ -131,10 +131,10 @@ func (m *Master) init(cloud cloudprovider.Interface, podInfoGetter client.PodInf
|
||||
}
|
||||
|
||||
// API_v1beta1 returns the resources and codec for API version v1beta1.
|
||||
func (m *Master) API_v1beta1() (map[string]apiserver.RESTStorage, apiserver.Codec) {
|
||||
func (m *Master) API_v1beta1() (map[string]apiserver.RESTStorage, runtime.Codec) {
|
||||
storage := make(map[string]apiserver.RESTStorage)
|
||||
for k, v := range m.storage {
|
||||
storage[k] = v
|
||||
}
|
||||
return storage, runtime.Codec
|
||||
return storage, runtime.DefaultCodec
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ import (
|
||||
|
||||
// Watcher is the interface needed to receive changes to services and endpoints.
|
||||
type Watcher interface {
|
||||
ListServices(label labels.Selector) (api.ServiceList, error)
|
||||
ListEndpoints(label labels.Selector) (api.EndpointsList, error)
|
||||
ListServices(label labels.Selector) (*api.ServiceList, error)
|
||||
ListEndpoints(label labels.Selector) (*api.EndpointsList, error)
|
||||
WatchServices(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error)
|
||||
WatchEndpoints(label, field labels.Selector, resourceVersion uint64) (watch.Interface, error)
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func (s ConfigSourceEtcd) GetServices() ([]api.Service, []api.Endpoints, error)
|
||||
// and create a Service entry for it.
|
||||
for i, node := range response.Node.Nodes {
|
||||
var svc api.Service
|
||||
err = runtime.DecodeInto([]byte(node.Value), &svc)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(node.Value), &svc)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to load Service: %s (%#v)", node.Value, err)
|
||||
continue
|
||||
@@ -166,7 +166,7 @@ func (s ConfigSourceEtcd) GetEndpoints(service string) (api.Endpoints, error) {
|
||||
}
|
||||
// Parse all the endpoint specifications in this value.
|
||||
var e api.Endpoints
|
||||
err = runtime.DecodeInto([]byte(response.Node.Value), &e)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(response.Node.Value), &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ func etcdResponseToService(response *etcd.Response) (*api.Service, error) {
|
||||
return nil, fmt.Errorf("invalid response from etcd: %#v", response)
|
||||
}
|
||||
var svc api.Service
|
||||
err := runtime.DecodeInto([]byte(response.Node.Value), &svc)
|
||||
err := runtime.DefaultCodec.DecodeInto([]byte(response.Node.Value), &svc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -230,7 +230,7 @@ func (s ConfigSourceEtcd) ProcessChange(response *etcd.Response) {
|
||||
func (s ConfigSourceEtcd) ProcessEndpointResponse(response *etcd.Response) {
|
||||
glog.Infof("Processing a change in endpoint configuration... %s", *response)
|
||||
var endpoints api.Endpoints
|
||||
err := runtime.DecodeInto([]byte(response.Node.Value), &endpoints)
|
||||
err := runtime.DefaultCodec.DecodeInto([]byte(response.Node.Value), &endpoints)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to parse service out of etcd key: %v : %+v", response.Node.Value, err)
|
||||
return
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// BindingStorage implements the RESTStorage interface. When bindings are written, it
|
||||
@@ -40,32 +41,32 @@ func NewBindingStorage(bindingRegistry Registry) *BindingStorage {
|
||||
}
|
||||
|
||||
// List returns an error because bindings are write-only objects.
|
||||
func (*BindingStorage) List(selector labels.Selector) (interface{}, error) {
|
||||
func (*BindingStorage) List(selector labels.Selector) (runtime.Object, error) {
|
||||
return nil, errors.NewNotFound("binding", "list")
|
||||
}
|
||||
|
||||
// Get returns an error because bindings are write-only objects.
|
||||
func (*BindingStorage) Get(id string) (interface{}, error) {
|
||||
func (*BindingStorage) Get(id string) (runtime.Object, error) {
|
||||
return nil, errors.NewNotFound("binding", id)
|
||||
}
|
||||
|
||||
// Delete returns an error because bindings are write-only objects.
|
||||
func (*BindingStorage) Delete(id string) (<-chan interface{}, error) {
|
||||
func (*BindingStorage) Delete(id string) (<-chan runtime.Object, error) {
|
||||
return nil, errors.NewNotFound("binding", id)
|
||||
}
|
||||
|
||||
// New returns a new binding object fit for having data unmarshalled into it.
|
||||
func (*BindingStorage) New() interface{} {
|
||||
func (*BindingStorage) New() runtime.Object {
|
||||
return &api.Binding{}
|
||||
}
|
||||
|
||||
// Create attempts to make the assignment indicated by the binding it recieves.
|
||||
func (b *BindingStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
func (b *BindingStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
binding, ok := obj.(*api.Binding)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("incorrect type: %#v", obj)
|
||||
}
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
if err := b.registry.ApplyBinding(binding); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -74,6 +75,6 @@ func (b *BindingStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
}
|
||||
|
||||
// Update returns an error-- this object may not be updated.
|
||||
func (b *BindingStorage) Update(obj interface{}) (<-chan interface{}, error) {
|
||||
func (b *BindingStorage) Update(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
return nil, fmt.Errorf("Bindings may not be changed.")
|
||||
}
|
||||
|
||||
@@ -38,12 +38,12 @@ func TestNewBindingStorage(t *testing.T) {
|
||||
PodID: "foo",
|
||||
Host: "bar",
|
||||
}
|
||||
body, err := runtime.Encode(binding)
|
||||
body, err := runtime.DefaultCodec.Encode(binding)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected encode error %v", err)
|
||||
}
|
||||
obj := b.New()
|
||||
err = runtime.DecodeInto(body, obj)
|
||||
err = runtime.DefaultCodec.DecodeInto(body, obj)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ type Registry interface {
|
||||
ListControllers() (*api.ReplicationControllerList, error)
|
||||
WatchControllers(resourceVersion uint64) (watch.Interface, error)
|
||||
GetController(controllerID string) (*api.ReplicationController, error)
|
||||
CreateController(controller api.ReplicationController) error
|
||||
UpdateController(controller api.ReplicationController) error
|
||||
CreateController(controller *api.ReplicationController) error
|
||||
UpdateController(controller *api.ReplicationController) error
|
||||
DeleteController(controllerID string) error
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
|
||||
@@ -51,7 +52,7 @@ func NewRegistryStorage(registry Registry, podRegistry pod.Registry) apiserver.R
|
||||
}
|
||||
|
||||
// Create registers the given ReplicationController.
|
||||
func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
controller, ok := obj.(*api.ReplicationController)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a replication controller: %#v", obj)
|
||||
@@ -67,8 +68,8 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
|
||||
controller.CreationTimestamp = util.Now()
|
||||
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
err := rs.registry.CreateController(*controller)
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
err := rs.registry.CreateController(controller)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -77,14 +78,14 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
}
|
||||
|
||||
// Delete asynchronously deletes the ReplicationController specified by its id.
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan runtime.Object, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteController(id)
|
||||
}), nil
|
||||
}
|
||||
|
||||
// Get obtains the ReplicationController specified by its id.
|
||||
func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
func (rs *RegistryStorage) Get(id string) (runtime.Object, error) {
|
||||
controller, err := rs.registry.GetController(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -93,7 +94,7 @@ func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// List obtains a list of ReplicationControllers that match selector.
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (interface{}, error) {
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (runtime.Object, error) {
|
||||
controllers, err := rs.registry.ListControllers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -109,13 +110,13 @@ func (rs *RegistryStorage) List(selector labels.Selector) (interface{}, error) {
|
||||
}
|
||||
|
||||
// New creates a new ReplicationController for use with Create and Update.
|
||||
func (rs RegistryStorage) New() interface{} {
|
||||
func (rs RegistryStorage) New() runtime.Object {
|
||||
return &api.ReplicationController{}
|
||||
}
|
||||
|
||||
// Update replaces a given ReplicationController instance with an existing
|
||||
// instance in storage.registry.
|
||||
func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Update(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
controller, ok := obj.(*api.ReplicationController)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a replication controller: %#v", obj)
|
||||
@@ -123,8 +124,8 @@ func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
|
||||
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 {
|
||||
return nil, errors.NewInvalid("replicationController", controller.ID, errs)
|
||||
}
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
err := rs.registry.UpdateController(*controller)
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
err := rs.registry.UpdateController(controller)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -148,7 +149,7 @@ func (rs *RegistryStorage) Watch(label, field labels.Selector, resourceVersion u
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) waitForController(ctrl api.ReplicationController) (interface{}, error) {
|
||||
func (rs *RegistryStorage) waitForController(ctrl *api.ReplicationController) (runtime.Object, error) {
|
||||
for {
|
||||
pods, err := rs.podRegistry.ListPods(labels.Set(ctrl.DesiredState.ReplicaSelector).AsSelector())
|
||||
if err != nil {
|
||||
|
||||
@@ -112,13 +112,13 @@ func TestControllerDecode(t *testing.T) {
|
||||
ID: "foo",
|
||||
},
|
||||
}
|
||||
body, err := runtime.Encode(controller)
|
||||
body, err := runtime.DefaultCodec.Encode(controller)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
controllerOut := storage.New()
|
||||
if err := runtime.DecodeInto(body, controllerOut); err != nil {
|
||||
if err := runtime.DefaultCodec.DecodeInto(body, controllerOut); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,5 +27,5 @@ type Registry interface {
|
||||
ListEndpoints() (*api.EndpointsList, error)
|
||||
GetEndpoints(name string) (*api.Endpoints, error)
|
||||
WatchEndpoints(labels, fields labels.Selector, resourceVersion uint64) (watch.Interface, error)
|
||||
UpdateEndpoints(e api.Endpoints) error
|
||||
UpdateEndpoints(e *api.Endpoints) error
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
@@ -38,12 +39,12 @@ func NewStorage(registry Registry) apiserver.RESTStorage {
|
||||
}
|
||||
|
||||
// Get satisfies the RESTStorage interface.
|
||||
func (rs *Storage) Get(id string) (interface{}, error) {
|
||||
func (rs *Storage) Get(id string) (runtime.Object, error) {
|
||||
return rs.registry.GetEndpoints(id)
|
||||
}
|
||||
|
||||
// List satisfies the RESTStorage interface.
|
||||
func (rs *Storage) List(selector labels.Selector) (interface{}, error) {
|
||||
func (rs *Storage) List(selector labels.Selector) (runtime.Object, error) {
|
||||
if !selector.Empty() {
|
||||
return nil, errors.New("label selectors are not supported on endpoints")
|
||||
}
|
||||
@@ -57,21 +58,21 @@ func (rs *Storage) Watch(label, field labels.Selector, resourceVersion uint64) (
|
||||
}
|
||||
|
||||
// Create satisfies the RESTStorage interface but is unimplemented.
|
||||
func (rs *Storage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *Storage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
return nil, errors.New("unimplemented")
|
||||
}
|
||||
|
||||
// Update satisfies the RESTStorage interface but is unimplemented.
|
||||
func (rs *Storage) Update(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *Storage) Update(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
return nil, errors.New("unimplemented")
|
||||
}
|
||||
|
||||
// Delete satisfies the RESTStorage interface but is unimplemented.
|
||||
func (rs *Storage) Delete(id string) (<-chan interface{}, error) {
|
||||
func (rs *Storage) Delete(id string) (<-chan runtime.Object, error) {
|
||||
return nil, errors.New("unimplemented")
|
||||
}
|
||||
|
||||
// New implements the RESTStorage interface.
|
||||
func (rs Storage) New() interface{} {
|
||||
func (rs Storage) New() runtime.Object {
|
||||
return &api.Endpoints{}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ func NewRegistry(client tools.EtcdClient) *Registry {
|
||||
registry := &Registry{
|
||||
EtcdHelper: tools.EtcdHelper{
|
||||
client,
|
||||
runtime.Codec,
|
||||
runtime.ResourceVersioner,
|
||||
runtime.DefaultCodec,
|
||||
runtime.DefaultResourceVersioner,
|
||||
},
|
||||
}
|
||||
registry.manifestFactory = &BasicManifestFactory{
|
||||
@@ -82,7 +82,7 @@ func (r *Registry) ListPods(selector labels.Selector) (*api.PodList, error) {
|
||||
|
||||
// WatchPods begins watching for new, changed, or deleted pods.
|
||||
func (r *Registry) WatchPods(resourceVersion uint64, filter func(*api.Pod) bool) (watch.Interface, error) {
|
||||
return r.WatchList("/registry/pods", resourceVersion, func(obj interface{}) bool {
|
||||
return r.WatchList("/registry/pods", resourceVersion, func(obj runtime.Object) bool {
|
||||
pod, ok := obj.(*api.Pod)
|
||||
if !ok {
|
||||
glog.Errorf("Unexpected object during pod watch: %#v", obj)
|
||||
@@ -110,14 +110,14 @@ func makeContainerKey(machine string) string {
|
||||
}
|
||||
|
||||
// CreatePod creates a pod based on a specification.
|
||||
func (r *Registry) CreatePod(pod api.Pod) error {
|
||||
func (r *Registry) CreatePod(pod *api.Pod) error {
|
||||
// Set current status to "Waiting".
|
||||
pod.CurrentState.Status = api.PodWaiting
|
||||
pod.CurrentState.Host = ""
|
||||
// DesiredState.Host == "" is a signal to the scheduler that this pod needs scheduling.
|
||||
pod.DesiredState.Status = api.PodRunning
|
||||
pod.DesiredState.Host = ""
|
||||
return r.CreateObj(makePodKey(pod.ID), &pod)
|
||||
return r.CreateObj(makePodKey(pod.ID), pod)
|
||||
}
|
||||
|
||||
// ApplyBinding implements binding's registry
|
||||
@@ -129,7 +129,7 @@ func (r *Registry) ApplyBinding(binding *api.Binding) error {
|
||||
// Returns the current state of the pod, or an error.
|
||||
func (r *Registry) setPodHostTo(podID, oldMachine, machine string) (finalPod *api.Pod, err error) {
|
||||
podKey := makePodKey(podID)
|
||||
err = r.AtomicUpdate(podKey, &api.Pod{}, func(obj interface{}) (interface{}, error) {
|
||||
err = r.AtomicUpdate(podKey, &api.Pod{}, func(obj runtime.Object) (runtime.Object, error) {
|
||||
pod, ok := obj.(*api.Pod)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected object: %#v", obj)
|
||||
@@ -156,13 +156,13 @@ func (r *Registry) assignPod(podID string, machine string) error {
|
||||
return err
|
||||
}
|
||||
contKey := makeContainerKey(machine)
|
||||
err = r.AtomicUpdate(contKey, &api.ContainerManifestList{}, func(in interface{}) (interface{}, error) {
|
||||
err = r.AtomicUpdate(contKey, &api.ContainerManifestList{}, func(in runtime.Object) (runtime.Object, error) {
|
||||
manifests := *in.(*api.ContainerManifestList)
|
||||
manifests.Items = append(manifests.Items, manifest)
|
||||
if !constraint.Allowed(manifests.Items) {
|
||||
return nil, fmt.Errorf("The assignment would cause a constraint violation")
|
||||
}
|
||||
return manifests, nil
|
||||
return &manifests, nil
|
||||
})
|
||||
if err != nil {
|
||||
// Put the pod's host back the way it was. This is a terrible hack that
|
||||
@@ -174,7 +174,7 @@ func (r *Registry) assignPod(podID string, machine string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Registry) UpdatePod(pod api.Pod) error {
|
||||
func (r *Registry) UpdatePod(pod *api.Pod) error {
|
||||
return fmt.Errorf("unimplemented!")
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ func (r *Registry) DeletePod(podID string) error {
|
||||
}
|
||||
// Next, remove the pod from the machine atomically.
|
||||
contKey := makeContainerKey(machine)
|
||||
return r.AtomicUpdate(contKey, &api.ContainerManifestList{}, func(in interface{}) (interface{}, error) {
|
||||
return r.AtomicUpdate(contKey, &api.ContainerManifestList{}, func(in runtime.Object) (runtime.Object, error) {
|
||||
manifests := in.(*api.ContainerManifestList)
|
||||
newManifests := make([]api.ContainerManifest, 0, len(manifests.Items))
|
||||
found := false
|
||||
@@ -258,7 +258,7 @@ func (r *Registry) GetController(controllerID string) (*api.ReplicationControlle
|
||||
}
|
||||
|
||||
// CreateController creates a new ReplicationController.
|
||||
func (r *Registry) CreateController(controller api.ReplicationController) error {
|
||||
func (r *Registry) CreateController(controller *api.ReplicationController) error {
|
||||
err := r.CreateObj(makeControllerKey(controller.ID), controller)
|
||||
if tools.IsEtcdNodeExist(err) {
|
||||
return errors.NewAlreadyExists("replicationController", controller.ID)
|
||||
@@ -267,8 +267,8 @@ func (r *Registry) CreateController(controller api.ReplicationController) error
|
||||
}
|
||||
|
||||
// UpdateController replaces an existing ReplicationController.
|
||||
func (r *Registry) UpdateController(controller api.ReplicationController) error {
|
||||
return r.SetObj(makeControllerKey(controller.ID), &controller)
|
||||
func (r *Registry) UpdateController(controller *api.ReplicationController) error {
|
||||
return r.SetObj(makeControllerKey(controller.ID), controller)
|
||||
}
|
||||
|
||||
// DeleteController deletes a ReplicationController specified by its ID.
|
||||
@@ -293,7 +293,7 @@ func (r *Registry) ListServices() (*api.ServiceList, error) {
|
||||
}
|
||||
|
||||
// CreateService creates a new Service.
|
||||
func (r *Registry) CreateService(svc api.Service) error {
|
||||
func (r *Registry) CreateService(svc *api.Service) error {
|
||||
err := r.CreateObj(makeServiceKey(svc.ID), svc)
|
||||
if tools.IsEtcdNodeExist(err) {
|
||||
return errors.NewAlreadyExists("service", svc.ID)
|
||||
@@ -352,8 +352,8 @@ func (r *Registry) DeleteService(name string) error {
|
||||
}
|
||||
|
||||
// UpdateService replaces an existing Service.
|
||||
func (r *Registry) UpdateService(svc api.Service) error {
|
||||
return r.SetObj(makeServiceKey(svc.ID), &svc)
|
||||
func (r *Registry) UpdateService(svc *api.Service) error {
|
||||
return r.SetObj(makeServiceKey(svc.ID), svc)
|
||||
}
|
||||
|
||||
// WatchServices begins watching for new, changed, or deleted service configurations.
|
||||
@@ -378,10 +378,10 @@ func (r *Registry) ListEndpoints() (*api.EndpointsList, error) {
|
||||
}
|
||||
|
||||
// UpdateEndpoints update Endpoints of a Service.
|
||||
func (r *Registry) UpdateEndpoints(e api.Endpoints) error {
|
||||
func (r *Registry) UpdateEndpoints(e *api.Endpoints) error {
|
||||
// TODO: this is a really bad misuse of AtomicUpdate, need to compute a diff inside the loop.
|
||||
return r.AtomicUpdate(makeServiceEndpointsKey(e.ID), &api.Endpoints{},
|
||||
func(input interface{}) (interface{}, error) {
|
||||
func(input runtime.Object) (runtime.Object, error) {
|
||||
// TODO: racy - label query is returning different results for two simultaneous updaters
|
||||
return e, nil
|
||||
})
|
||||
|
||||
@@ -41,7 +41,7 @@ func NewTestEtcdRegistry(client tools.EtcdClient) *Registry {
|
||||
|
||||
func TestEtcdGetPod(t *testing.T) {
|
||||
fakeClient := tools.NewFakeEtcdClient(t)
|
||||
fakeClient.Set("/registry/pods/foo", runtime.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
fakeClient.Set("/registry/pods/foo", runtime.DefaultScheme.EncodeOrDie(&api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
pod, err := registry.GetPod("foo")
|
||||
if err != nil {
|
||||
@@ -77,9 +77,9 @@ func TestEtcdCreatePod(t *testing.T) {
|
||||
},
|
||||
E: tools.EtcdErrorNotFound,
|
||||
}
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(&api.ContainerManifestList{}), 0)
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.DefaultScheme.EncodeOrDie(&api.ContainerManifestList{}), 0)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreatePod(api.Pod{
|
||||
err := registry.CreatePod(&api.Pod{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
@@ -108,7 +108,7 @@ func TestEtcdCreatePod(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
var pod api.Pod
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &pod)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &pod)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func TestEtcdCreatePod(t *testing.T) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &manifests)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &manifests)
|
||||
if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" {
|
||||
t.Errorf("Unexpected manifest list: %#v", manifests)
|
||||
}
|
||||
@@ -133,13 +133,13 @@ func TestEtcdCreatePodAlreadyExisting(t *testing.T) {
|
||||
fakeClient.Data["/registry/pods/foo"] = tools.EtcdResponseWithError{
|
||||
R: &etcd.Response{
|
||||
Node: &etcd.Node{
|
||||
Value: runtime.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&api.Pod{JSONBase: api.JSONBase{ID: "foo"}}),
|
||||
},
|
||||
},
|
||||
E: nil,
|
||||
}
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreatePod(api.Pod{
|
||||
err := registry.CreatePod(&api.Pod{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
@@ -165,7 +165,7 @@ func TestEtcdCreatePodWithContainersError(t *testing.T) {
|
||||
E: tools.EtcdErrorValueRequired,
|
||||
}
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreatePod(api.Pod{
|
||||
err := registry.CreatePod(&api.Pod{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
@@ -205,7 +205,7 @@ func TestEtcdCreatePodWithContainersNotFound(t *testing.T) {
|
||||
E: tools.EtcdErrorNotFound,
|
||||
}
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreatePod(api.Pod{
|
||||
err := registry.CreatePod(&api.Pod{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
@@ -235,7 +235,7 @@ func TestEtcdCreatePodWithContainersNotFound(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
var pod api.Pod
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &pod)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &pod)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -249,7 +249,7 @@ func TestEtcdCreatePodWithContainersNotFound(t *testing.T) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &manifests)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &manifests)
|
||||
if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" {
|
||||
t.Errorf("Unexpected manifest list: %#v", manifests)
|
||||
}
|
||||
@@ -264,13 +264,13 @@ func TestEtcdCreatePodWithExistingContainers(t *testing.T) {
|
||||
},
|
||||
E: tools.EtcdErrorNotFound,
|
||||
}
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(api.ContainerManifestList{
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.DefaultScheme.EncodeOrDie(&api.ContainerManifestList{
|
||||
Items: []api.ContainerManifest{
|
||||
{ID: "bar"},
|
||||
},
|
||||
}), 0)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreatePod(api.Pod{
|
||||
err := registry.CreatePod(&api.Pod{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
@@ -300,7 +300,7 @@ func TestEtcdCreatePodWithExistingContainers(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
var pod api.Pod
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &pod)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &pod)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -314,7 +314,7 @@ func TestEtcdCreatePodWithExistingContainers(t *testing.T) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &manifests)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &manifests)
|
||||
if len(manifests.Items) != 2 || manifests.Items[1].ID != "foo" {
|
||||
t.Errorf("Unexpected manifest list: %#v", manifests)
|
||||
}
|
||||
@@ -325,11 +325,11 @@ func TestEtcdDeletePod(t *testing.T) {
|
||||
fakeClient.TestIndex = true
|
||||
|
||||
key := "/registry/pods/foo"
|
||||
fakeClient.Set(key, runtime.EncodeOrDie(api.Pod{
|
||||
fakeClient.Set(key, runtime.DefaultScheme.EncodeOrDie(&api.Pod{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
DesiredState: api.PodState{Host: "machine"},
|
||||
}), 0)
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(&api.ContainerManifestList{
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.DefaultScheme.EncodeOrDie(&api.ContainerManifestList{
|
||||
Items: []api.ContainerManifest{
|
||||
{ID: "foo"},
|
||||
},
|
||||
@@ -350,7 +350,7 @@ func TestEtcdDeletePod(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
var manifests api.ContainerManifestList
|
||||
runtime.DecodeInto([]byte(response.Node.Value), &manifests)
|
||||
runtime.DefaultCodec.DecodeInto([]byte(response.Node.Value), &manifests)
|
||||
if len(manifests.Items) != 0 {
|
||||
t.Errorf("Unexpected container set: %s, expected empty", response.Node.Value)
|
||||
}
|
||||
@@ -361,11 +361,11 @@ func TestEtcdDeletePodMultipleContainers(t *testing.T) {
|
||||
fakeClient.TestIndex = true
|
||||
|
||||
key := "/registry/pods/foo"
|
||||
fakeClient.Set(key, runtime.EncodeOrDie(api.Pod{
|
||||
fakeClient.Set(key, runtime.DefaultScheme.EncodeOrDie(&api.Pod{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
DesiredState: api.PodState{Host: "machine"},
|
||||
}), 0)
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(&api.ContainerManifestList{
|
||||
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.DefaultScheme.EncodeOrDie(&api.ContainerManifestList{
|
||||
Items: []api.ContainerManifest{
|
||||
{ID: "foo"},
|
||||
{ID: "bar"},
|
||||
@@ -388,7 +388,7 @@ func TestEtcdDeletePodMultipleContainers(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
var manifests api.ContainerManifestList
|
||||
runtime.DecodeInto([]byte(response.Node.Value), &manifests)
|
||||
runtime.DefaultCodec.DecodeInto([]byte(response.Node.Value), &manifests)
|
||||
if len(manifests.Items) != 1 {
|
||||
t.Fatalf("Unexpected manifest set: %#v, expected empty", manifests)
|
||||
}
|
||||
@@ -445,13 +445,13 @@ func TestEtcdListPods(t *testing.T) {
|
||||
Node: &etcd.Node{
|
||||
Nodes: []*etcd.Node{
|
||||
{
|
||||
Value: runtime.EncodeOrDie(api.Pod{
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&api.Pod{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
DesiredState: api.PodState{Host: "machine"},
|
||||
}),
|
||||
},
|
||||
{
|
||||
Value: runtime.EncodeOrDie(api.Pod{
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&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: runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}),
|
||||
},
|
||||
{
|
||||
Value: runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "bar"}}),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&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", runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
fakeClient.Set("/registry/controllers/foo", runtime.DefaultScheme.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
ctrl, err := registry.GetController("foo")
|
||||
if err != nil {
|
||||
@@ -593,7 +593,7 @@ func TestEtcdDeleteController(t *testing.T) {
|
||||
func TestEtcdCreateController(t *testing.T) {
|
||||
fakeClient := tools.NewFakeEtcdClient(t)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreateController(api.ReplicationController{
|
||||
err := registry.CreateController(&api.ReplicationController{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
@@ -607,7 +607,7 @@ func TestEtcdCreateController(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
var ctrl api.ReplicationController
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &ctrl)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &ctrl)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -619,10 +619,10 @@ func TestEtcdCreateController(t *testing.T) {
|
||||
|
||||
func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
|
||||
fakeClient := tools.NewFakeEtcdClient(t)
|
||||
fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
fakeClient.Set("/registry/controllers/foo", runtime.DefaultScheme.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreateController(api.ReplicationController{
|
||||
err := registry.CreateController(&api.ReplicationController{
|
||||
JSONBase: api.JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
@@ -636,9 +636,9 @@ func TestEtcdUpdateController(t *testing.T) {
|
||||
fakeClient := tools.NewFakeEtcdClient(t)
|
||||
fakeClient.TestIndex = true
|
||||
|
||||
resp, _ := fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
resp, _ := fakeClient.Set("/registry/controllers/foo", runtime.DefaultScheme.EncodeOrDie(&api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.UpdateController(api.ReplicationController{
|
||||
err := registry.UpdateController(&api.ReplicationController{
|
||||
JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex},
|
||||
DesiredState: api.ReplicationControllerState{
|
||||
Replicas: 2,
|
||||
@@ -662,10 +662,10 @@ func TestEtcdListServices(t *testing.T) {
|
||||
Node: &etcd.Node{
|
||||
Nodes: []*etcd.Node{
|
||||
{
|
||||
Value: runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "foo"}}),
|
||||
},
|
||||
{
|
||||
Value: runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "bar"}}),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "bar"}}),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -686,7 +686,7 @@ func TestEtcdListServices(t *testing.T) {
|
||||
func TestEtcdCreateService(t *testing.T) {
|
||||
fakeClient := tools.NewFakeEtcdClient(t)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreateService(api.Service{
|
||||
err := registry.CreateService(&api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -699,7 +699,7 @@ func TestEtcdCreateService(t *testing.T) {
|
||||
}
|
||||
|
||||
var service api.Service
|
||||
err = runtime.DecodeInto([]byte(resp.Node.Value), &service)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(resp.Node.Value), &service)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -711,9 +711,9 @@ func TestEtcdCreateService(t *testing.T) {
|
||||
|
||||
func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
|
||||
fakeClient := tools.NewFakeEtcdClient(t)
|
||||
fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
fakeClient.Set("/registry/services/specs/foo", runtime.DefaultScheme.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
err := registry.CreateService(api.Service{
|
||||
err := registry.CreateService(&api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
})
|
||||
if !errors.IsAlreadyExists(err) {
|
||||
@@ -723,7 +723,7 @@ func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
|
||||
|
||||
func TestEtcdGetService(t *testing.T) {
|
||||
fakeClient := tools.NewFakeEtcdClient(t)
|
||||
fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
fakeClient.Set("/registry/services/specs/foo", runtime.DefaultScheme.EncodeOrDie(&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", runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
resp, _ := fakeClient.Set("/registry/services/specs/foo", runtime.DefaultScheme.EncodeOrDie(&api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
registry := NewTestEtcdRegistry(fakeClient)
|
||||
testService := api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex},
|
||||
@@ -786,7 +786,7 @@ func TestEtcdUpdateService(t *testing.T) {
|
||||
"baz": "bar",
|
||||
},
|
||||
}
|
||||
err := registry.UpdateService(testService)
|
||||
err := registry.UpdateService(&testService)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -812,10 +812,10 @@ func TestEtcdListEndpoints(t *testing.T) {
|
||||
Node: &etcd.Node{
|
||||
Nodes: []*etcd.Node{
|
||||
{
|
||||
Value: runtime.EncodeOrDie(api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:8345"}}),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:8345"}}),
|
||||
},
|
||||
{
|
||||
Value: runtime.EncodeOrDie(api.Endpoints{JSONBase: api.JSONBase{ID: "bar"}}),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(&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", runtime.EncodeOrDie(endpoints), 0)
|
||||
fakeClient.Set("/registry/services/endpoints/foo", runtime.DefaultScheme.EncodeOrDie(endpoints), 0)
|
||||
|
||||
got, err := registry.GetEndpoints("foo")
|
||||
if err != nil {
|
||||
@@ -862,9 +862,9 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
|
||||
Endpoints: []string{"baz", "bar"},
|
||||
}
|
||||
|
||||
fakeClient.Set("/registry/services/endpoints/foo", runtime.EncodeOrDie(api.Endpoints{}), 0)
|
||||
fakeClient.Set("/registry/services/endpoints/foo", runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{}), 0)
|
||||
|
||||
err := registry.UpdateEndpoints(endpoints)
|
||||
err := registry.UpdateEndpoints(&endpoints)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -874,7 +874,7 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
var endpointsOut api.Endpoints
|
||||
err = runtime.DecodeInto([]byte(response.Node.Value), &endpointsOut)
|
||||
err = runtime.DefaultCodec.DecodeInto([]byte(response.Node.Value), &endpointsOut)
|
||||
if !reflect.DeepEqual(endpoints, endpointsOut) {
|
||||
t.Errorf("Unexpected endpoints: %#v, expected %#v", endpointsOut, endpoints)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,7 @@ func NewRegistryStorage(m Registry) apiserver.RESTStorage {
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
minion, ok := obj.(*api.Minion)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a minion: %#v", obj)
|
||||
@@ -48,7 +49,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
|
||||
minion.CreationTimestamp = util.Now()
|
||||
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
err := rs.registry.Insert(minion.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -64,7 +65,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan runtime.Object, error) {
|
||||
exists, err := rs.registry.Contains(id)
|
||||
if !exists {
|
||||
return nil, ErrDoesNotExist
|
||||
@@ -72,12 +73,12 @@ func (rs *RegistryStorage) Delete(id string) (<-chan interface{}, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
return &api.Status{Status: api.StatusSuccess}, rs.registry.Delete(id)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
func (rs *RegistryStorage) Get(id string) (runtime.Object, error) {
|
||||
exists, err := rs.registry.Contains(id)
|
||||
if !exists {
|
||||
return nil, ErrDoesNotExist
|
||||
@@ -85,26 +86,26 @@ func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
return rs.toApiMinion(id), err
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (interface{}, error) {
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (runtime.Object, error) {
|
||||
nameList, err := rs.registry.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var list api.MinionList
|
||||
for _, name := range nameList {
|
||||
list.Items = append(list.Items, rs.toApiMinion(name))
|
||||
list.Items = append(list.Items, *rs.toApiMinion(name))
|
||||
}
|
||||
return list, nil
|
||||
return &list, nil
|
||||
}
|
||||
|
||||
func (rs RegistryStorage) New() interface{} {
|
||||
func (rs RegistryStorage) New() runtime.Object {
|
||||
return &api.Minion{}
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Update(minion interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Update(minion runtime.Object) (<-chan runtime.Object, error) {
|
||||
return nil, fmt.Errorf("Minions can only be created (inserted) and deleted.")
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) toApiMinion(name string) api.Minion {
|
||||
return api.Minion{JSONBase: api.JSONBase{ID: name}}
|
||||
func (rs *RegistryStorage) toApiMinion(name string) *api.Minion {
|
||||
return &api.Minion{JSONBase: api.JSONBase{ID: name}}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ func TestMinionRegistryStorage(t *testing.T) {
|
||||
m := NewRegistry([]string{"foo", "bar"})
|
||||
ms := NewRegistryStorage(m)
|
||||
|
||||
if obj, err := ms.Get("foo"); err != nil || obj.(api.Minion).ID != "foo" {
|
||||
if obj, err := ms.Get("foo"); err != nil || obj.(*api.Minion).ID != "foo" {
|
||||
t.Errorf("missing expected object")
|
||||
}
|
||||
if obj, err := ms.Get("bar"); err != nil || obj.(api.Minion).ID != "bar" {
|
||||
if obj, err := ms.Get("bar"); err != nil || obj.(*api.Minion).ID != "bar" {
|
||||
t.Errorf("missing expected object")
|
||||
}
|
||||
if _, err := ms.Get("baz"); err != ErrDoesNotExist {
|
||||
@@ -43,10 +43,10 @@ func TestMinionRegistryStorage(t *testing.T) {
|
||||
t.Errorf("insert failed")
|
||||
}
|
||||
obj := <-c
|
||||
if m, ok := obj.(api.Minion); !ok || m.ID != "baz" {
|
||||
if m, ok := obj.(*api.Minion); !ok || m.ID != "baz" {
|
||||
t.Errorf("insert return value was weird: %#v", obj)
|
||||
}
|
||||
if obj, err := ms.Get("baz"); err != nil || obj.(api.Minion).ID != "baz" {
|
||||
if obj, err := ms.Get("baz"); err != nil || obj.(*api.Minion).ID != "baz" {
|
||||
t.Errorf("insert didn't actually insert")
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func TestMinionRegistryStorage(t *testing.T) {
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(list.(api.MinionList).Items, expect) {
|
||||
if !reflect.DeepEqual(list.(*api.MinionList).Items, expect) {
|
||||
t.Errorf("Unexpected list value: %#v", list)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ type Registry interface {
|
||||
// Get a specific pod
|
||||
GetPod(podID string) (*api.Pod, error)
|
||||
// Create a pod based on a specification.
|
||||
CreatePod(pod api.Pod) error
|
||||
CreatePod(pod *api.Pod) error
|
||||
// Update an existing pod
|
||||
UpdatePod(pod api.Pod) error
|
||||
UpdatePod(pod *api.Pod) error
|
||||
// Delete an existing pod
|
||||
DeletePod(podID string) error
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
|
||||
@@ -64,7 +65,7 @@ func NewRegistryStorage(config *RegistryStorageConfig) apiserver.RESTStorage {
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
pod := obj.(*api.Pod)
|
||||
if len(pod.ID) == 0 {
|
||||
pod.ID = uuid.NewUUID().String()
|
||||
@@ -76,21 +77,21 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
|
||||
pod.CreationTimestamp = util.Now()
|
||||
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
if err := rs.registry.CreatePod(*pod); err != nil {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
if err := rs.registry.CreatePod(pod); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rs.registry.GetPod(pod.ID)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan runtime.Object, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
return &api.Status{Status: api.StatusSuccess}, rs.registry.DeletePod(id)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
func (rs *RegistryStorage) Get(id string) (runtime.Object, error) {
|
||||
pod, err := rs.registry.GetPod(id)
|
||||
if err != nil {
|
||||
return pod, err
|
||||
@@ -106,7 +107,7 @@ func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
return pod, err
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (interface{}, error) {
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (runtime.Object, error) {
|
||||
pods, err := rs.registry.ListPods(selector)
|
||||
if err == nil {
|
||||
for i := range pods.Items {
|
||||
@@ -131,17 +132,17 @@ func (rs *RegistryStorage) Watch(label, field labels.Selector, resourceVersion u
|
||||
})
|
||||
}
|
||||
|
||||
func (rs RegistryStorage) New() interface{} {
|
||||
func (rs RegistryStorage) New() runtime.Object {
|
||||
return &api.Pod{}
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Update(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
pod := obj.(*api.Pod)
|
||||
if errs := validation.ValidatePod(pod); len(errs) > 0 {
|
||||
return nil, errors.NewInvalid("pod", pod.ID, errs)
|
||||
}
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
if err := rs.registry.UpdatePod(*pod); err != nil {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
if err := rs.registry.UpdatePod(pod); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rs.registry.GetPod(pod.ID)
|
||||
@@ -235,7 +236,7 @@ func getPodStatus(pod *api.Pod) api.PodStatus {
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) waitForPodRunning(pod api.Pod) (interface{}, error) {
|
||||
func (rs *RegistryStorage) waitForPodRunning(pod *api.Pod) (runtime.Object, error) {
|
||||
for {
|
||||
podObj, err := rs.Get(pod.ID)
|
||||
if err != nil || podObj == nil {
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
|
||||
func expectApiStatusError(t *testing.T, ch <-chan interface{}, msg string) {
|
||||
func expectApiStatusError(t *testing.T, ch <-chan runtime.Object, msg string) {
|
||||
out := <-ch
|
||||
status, ok := out.(*api.Status)
|
||||
if !ok {
|
||||
@@ -44,7 +44,7 @@ func expectApiStatusError(t *testing.T, ch <-chan interface{}, msg string) {
|
||||
}
|
||||
}
|
||||
|
||||
func expectPod(t *testing.T, ch <-chan interface{}) (*api.Pod, bool) {
|
||||
func expectPod(t *testing.T, ch <-chan runtime.Object) (*api.Pod, bool) {
|
||||
out := <-ch
|
||||
pod, ok := out.(*api.Pod)
|
||||
if !ok || pod == nil {
|
||||
@@ -178,13 +178,13 @@ func TestPodDecode(t *testing.T) {
|
||||
ID: "foo",
|
||||
},
|
||||
}
|
||||
body, err := runtime.Encode(expected)
|
||||
body, err := runtime.DefaultCodec.Encode(expected)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
actual := storage.New()
|
||||
if err := runtime.DecodeInto(body, actual); err != nil {
|
||||
if err := runtime.DefaultCodec.DecodeInto(body, actual); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ func (r *ControllerRegistry) GetController(ID string) (*api.ReplicationControlle
|
||||
return &api.ReplicationController{}, r.Err
|
||||
}
|
||||
|
||||
func (r *ControllerRegistry) CreateController(controller api.ReplicationController) error {
|
||||
func (r *ControllerRegistry) CreateController(controller *api.ReplicationController) error {
|
||||
return r.Err
|
||||
}
|
||||
|
||||
func (r *ControllerRegistry) UpdateController(controller api.ReplicationController) error {
|
||||
func (r *ControllerRegistry) UpdateController(controller *api.ReplicationController) error {
|
||||
return r.Err
|
||||
}
|
||||
|
||||
|
||||
@@ -68,19 +68,19 @@ func (r *PodRegistry) GetPod(podId string) (*api.Pod, error) {
|
||||
return r.Pod, r.Err
|
||||
}
|
||||
|
||||
func (r *PodRegistry) CreatePod(pod api.Pod) error {
|
||||
func (r *PodRegistry) CreatePod(pod *api.Pod) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
r.Pod = &pod
|
||||
r.mux.Action(watch.Added, &pod)
|
||||
r.Pod = pod
|
||||
r.mux.Action(watch.Added, pod)
|
||||
return r.Err
|
||||
}
|
||||
|
||||
func (r *PodRegistry) UpdatePod(pod api.Pod) error {
|
||||
func (r *PodRegistry) UpdatePod(pod *api.Pod) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
r.Pod = &pod
|
||||
r.mux.Action(watch.Modified, &pod)
|
||||
r.Pod = pod
|
||||
r.mux.Action(watch.Modified, pod)
|
||||
return r.Err
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ func (r *ServiceRegistry) ListServices() (*api.ServiceList, error) {
|
||||
return &r.List, r.Err
|
||||
}
|
||||
|
||||
func (r *ServiceRegistry) CreateService(svc api.Service) error {
|
||||
r.Service = &svc
|
||||
r.List.Items = append(r.List.Items, svc)
|
||||
func (r *ServiceRegistry) CreateService(svc *api.Service) error {
|
||||
r.Service = svc
|
||||
r.List.Items = append(r.List.Items, *svc)
|
||||
return r.Err
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (r *ServiceRegistry) DeleteService(id string) error {
|
||||
return r.Err
|
||||
}
|
||||
|
||||
func (r *ServiceRegistry) UpdateService(svc api.Service) error {
|
||||
func (r *ServiceRegistry) UpdateService(svc *api.Service) error {
|
||||
r.UpdatedID = svc.ID
|
||||
return r.Err
|
||||
}
|
||||
@@ -76,8 +76,8 @@ func (r *ServiceRegistry) GetEndpoints(id string) (*api.Endpoints, error) {
|
||||
return &r.Endpoints, r.Err
|
||||
}
|
||||
|
||||
func (r *ServiceRegistry) UpdateEndpoints(e api.Endpoints) error {
|
||||
r.Endpoints = e
|
||||
func (r *ServiceRegistry) UpdateEndpoints(e *api.Endpoints) error {
|
||||
r.Endpoints = *e
|
||||
return r.Err
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ import (
|
||||
// Registry is an interface for things that know how to store services.
|
||||
type Registry interface {
|
||||
ListServices() (*api.ServiceList, error)
|
||||
CreateService(svc api.Service) error
|
||||
CreateService(svc *api.Service) error
|
||||
GetService(name string) (*api.Service, error)
|
||||
DeleteService(name string) error
|
||||
UpdateService(svc api.Service) error
|
||||
UpdateService(svc *api.Service) error
|
||||
WatchServices(labels, fields labels.Selector, resourceVersion uint64) (watch.Interface, error)
|
||||
|
||||
// TODO: endpoints and their implementation should be separated, setting endpoints should be
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
@@ -49,7 +50,7 @@ func NewRegistryStorage(registry Registry, cloud cloudprovider.Interface, machin
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
srv := obj.(*api.Service)
|
||||
if errs := validation.ValidateService(srv); len(errs) > 0 {
|
||||
return nil, errors.NewInvalid("service", srv.ID, errs)
|
||||
@@ -57,7 +58,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
|
||||
srv.CreationTimestamp = util.Now()
|
||||
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
// TODO: Consider moving this to a rectification loop, so that we make/remove external load balancers
|
||||
// correctly no matter what http operations happen.
|
||||
if srv.CreateExternalLoadBalancer {
|
||||
@@ -85,7 +86,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err := rs.registry.CreateService(*srv)
|
||||
err := rs.registry.CreateService(srv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -93,18 +94,18 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Delete(id string) (<-chan runtime.Object, error) {
|
||||
service, err := rs.registry.GetService(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
rs.deleteExternalLoadBalancer(service)
|
||||
return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteService(id)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
func (rs *RegistryStorage) Get(id string) (runtime.Object, error) {
|
||||
s, err := rs.registry.GetService(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -112,7 +113,7 @@ func (rs *RegistryStorage) Get(id string) (interface{}, error) {
|
||||
return s, err
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (interface{}, error) {
|
||||
func (rs *RegistryStorage) List(selector labels.Selector) (runtime.Object, error) {
|
||||
list, err := rs.registry.ListServices()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -133,7 +134,7 @@ func (rs *RegistryStorage) Watch(label, field labels.Selector, resourceVersion u
|
||||
return rs.registry.WatchServices(label, field, resourceVersion)
|
||||
}
|
||||
|
||||
func (rs RegistryStorage) New() interface{} {
|
||||
func (rs RegistryStorage) New() runtime.Object {
|
||||
return &api.Service{}
|
||||
}
|
||||
|
||||
@@ -155,14 +156,14 @@ func GetServiceEnvironmentVariables(registry Registry, machine string) ([]api.En
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
|
||||
func (rs *RegistryStorage) Update(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||
srv := obj.(*api.Service)
|
||||
if errs := validation.ValidateService(srv); len(errs) > 0 {
|
||||
return nil, errors.NewInvalid("service", srv.ID, errs)
|
||||
}
|
||||
return apiserver.MakeAsync(func() (interface{}, error) {
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
// TODO: check to see if external load balancer status changed
|
||||
err := rs.registry.UpdateService(*srv)
|
||||
err := rs.registry.UpdateService(srv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ func TestServiceStorageValidatesCreate(t *testing.T) {
|
||||
|
||||
func TestServiceRegistryUpdate(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
registry.CreateService(api.Service{
|
||||
registry.CreateService(&api.Service{
|
||||
Port: 6502,
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
Selector: map[string]string{"bar": "baz1"},
|
||||
@@ -118,7 +118,7 @@ func TestServiceRegistryUpdate(t *testing.T) {
|
||||
|
||||
func TestServiceStorageValidatesUpdate(t *testing.T) {
|
||||
registry := registrytest.NewServiceRegistry()
|
||||
registry.CreateService(api.Service{
|
||||
registry.CreateService(&api.Service{
|
||||
Port: 6502,
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
Selector: map[string]string{"bar": "baz"},
|
||||
@@ -200,7 +200,7 @@ func TestServiceRegistryDelete(t *testing.T) {
|
||||
fakeCloud := &cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
svc := api.Service{
|
||||
svc := &api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
Selector: map[string]string{"bar": "baz"},
|
||||
}
|
||||
@@ -220,7 +220,7 @@ func TestServiceRegistryDeleteExternal(t *testing.T) {
|
||||
fakeCloud := &cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
svc := api.Service{
|
||||
svc := &api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
Selector: map[string]string{"bar": "baz"},
|
||||
CreateExternalLoadBalancer: true,
|
||||
@@ -263,7 +263,7 @@ func TestServiceRegistryGet(t *testing.T) {
|
||||
fakeCloud := &cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
registry.CreateService(api.Service{
|
||||
registry.CreateService(&api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
Selector: map[string]string{"bar": "baz"},
|
||||
})
|
||||
@@ -282,7 +282,7 @@ func TestServiceRegistryResourceLocation(t *testing.T) {
|
||||
fakeCloud := &cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
registry.CreateService(api.Service{
|
||||
registry.CreateService(&api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
Selector: map[string]string{"bar": "baz"},
|
||||
})
|
||||
@@ -310,11 +310,11 @@ func TestServiceRegistryList(t *testing.T) {
|
||||
fakeCloud := &cloud.FakeCloud{}
|
||||
machines := []string{"foo", "bar", "baz"}
|
||||
storage := NewRegistryStorage(registry, fakeCloud, minion.NewRegistry(machines))
|
||||
registry.CreateService(api.Service{
|
||||
registry.CreateService(&api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
Selector: map[string]string{"bar": "baz"},
|
||||
})
|
||||
registry.CreateService(api.Service{
|
||||
registry.CreateService(&api.Service{
|
||||
JSONBase: api.JSONBase{ID: "foo2"},
|
||||
Selector: map[string]string{"bar2": "baz2"},
|
||||
})
|
||||
|
||||
@@ -33,7 +33,7 @@ func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, err := Decode(b)
|
||||
obj, err := DefaultCodec.Decode(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
return Encode(a.Object)
|
||||
return DefaultCodec.Encode(a.Object)
|
||||
}
|
||||
|
||||
// SetYAML implements the yaml.Setter interface.
|
||||
@@ -67,7 +67,7 @@ func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
|
||||
if err != nil {
|
||||
panic("yaml can't reverse its own object")
|
||||
}
|
||||
obj, err := Decode(b)
|
||||
obj, err := DefaultCodec.Decode(b)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
|
||||
return
|
||||
}
|
||||
// Encode returns JSON, which is conveniently a subset of YAML.
|
||||
v, err := Encode(a.Object)
|
||||
v, err := DefaultCodec.Encode(a.Object)
|
||||
if err != nil {
|
||||
panic("impossible to encode API object!")
|
||||
}
|
||||
|
||||
@@ -22,14 +22,19 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type EmbeddedTest struct {
|
||||
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) {
|
||||
type EmbeddedTest struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Object EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"`
|
||||
EmptyObject EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
|
||||
}
|
||||
AddKnownTypes("", EmbeddedTest{})
|
||||
AddKnownTypes("v1beta1", EmbeddedTest{})
|
||||
// TODO(dbsmith) fix EmbeddedObject to not use DefaultScheme.
|
||||
s := DefaultScheme
|
||||
s.AddKnownTypes("", &EmbeddedTest{})
|
||||
s.AddKnownTypes("v1beta1", &EmbeddedTest{})
|
||||
|
||||
outer := &EmbeddedTest{
|
||||
JSONBase: JSONBase{ID: "outer"},
|
||||
@@ -40,14 +45,14 @@ func TestEmbeddedObject(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
wire, err := Encode(outer)
|
||||
wire, err := s.Encode(outer)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected encode error '%v'", err)
|
||||
}
|
||||
|
||||
t.Logf("Wire format is:\n%v\n", string(wire))
|
||||
|
||||
decoded, err := Decode(wire)
|
||||
decoded, err := s.Decode(wire)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected decode error %v", err)
|
||||
}
|
||||
|
||||
@@ -24,41 +24,44 @@ import (
|
||||
"gopkg.in/v1/yaml"
|
||||
)
|
||||
|
||||
// codec defines methods for serializing and deserializing API
|
||||
// objects.
|
||||
type codec interface {
|
||||
Encode(obj interface{}) (data []byte, err error)
|
||||
Decode(data []byte) (interface{}, error)
|
||||
DecodeInto(data []byte, obj interface{}) error
|
||||
var DefaultResourceVersioner ResourceVersioner = NewJSONBaseResourceVersioner()
|
||||
var DefaultScheme = NewScheme("", "v1beta1")
|
||||
var DefaultCodec Codec = DefaultScheme
|
||||
|
||||
// Scheme defines methods for serializing and deserializing API objects. It
|
||||
// is an adaptation of conversion's Scheme for our API objects.
|
||||
type Scheme struct {
|
||||
raw *conversion.Scheme
|
||||
}
|
||||
|
||||
// resourceVersioner provides methods for setting and retrieving
|
||||
// the resource version from an API object.
|
||||
type resourceVersioner interface {
|
||||
SetResourceVersion(obj interface{}, version uint64) error
|
||||
ResourceVersion(obj interface{}) (uint64, error)
|
||||
}
|
||||
|
||||
var ResourceVersioner resourceVersioner = NewJSONBaseResourceVersioner()
|
||||
var conversionScheme = conversion.NewScheme()
|
||||
var Codec codec = conversionScheme
|
||||
|
||||
func init() {
|
||||
conversionScheme.InternalVersion = ""
|
||||
conversionScheme.ExternalVersion = "v1beta1"
|
||||
conversionScheme.MetaInsertionFactory = metaInsertion{}
|
||||
// NewScheme creates a new Scheme. A default scheme is provided and accessible
|
||||
// as the "DefaultScheme" variable.
|
||||
func NewScheme(internalVersion, externalVersion string) *Scheme {
|
||||
s := &Scheme{conversion.NewScheme()}
|
||||
s.raw.InternalVersion = internalVersion
|
||||
s.raw.ExternalVersion = externalVersion
|
||||
s.raw.MetaInsertionFactory = metaInsertion{}
|
||||
return s
|
||||
}
|
||||
|
||||
// AddKnownTypes registers the types of the arguments to the marshaller of the package api.
|
||||
// Encode() refuses the object unless its type is registered with AddKnownTypes.
|
||||
func AddKnownTypes(version string, types ...interface{}) {
|
||||
conversionScheme.AddKnownTypes(version, types...)
|
||||
func (s *Scheme) AddKnownTypes(version string, types ...Object) {
|
||||
interfaces := make([]interface{}, len(types))
|
||||
for i := range types {
|
||||
interfaces[i] = types[i]
|
||||
}
|
||||
s.raw.AddKnownTypes(version, interfaces...)
|
||||
}
|
||||
|
||||
// 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 New(versionName, typeName string) (interface{}, error) {
|
||||
return conversionScheme.NewObject(versionName, typeName)
|
||||
func (s *Scheme) New(versionName, typeName string) (Object, error) {
|
||||
obj, err := s.raw.NewObject(versionName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(Object), nil
|
||||
}
|
||||
|
||||
// AddConversionFuncs adds a function to the list of conversion functions. The given
|
||||
@@ -73,20 +76,20 @@ func New(versionName, typeName string) (interface{}, error) {
|
||||
// sanely copy fields that have the same names. It's OK if the destination type has
|
||||
// extra fields, but it must not remove any. So you only need to add a conversion
|
||||
// function for things with changed/removed fields.
|
||||
func AddConversionFuncs(conversionFuncs ...interface{}) error {
|
||||
return conversionScheme.AddConversionFuncs(conversionFuncs...)
|
||||
func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error {
|
||||
return s.raw.AddConversionFuncs(conversionFuncs...)
|
||||
}
|
||||
|
||||
// Convert will attempt to convert in into out. Both must be pointers to API objects.
|
||||
// Convert will attempt to convert in into out. Both must be pointers.
|
||||
// For easy testing of conversion functions. Returns an error if the conversion isn't
|
||||
// possible.
|
||||
func Convert(in, out interface{}) error {
|
||||
return conversionScheme.Convert(in, out)
|
||||
func (s *Scheme) Convert(in, out interface{}) error {
|
||||
return s.raw.Convert(in, out)
|
||||
}
|
||||
|
||||
// FindJSONBase takes an arbitary api type, returns pointer to its JSONBase field.
|
||||
// obj must be a pointer to an api type.
|
||||
func FindJSONBase(obj interface{}) (JSONBaseInterface, error) {
|
||||
func FindJSONBase(obj Object) (JSONBaseInterface, error) {
|
||||
v, err := enforcePtr(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -108,8 +111,8 @@ func FindJSONBase(obj interface{}) (JSONBaseInterface, error) {
|
||||
}
|
||||
|
||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
|
||||
func EncodeOrDie(obj interface{}) string {
|
||||
return conversionScheme.EncodeOrDie(obj)
|
||||
func (s *Scheme) EncodeOrDie(obj Object) string {
|
||||
return s.raw.EncodeOrDie(obj)
|
||||
}
|
||||
|
||||
// Encode turns the given api object into an appropriate JSON string.
|
||||
@@ -146,14 +149,14 @@ func EncodeOrDie(obj interface{}) string {
|
||||
// default will be needed, to allow operating in clusters that haven't yet
|
||||
// upgraded.
|
||||
//
|
||||
func Encode(obj interface{}) (data []byte, err error) {
|
||||
return conversionScheme.Encode(obj)
|
||||
func (s *Scheme) Encode(obj Object) (data []byte, err error) {
|
||||
return s.raw.Encode(obj)
|
||||
}
|
||||
|
||||
// enforcePtr ensures that obj is a pointer of some sort. Returns a reflect.Value of the
|
||||
// dereferenced pointer, ensuring that it is settable/addressable.
|
||||
// Returns an error if this is not possible.
|
||||
func enforcePtr(obj interface{}) (reflect.Value, error) {
|
||||
func enforcePtr(obj Object) (reflect.Value, error) {
|
||||
v := reflect.ValueOf(obj)
|
||||
if v.Kind() != reflect.Ptr {
|
||||
return reflect.Value{}, fmt.Errorf("expected pointer, but got %v", v.Type().Name())
|
||||
@@ -181,8 +184,12 @@ func VersionAndKind(data []byte) (version, kind string, err error) {
|
||||
// Deduces the type based upon the APIVersion and Kind fields, which are set
|
||||
// by Encode. Only versioned objects (APIVersion != "") are accepted. The object
|
||||
// will be converted into the in-memory unversioned type before being returned.
|
||||
func Decode(data []byte) (interface{}, error) {
|
||||
return conversionScheme.Decode(data)
|
||||
func (s *Scheme) Decode(data []byte) (Object, error) {
|
||||
obj, err := s.raw.Decode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(Object), nil
|
||||
}
|
||||
|
||||
// DecodeInto parses a YAML or JSON string and stores it in obj. Returns an error
|
||||
@@ -190,22 +197,22 @@ func Decode(data []byte) (interface{}, error) {
|
||||
// pointer to an api type.
|
||||
// If obj's APIVersion doesn't match that in data, an attempt will be made to convert
|
||||
// data into obj's version.
|
||||
func DecodeInto(data []byte, obj interface{}) error {
|
||||
return conversionScheme.DecodeInto(data, obj)
|
||||
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.
|
||||
// TODO(dbsmith): implement directly instead of via Encode/Decode
|
||||
func Copy(obj interface{}) (interface{}, error) {
|
||||
data, err := Encode(obj)
|
||||
func (s *Scheme) Copy(obj Object) (Object, error) {
|
||||
data, err := s.Encode(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Decode(data)
|
||||
return s.Decode(data)
|
||||
}
|
||||
|
||||
func CopyOrDie(obj interface{}) interface{} {
|
||||
newObj, err := Copy(obj)
|
||||
func (s *Scheme) CopyOrDie(obj Object) Object {
|
||||
newObj, err := s.Copy(obj)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -25,31 +25,13 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func TestEncode_NonPtr(t *testing.T) {
|
||||
pod := api.Pod{
|
||||
Labels: map[string]string{"name": "foo"},
|
||||
}
|
||||
obj := interface{}(pod)
|
||||
data, err := runtime.Encode(obj)
|
||||
obj2, err2 := runtime.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
}
|
||||
if _, ok := obj2.(*api.Pod); !ok {
|
||||
t.Fatalf("Got wrong type")
|
||||
}
|
||||
if !reflect.DeepEqual(obj2, &pod) {
|
||||
t.Errorf("Expected:\n %#v,\n Got:\n %#v", &pod, obj2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode_Ptr(t *testing.T) {
|
||||
func TestEncode(t *testing.T) {
|
||||
pod := &api.Pod{
|
||||
Labels: map[string]string{"name": "foo"},
|
||||
}
|
||||
obj := interface{}(pod)
|
||||
data, err := runtime.Encode(obj)
|
||||
obj2, err2 := runtime.Decode(data)
|
||||
obj := runtime.Object(pod)
|
||||
data, err := runtime.DefaultScheme.Encode(obj)
|
||||
obj2, err2 := runtime.DefaultScheme.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
}
|
||||
@@ -63,11 +45,11 @@ func TestEncode_Ptr(t *testing.T) {
|
||||
|
||||
func TestBadJSONRejection(t *testing.T) {
|
||||
badJSONMissingKind := []byte(`{ }`)
|
||||
if _, err := runtime.Decode(badJSONMissingKind); err == nil {
|
||||
if _, err := runtime.DefaultScheme.Decode(badJSONMissingKind); err == nil {
|
||||
t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind)
|
||||
}
|
||||
badJSONUnknownType := []byte(`{"kind": "bar"}`)
|
||||
if _, err1 := runtime.Decode(badJSONUnknownType); err1 == nil {
|
||||
if _, err1 := runtime.DefaultScheme.Decode(badJSONUnknownType); err1 == nil {
|
||||
t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
|
||||
}
|
||||
/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)
|
||||
|
||||
40
pkg/runtime/interfaces.go
Normal file
40
pkg/runtime/interfaces.go
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
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 runtime
|
||||
|
||||
// Codec defines methods for serializing and deserializing API objects.
|
||||
type Codec interface {
|
||||
Encode(obj Object) (data []byte, err error)
|
||||
Decode(data []byte) (Object, error)
|
||||
DecodeInto(data []byte, obj Object) error
|
||||
}
|
||||
|
||||
// ResourceVersioner provides methods for setting and retrieving
|
||||
// the resource version from an API object.
|
||||
type ResourceVersioner interface {
|
||||
SetResourceVersion(obj Object, version uint64) error
|
||||
ResourceVersion(obj Object) (uint64, error)
|
||||
}
|
||||
|
||||
// All api types must support the Object interface. It's deliberately tiny so that this is not an onerous
|
||||
// burden. Implement it with a pointer reciever; this will allow us to use the go compiler to check the
|
||||
// one thing about our objects that it's capable of checking for us.
|
||||
type Object interface {
|
||||
// This function is used only to enforce membership. It's never called.
|
||||
// TODO: Consider mass rename in the future to make it do something useful.
|
||||
IsAnAPIObject()
|
||||
}
|
||||
@@ -23,13 +23,13 @@ import (
|
||||
|
||||
// NewJSONBaseResourceVersioner returns a resourceVersioner that can set or
|
||||
// retrieve ResourceVersion on objects derived from JSONBase.
|
||||
func NewJSONBaseResourceVersioner() resourceVersioner {
|
||||
func NewJSONBaseResourceVersioner() ResourceVersioner {
|
||||
return &jsonBaseResourceVersioner{}
|
||||
}
|
||||
|
||||
type jsonBaseResourceVersioner struct{}
|
||||
|
||||
func (v jsonBaseResourceVersioner) ResourceVersion(obj interface{}) (uint64, error) {
|
||||
func (v jsonBaseResourceVersioner) ResourceVersion(obj Object) (uint64, error) {
|
||||
json, err := FindJSONBase(obj)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -37,7 +37,7 @@ func (v jsonBaseResourceVersioner) ResourceVersion(obj interface{}) (uint64, err
|
||||
return json.ResourceVersion(), nil
|
||||
}
|
||||
|
||||
func (v jsonBaseResourceVersioner) SetResourceVersion(obj interface{}, version uint64) error {
|
||||
func (v jsonBaseResourceVersioner) SetResourceVersion(obj Object, version uint64) error {
|
||||
json, err := FindJSONBase(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -77,20 +77,20 @@ func TestGenericJSONBase(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type MyAPIObject struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
|
||||
func (*MyAPIObject) IsAnAPIObject() {}
|
||||
|
||||
type MyIncorrectlyMarkedAsAPIObject struct {
|
||||
}
|
||||
|
||||
func (*MyIncorrectlyMarkedAsAPIObject) IsAnAPIObject() {}
|
||||
|
||||
func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
type JSONBase struct {
|
||||
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
|
||||
ID string `json:"id,omitempty" yaml:"id,omitempty"`
|
||||
CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"`
|
||||
SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"`
|
||||
ResourceVersion uint64 `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"`
|
||||
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
|
||||
}
|
||||
type MyAPIObject struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
type T struct {
|
||||
Object interface{}
|
||||
Object
|
||||
Expected uint64
|
||||
}
|
||||
testCases := map[string]T{
|
||||
@@ -110,10 +110,10 @@ func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
}
|
||||
|
||||
failingCases := map[string]struct {
|
||||
Object interface{}
|
||||
Object
|
||||
Expected uint64
|
||||
}{
|
||||
"not a valid object to try": {JSONBase{ResourceVersion: 1}, 1},
|
||||
"not a valid object to try": {&MyIncorrectlyMarkedAsAPIObject{}, 1},
|
||||
}
|
||||
for key, testCase := range failingCases {
|
||||
_, err := versioning.ResourceVersion(testCase.Object)
|
||||
@@ -123,7 +123,7 @@ func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
}
|
||||
|
||||
setCases := map[string]struct {
|
||||
Object interface{}
|
||||
Object
|
||||
Expected uint64
|
||||
}{
|
||||
"pointer to api object with version": {&MyAPIObject{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
|
||||
@@ -140,17 +140,4 @@ func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
t.Errorf("%s: expected %d, got %d", key, 5, actual)
|
||||
}
|
||||
}
|
||||
|
||||
failingSetCases := map[string]struct {
|
||||
Object interface{}
|
||||
Expected uint64
|
||||
}{
|
||||
"empty api object": {MyAPIObject{}, 0},
|
||||
"api object with version": {MyAPIObject{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
|
||||
}
|
||||
for key, testCase := range failingSetCases {
|
||||
if err := versioning.SetResourceVersion(testCase.Object, 5); err == nil {
|
||||
t.Errorf("%s: unexpected non-error", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,9 @@ import (
|
||||
// runtime.JSONBase `yaml:",inline" json:",inline"`
|
||||
// ... // other fields
|
||||
// }
|
||||
// func (*MyAwesomeAPIObject) IsAnAPIObject() {}
|
||||
//
|
||||
// JSONBase is provided here for convenience. You may use it directlly from this package or define
|
||||
// JSONBase is provided here for convenience. You may use it directly from this package or define
|
||||
// your own with the same fields.
|
||||
//
|
||||
type JSONBase struct {
|
||||
@@ -43,17 +44,16 @@ type JSONBase struct {
|
||||
}
|
||||
|
||||
// EmbeddedObject has 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 interface{}
|
||||
// via the Get() function. Only objects having a JSONBase may be stored via Object.
|
||||
// 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.
|
||||
//
|
||||
// Note that object assumes that you've registered all of your api types with the api package.
|
||||
//
|
||||
// Note that objects will be serialized into the api package's default external versioned type;
|
||||
// this should be fixed in the future to use the version of the current Codec instead.
|
||||
// TODO(dbsmith): Stop using runtime.Codec, use the codec appropriate for the conversion (I have a plan).
|
||||
type EmbeddedObject struct {
|
||||
Object interface{}
|
||||
Object
|
||||
}
|
||||
|
||||
// Extension allows api objects with unknown types to be passed-through. This can be used
|
||||
@@ -61,4 +61,8 @@ type EmbeddedObject struct {
|
||||
// JSONBase features-- kind, version, resourceVersion, etc.
|
||||
// TODO: Not implemented yet
|
||||
type Extension struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
// RawJSON to go here.
|
||||
}
|
||||
|
||||
func (*Extension) IsAnAPIObject() {}
|
||||
|
||||
@@ -73,7 +73,7 @@ func (e *EndpointController) SyncServiceEndpoints() error {
|
||||
endpoints[ix] = net.JoinHostPort(pod.CurrentState.PodIP, strconv.Itoa(port))
|
||||
}
|
||||
// TODO: this is totally broken, we need to compute this and store inside an AtomicUpdate loop.
|
||||
err = e.serviceRegistry.UpdateEndpoints(api.Endpoints{
|
||||
err = e.serviceRegistry.UpdateEndpoints(&api.Endpoints{
|
||||
JSONBase: api.JSONBase{ID: service.ID},
|
||||
Endpoints: endpoints,
|
||||
})
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
@@ -42,7 +43,7 @@ func NewAPIEventDecoder(stream io.ReadCloser) *APIEventDecoder {
|
||||
|
||||
// Decode blocks until it can return the next object in the stream. Returns an error
|
||||
// if the stream is closed or an object can't be decoded.
|
||||
func (d *APIEventDecoder) Decode() (action watch.EventType, object interface{}, err error) {
|
||||
func (d *APIEventDecoder) Decode() (action watch.EventType, object runtime.Object, err error) {
|
||||
var got api.WatchEvent
|
||||
err = d.decoder.Decode(&got)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/coreos/go-etcd/etcd"
|
||||
)
|
||||
|
||||
@@ -38,19 +39,6 @@ var (
|
||||
EtcdErrorValueRequired = &etcd.EtcdError{ErrorCode: EtcdErrorCodeValueRequired}
|
||||
)
|
||||
|
||||
// Codec provides methods for transforming Etcd values into objects and back.
|
||||
type Codec interface {
|
||||
Encode(obj interface{}) (data []byte, err error)
|
||||
Decode(data []byte) (interface{}, error)
|
||||
DecodeInto(data []byte, obj interface{}) error
|
||||
}
|
||||
|
||||
// ResourceVersioner provides methods for managing object modification tracking.
|
||||
type ResourceVersioner interface {
|
||||
SetResourceVersion(obj interface{}, version uint64) error
|
||||
ResourceVersion(obj interface{}) (uint64, error)
|
||||
}
|
||||
|
||||
// EtcdClient is an injectable interface for testing.
|
||||
type EtcdClient interface {
|
||||
AddChild(key, data string, ttl uint64) (*etcd.Response, error)
|
||||
@@ -77,9 +65,9 @@ type EtcdGetSet interface {
|
||||
// EtcdHelper offers common object marshalling/unmarshalling operations on an etcd client.
|
||||
type EtcdHelper struct {
|
||||
Client EtcdGetSet
|
||||
Codec Codec
|
||||
Codec runtime.Codec
|
||||
// optional, no atomic operations can be performed without this interface
|
||||
ResourceVersioner ResourceVersioner
|
||||
ResourceVersioner runtime.ResourceVersioner
|
||||
}
|
||||
|
||||
// IsEtcdNotFound returns true iff err is an etcd not found error.
|
||||
@@ -151,9 +139,9 @@ func (h *EtcdHelper) ExtractList(key string, slicePtr interface{}, resourceVersi
|
||||
v := pv.Elem()
|
||||
for _, node := range nodes {
|
||||
obj := reflect.New(v.Type().Elem())
|
||||
err = h.Codec.DecodeInto([]byte(node.Value), obj.Interface())
|
||||
err = h.Codec.DecodeInto([]byte(node.Value), obj.Interface().(runtime.Object))
|
||||
if h.ResourceVersioner != nil {
|
||||
_ = h.ResourceVersioner.SetResourceVersion(obj.Interface(), node.ModifiedIndex)
|
||||
_ = h.ResourceVersioner.SetResourceVersion(obj.Interface().(runtime.Object), node.ModifiedIndex)
|
||||
// being unable to set the version does not prevent the object from being extracted
|
||||
}
|
||||
if err != nil {
|
||||
@@ -167,12 +155,12 @@ func (h *EtcdHelper) ExtractList(key string, slicePtr interface{}, resourceVersi
|
||||
// ExtractObj unmarshals json found at key into objPtr. On a not found error, will either return
|
||||
// a zero object of the requested type, or an error, depending on ignoreNotFound. Treats
|
||||
// empty responses and nil response nodes exactly like a not found error.
|
||||
func (h *EtcdHelper) ExtractObj(key string, objPtr interface{}, ignoreNotFound bool) error {
|
||||
func (h *EtcdHelper) ExtractObj(key string, objPtr runtime.Object, ignoreNotFound bool) error {
|
||||
_, _, err := h.bodyAndExtractObj(key, objPtr, ignoreNotFound)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr interface{}, ignoreNotFound bool) (body string, modifiedIndex uint64, err error) {
|
||||
func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr runtime.Object, ignoreNotFound bool) (body string, modifiedIndex uint64, err error) {
|
||||
response, err := h.Client.Get(key, false, false)
|
||||
|
||||
if err != nil && !IsEtcdNotFound(err) {
|
||||
@@ -198,7 +186,7 @@ func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr interface{}, ignoreNot
|
||||
}
|
||||
|
||||
// CreateObj adds a new object at a key unless it already exists.
|
||||
func (h *EtcdHelper) CreateObj(key string, obj interface{}) error {
|
||||
func (h *EtcdHelper) CreateObj(key string, obj runtime.Object) error {
|
||||
data, err := h.Codec.Encode(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -221,7 +209,7 @@ func (h *EtcdHelper) Delete(key string, recursive bool) error {
|
||||
|
||||
// SetObj marshals obj via json, and stores under key. Will do an
|
||||
// atomic update if obj's ResourceVersion field is set.
|
||||
func (h *EtcdHelper) SetObj(key string, obj interface{}) error {
|
||||
func (h *EtcdHelper) SetObj(key string, obj runtime.Object) error {
|
||||
data, err := h.Codec.Encode(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -240,7 +228,7 @@ func (h *EtcdHelper) SetObj(key string, obj interface{}) error {
|
||||
|
||||
// Pass an EtcdUpdateFunc to EtcdHelper.AtomicUpdate to make an atomic etcd update.
|
||||
// See the comment for AtomicUpdate for more detail.
|
||||
type EtcdUpdateFunc func(input interface{}) (output interface{}, err error)
|
||||
type EtcdUpdateFunc func(input runtime.Object) (output runtime.Object, err error)
|
||||
|
||||
// AtomicUpdate generalizes the pattern that allows for making atomic updates to etcd objects.
|
||||
// Note, tryUpdate may be called more than once.
|
||||
@@ -248,7 +236,7 @@ type EtcdUpdateFunc func(input interface{}) (output interface{}, err error)
|
||||
// Example:
|
||||
//
|
||||
// h := &util.EtcdHelper{client, encoding, versioning}
|
||||
// err := h.AtomicUpdate("myKey", &MyType{}, func(input interface{}) (interface{}, error) {
|
||||
// err := h.AtomicUpdate("myKey", &MyType{}, func(input runtime.Object) (runtime.Object, error) {
|
||||
// // Before this function is called, currentObj has been reset to etcd's current
|
||||
// // contents for "myKey".
|
||||
//
|
||||
@@ -261,14 +249,14 @@ type EtcdUpdateFunc func(input interface{}) (output interface{}, err error)
|
||||
// return cur, nil
|
||||
// })
|
||||
//
|
||||
func (h *EtcdHelper) AtomicUpdate(key string, ptrToType interface{}, tryUpdate EtcdUpdateFunc) error {
|
||||
func (h *EtcdHelper) AtomicUpdate(key string, ptrToType runtime.Object, tryUpdate EtcdUpdateFunc) error {
|
||||
pt := reflect.TypeOf(ptrToType)
|
||||
if pt.Kind() != reflect.Ptr {
|
||||
// Panic is appropriate, because this is a programming error.
|
||||
panic("need ptr to type")
|
||||
}
|
||||
for {
|
||||
obj := reflect.New(pt.Elem()).Interface()
|
||||
obj := reflect.New(pt.Elem()).Interface().(runtime.Object)
|
||||
origBody, index, err := h.bodyAndExtractObj(key, obj, true)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/coreos/go-etcd/etcd"
|
||||
@@ -40,15 +39,16 @@ type TestResource struct {
|
||||
Value int `json:"value" yaml:"value,omitempty"`
|
||||
}
|
||||
|
||||
var scheme *conversion.Scheme
|
||||
var codec = runtime.Codec
|
||||
var versioner = runtime.ResourceVersioner
|
||||
func (*TestResource) IsAnAPIObject() {}
|
||||
|
||||
var scheme *runtime.Scheme
|
||||
var codec = runtime.DefaultCodec
|
||||
var versioner = runtime.DefaultResourceVersioner
|
||||
|
||||
func init() {
|
||||
scheme = conversion.NewScheme()
|
||||
scheme.ExternalVersion = "v1beta1"
|
||||
scheme.AddKnownTypes("", TestResource{})
|
||||
scheme.AddKnownTypes("v1beta1", TestResource{})
|
||||
scheme = runtime.NewScheme("", "v1beta1")
|
||||
scheme.AddKnownTypes("", &TestResource{})
|
||||
scheme.AddKnownTypes("v1beta1", &TestResource{})
|
||||
}
|
||||
|
||||
func TestIsEtcdNotFound(t *testing.T) {
|
||||
@@ -166,7 +166,7 @@ func TestExtractObjNotFoundErr(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetObj(t *testing.T) {
|
||||
obj := api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
obj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
helper := EtcdHelper{fakeClient, codec, versioner}
|
||||
err := helper.SetObj("/some/key", obj)
|
||||
@@ -191,7 +191,7 @@ func TestSetObjWithVersion(t *testing.T) {
|
||||
fakeClient.Data["/some/key"] = EtcdResponseWithError{
|
||||
R: &etcd.Response{
|
||||
Node: &etcd.Node{
|
||||
Value: runtime.EncodeOrDie(obj),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(obj),
|
||||
ModifiedIndex: 1,
|
||||
},
|
||||
},
|
||||
@@ -214,7 +214,7 @@ func TestSetObjWithVersion(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetObjWithoutResourceVersioner(t *testing.T) {
|
||||
obj := api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
obj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
helper := EtcdHelper{fakeClient, codec, nil}
|
||||
err := helper.SetObj("/some/key", obj)
|
||||
@@ -241,7 +241,7 @@ func TestAtomicUpdate(t *testing.T) {
|
||||
// Create a new node.
|
||||
fakeClient.ExpectNotFoundGet("/some/key")
|
||||
obj := &TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: 1}
|
||||
err := helper.AtomicUpdate("/some/key", &TestResource{}, func(in interface{}) (interface{}, error) {
|
||||
err := helper.AtomicUpdate("/some/key", &TestResource{}, func(in runtime.Object) (runtime.Object, error) {
|
||||
return obj, nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -260,7 +260,7 @@ func TestAtomicUpdate(t *testing.T) {
|
||||
// Update an existing node.
|
||||
callbackCalled := false
|
||||
objUpdate := &TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: 2}
|
||||
err = helper.AtomicUpdate("/some/key", &TestResource{}, func(in interface{}) (interface{}, error) {
|
||||
err = helper.AtomicUpdate("/some/key", &TestResource{}, func(in runtime.Object) (runtime.Object, error) {
|
||||
callbackCalled = true
|
||||
|
||||
if in.(*TestResource).Value != 1 {
|
||||
@@ -295,7 +295,7 @@ func TestAtomicUpdateNoChange(t *testing.T) {
|
||||
// Create a new node.
|
||||
fakeClient.ExpectNotFoundGet("/some/key")
|
||||
obj := &TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: 1}
|
||||
err := helper.AtomicUpdate("/some/key", &TestResource{}, func(in interface{}) (interface{}, error) {
|
||||
err := helper.AtomicUpdate("/some/key", &TestResource{}, func(in runtime.Object) (runtime.Object, error) {
|
||||
return obj, nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -306,7 +306,7 @@ func TestAtomicUpdateNoChange(t *testing.T) {
|
||||
callbackCalled := false
|
||||
objUpdate := &TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: 1}
|
||||
fakeClient.Err = errors.New("should not be called")
|
||||
err = helper.AtomicUpdate("/some/key", &TestResource{}, func(in interface{}) (interface{}, error) {
|
||||
err = helper.AtomicUpdate("/some/key", &TestResource{}, func(in runtime.Object) (runtime.Object, error) {
|
||||
callbackCalled = true
|
||||
return objUpdate, nil
|
||||
})
|
||||
@@ -338,7 +338,7 @@ func TestAtomicUpdate_CreateCollision(t *testing.T) {
|
||||
defer wgDone.Done()
|
||||
|
||||
firstCall := true
|
||||
err := helper.AtomicUpdate("/some/key", &TestResource{}, func(in interface{}) (interface{}, error) {
|
||||
err := helper.AtomicUpdate("/some/key", &TestResource{}, func(in runtime.Object) (runtime.Object, error) {
|
||||
defer func() { firstCall = false }()
|
||||
|
||||
if firstCall {
|
||||
@@ -348,7 +348,7 @@ func TestAtomicUpdate_CreateCollision(t *testing.T) {
|
||||
}
|
||||
|
||||
currValue := in.(*TestResource).Value
|
||||
obj := TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: currValue + 1}
|
||||
obj := &TestResource{JSONBase: api.JSONBase{ID: "foo"}, Value: currValue + 1}
|
||||
return obj, nil
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -19,6 +19,7 @@ package tools
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
"github.com/coreos/go-etcd/etcd"
|
||||
@@ -27,10 +28,10 @@ import (
|
||||
|
||||
// FilterFunc is a predicate which takes an API object and returns true
|
||||
// iff the object should remain in the set.
|
||||
type FilterFunc func(obj interface{}) bool
|
||||
type FilterFunc func(obj runtime.Object) bool
|
||||
|
||||
// Everything is a FilterFunc which accepts all objects.
|
||||
func Everything(interface{}) bool {
|
||||
func Everything(runtime.Object) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ func (h *EtcdHelper) Watch(key string, resourceVersion uint64) (watch.Interface,
|
||||
// change or wrap the serialized etcd object.
|
||||
//
|
||||
// startTime := time.Now()
|
||||
// helper.WatchAndTransform(key, version, func(input interface{}) (interface{}, error) {
|
||||
// helper.WatchAndTransform(key, version, func(input runtime.Object) (runtime.Object, error) {
|
||||
// value := input.(TimeAwareValue)
|
||||
// value.Since = startTime
|
||||
// return value, nil
|
||||
@@ -72,12 +73,12 @@ func (h *EtcdHelper) WatchAndTransform(key string, resourceVersion uint64, trans
|
||||
}
|
||||
|
||||
// TransformFunc attempts to convert an object to another object for use with a watcher.
|
||||
type TransformFunc func(interface{}) (interface{}, error)
|
||||
type TransformFunc func(runtime.Object) (runtime.Object, error)
|
||||
|
||||
// etcdWatcher converts a native etcd watch to a watch.Interface.
|
||||
type etcdWatcher struct {
|
||||
encoding Codec
|
||||
versioner ResourceVersioner
|
||||
encoding runtime.Codec
|
||||
versioner runtime.ResourceVersioner
|
||||
transform TransformFunc
|
||||
|
||||
list bool // If we're doing a recursive watch, should be true.
|
||||
@@ -98,7 +99,7 @@ type etcdWatcher struct {
|
||||
|
||||
// newEtcdWatcher returns a new etcdWatcher; if list is true, watch sub-nodes. If you provide a transform
|
||||
// and a versioner, the versioner must be able to handle the objects that transform creates.
|
||||
func newEtcdWatcher(list bool, filter FilterFunc, encoding Codec, versioner ResourceVersioner, transform TransformFunc) *etcdWatcher {
|
||||
func newEtcdWatcher(list bool, filter FilterFunc, encoding runtime.Codec, versioner runtime.ResourceVersioner, transform TransformFunc) *etcdWatcher {
|
||||
w := &etcdWatcher{
|
||||
encoding: encoding,
|
||||
versioner: versioner,
|
||||
@@ -192,7 +193,7 @@ func (w *etcdWatcher) translate() {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *etcdWatcher) decodeObject(data []byte, index uint64) (interface{}, error) {
|
||||
func (w *etcdWatcher) decodeObject(data []byte, index uint64) (runtime.Object, error) {
|
||||
obj, err := w.encoding.Decode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -260,7 +261,7 @@ func (w *etcdWatcher) sendModify(res *etcd.Response) {
|
||||
}
|
||||
curObjPasses := w.filter(curObj)
|
||||
oldObjPasses := false
|
||||
var oldObj interface{}
|
||||
var oldObj runtime.Object
|
||||
if res.PrevNode != nil && res.PrevNode.Value != "" {
|
||||
// Ignore problems reading the old object.
|
||||
if oldObj, err = w.decodeObject([]byte(res.PrevNode.Value), res.PrevNode.ModifiedIndex); err == nil {
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestWatchInterpretations(t *testing.T) {
|
||||
podFoo := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
podBar := &api.Pod{JSONBase: api.JSONBase{ID: "bar"}}
|
||||
podBaz := &api.Pod{JSONBase: api.JSONBase{ID: "baz"}}
|
||||
firstLetterIsB := func(obj interface{}) bool {
|
||||
firstLetterIsB := func(obj runtime.Object) bool {
|
||||
return obj.(*api.Pod).ID[0] == 'b'
|
||||
}
|
||||
|
||||
@@ -44,66 +44,66 @@ func TestWatchInterpretations(t *testing.T) {
|
||||
nodeValue string
|
||||
expectEmit bool
|
||||
expectType watch.EventType
|
||||
expectObject interface{}
|
||||
expectObject runtime.Object
|
||||
}{
|
||||
"create": {
|
||||
actions: []string{"create", "get"},
|
||||
nodeValue: runtime.EncodeOrDie(podBar),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podBar),
|
||||
expectEmit: true,
|
||||
expectType: watch.Added,
|
||||
expectObject: podBar,
|
||||
},
|
||||
"create but filter blocks": {
|
||||
actions: []string{"create", "get"},
|
||||
nodeValue: runtime.EncodeOrDie(podFoo),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podFoo),
|
||||
expectEmit: false,
|
||||
},
|
||||
"delete": {
|
||||
actions: []string{"delete"},
|
||||
prevNodeValue: runtime.EncodeOrDie(podBar),
|
||||
prevNodeValue: runtime.DefaultScheme.EncodeOrDie(podBar),
|
||||
expectEmit: true,
|
||||
expectType: watch.Deleted,
|
||||
expectObject: podBar,
|
||||
},
|
||||
"delete but filter blocks": {
|
||||
actions: []string{"delete"},
|
||||
nodeValue: runtime.EncodeOrDie(podFoo),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podFoo),
|
||||
expectEmit: false,
|
||||
},
|
||||
"modify appears to create 1": {
|
||||
actions: []string{"set", "compareAndSwap"},
|
||||
nodeValue: runtime.EncodeOrDie(podBar),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podBar),
|
||||
expectEmit: true,
|
||||
expectType: watch.Added,
|
||||
expectObject: podBar,
|
||||
},
|
||||
"modify appears to create 2": {
|
||||
actions: []string{"set", "compareAndSwap"},
|
||||
prevNodeValue: runtime.EncodeOrDie(podFoo),
|
||||
nodeValue: runtime.EncodeOrDie(podBar),
|
||||
prevNodeValue: runtime.DefaultScheme.EncodeOrDie(podFoo),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podBar),
|
||||
expectEmit: true,
|
||||
expectType: watch.Added,
|
||||
expectObject: podBar,
|
||||
},
|
||||
"modify appears to delete": {
|
||||
actions: []string{"set", "compareAndSwap"},
|
||||
prevNodeValue: runtime.EncodeOrDie(podBar),
|
||||
nodeValue: runtime.EncodeOrDie(podFoo),
|
||||
prevNodeValue: runtime.DefaultScheme.EncodeOrDie(podBar),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podFoo),
|
||||
expectEmit: true,
|
||||
expectType: watch.Deleted,
|
||||
expectObject: podBar, // Should return last state that passed the filter!
|
||||
},
|
||||
"modify modifies": {
|
||||
actions: []string{"set", "compareAndSwap"},
|
||||
prevNodeValue: runtime.EncodeOrDie(podBar),
|
||||
nodeValue: runtime.EncodeOrDie(podBaz),
|
||||
prevNodeValue: runtime.DefaultScheme.EncodeOrDie(podBar),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podBaz),
|
||||
expectEmit: true,
|
||||
expectType: watch.Modified,
|
||||
expectObject: podBaz,
|
||||
},
|
||||
"modify ignores": {
|
||||
actions: []string{"set", "compareAndSwap"},
|
||||
nodeValue: runtime.EncodeOrDie(podFoo),
|
||||
nodeValue: runtime.DefaultScheme.EncodeOrDie(podFoo),
|
||||
expectEmit: false,
|
||||
},
|
||||
}
|
||||
@@ -259,7 +259,7 @@ func TestWatchEtcdState(t *testing.T) {
|
||||
{
|
||||
Action: "create",
|
||||
Node: &etcd.Node{
|
||||
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
Value: string(runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -273,12 +273,12 @@ func TestWatchEtcdState(t *testing.T) {
|
||||
{
|
||||
Action: "compareAndSwap",
|
||||
Node: &etcd.Node{
|
||||
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
|
||||
Value: string(runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 2,
|
||||
},
|
||||
PrevNode: &etcd.Node{
|
||||
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
Value: string(runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 1,
|
||||
},
|
||||
@@ -295,7 +295,7 @@ func TestWatchEtcdState(t *testing.T) {
|
||||
R: &etcd.Response{
|
||||
Action: "get",
|
||||
Node: &etcd.Node{
|
||||
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
Value: string(runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 1,
|
||||
},
|
||||
@@ -308,12 +308,12 @@ func TestWatchEtcdState(t *testing.T) {
|
||||
{
|
||||
Action: "compareAndSwap",
|
||||
Node: &etcd.Node{
|
||||
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
|
||||
Value: string(runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 2,
|
||||
},
|
||||
PrevNode: &etcd.Node{
|
||||
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
Value: string(runtime.DefaultScheme.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 1,
|
||||
},
|
||||
@@ -370,7 +370,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
|
||||
EtcdResponseWithError{
|
||||
R: &etcd.Response{
|
||||
Node: &etcd.Node{
|
||||
Value: runtime.EncodeOrDie(pod),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(pod),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 1,
|
||||
},
|
||||
@@ -385,7 +385,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
|
||||
EtcdResponseWithError{
|
||||
R: &etcd.Response{
|
||||
Node: &etcd.Node{
|
||||
Value: runtime.EncodeOrDie(pod),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(pod),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 2,
|
||||
},
|
||||
@@ -443,13 +443,13 @@ func TestWatchListFromZeroIndex(t *testing.T) {
|
||||
Dir: true,
|
||||
Nodes: etcd.Nodes{
|
||||
&etcd.Node{
|
||||
Value: runtime.EncodeOrDie(pod),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(pod),
|
||||
CreatedIndex: 1,
|
||||
ModifiedIndex: 1,
|
||||
Nodes: etcd.Nodes{},
|
||||
},
|
||||
&etcd.Node{
|
||||
Value: runtime.EncodeOrDie(pod),
|
||||
Value: runtime.DefaultScheme.EncodeOrDie(pod),
|
||||
CreatedIndex: 2,
|
||||
ModifiedIndex: 2,
|
||||
Nodes: etcd.Nodes{},
|
||||
|
||||
@@ -24,6 +24,11 @@ type FilterFunc func(in Event) (out Event, keep bool)
|
||||
// Putting a filter on a watch, as an unavoidable side-effect due to the way
|
||||
// go channels work, effectively causes the watch's event channel to have its
|
||||
// queue length increased by one.
|
||||
//
|
||||
// WARNING: filter has a fatal flaw, in that it can't properly update the
|
||||
// Type field (Add/Modified/Deleted) to reflect items beginning to pass the
|
||||
// filter when they previously didn't.
|
||||
//
|
||||
func Filter(w Interface, f FilterFunc) Interface {
|
||||
fw := &filteredWatch{
|
||||
incoming: w,
|
||||
|
||||
@@ -23,16 +23,16 @@ import (
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
table := []Event{
|
||||
{Added, "foo"},
|
||||
{Added, "bar"},
|
||||
{Added, "baz"},
|
||||
{Added, "qux"},
|
||||
{Added, "zoo"},
|
||||
{Added, testType("foo")},
|
||||
{Added, testType("bar")},
|
||||
{Added, testType("baz")},
|
||||
{Added, testType("qux")},
|
||||
{Added, testType("zoo")},
|
||||
}
|
||||
|
||||
source := NewFake()
|
||||
filtered := Filter(source, func(e Event) (Event, bool) {
|
||||
return e, e.Object.(string)[0] != 'b'
|
||||
return e, e.Object.(testType)[0] != 'b'
|
||||
})
|
||||
|
||||
go func() {
|
||||
@@ -48,7 +48,7 @@ func TestFilter(t *testing.T) {
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
got = append(got, event.Object.(string))
|
||||
got = append(got, string(event.Object.(testType)))
|
||||
}
|
||||
|
||||
if e, a := []string{"foo", "qux", "zoo"}, got; !reflect.DeepEqual(e, a) {
|
||||
@@ -59,11 +59,11 @@ func TestFilter(t *testing.T) {
|
||||
func TestFilterStop(t *testing.T) {
|
||||
source := NewFake()
|
||||
filtered := Filter(source, func(e Event) (Event, bool) {
|
||||
return e, e.Object.(string)[0] != 'b'
|
||||
return e, e.Object.(testType)[0] != 'b'
|
||||
})
|
||||
|
||||
go func() {
|
||||
source.Add("foo")
|
||||
source.Add(testType("foo"))
|
||||
filtered.Stop()
|
||||
}()
|
||||
|
||||
@@ -73,7 +73,7 @@ func TestFilterStop(t *testing.T) {
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
got = append(got, event.Object.(string))
|
||||
got = append(got, string(event.Object.(testType)))
|
||||
}
|
||||
|
||||
if e, a := []string{"foo"}, got; !reflect.DeepEqual(e, a) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package watch
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
@@ -27,7 +28,7 @@ type Decoder interface {
|
||||
// Decode should return the type of event, the decoded object, or an error.
|
||||
// An error will cause StreamWatcher to call Close(). Decode should block until
|
||||
// it has data or an error occurs.
|
||||
Decode() (action EventType, object interface{}, err error)
|
||||
Decode() (action EventType, object runtime.Object, err error)
|
||||
|
||||
// Close should close the underlying io.Reader, signalling to the source of
|
||||
// the stream that it is no longer being watched. Close() must cause any
|
||||
|
||||
@@ -20,13 +20,15 @@ import (
|
||||
"io"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
type fakeDecoder struct {
|
||||
items chan Event
|
||||
}
|
||||
|
||||
func (f fakeDecoder) Decode() (action EventType, object interface{}, err error) {
|
||||
func (f fakeDecoder) Decode() (action EventType, object runtime.Object, err error) {
|
||||
item, open := <-f.items
|
||||
if !open {
|
||||
return action, nil, io.EOF
|
||||
@@ -40,7 +42,7 @@ func (f fakeDecoder) Close() {
|
||||
|
||||
func TestStreamWatcher(t *testing.T) {
|
||||
table := []Event{
|
||||
{Added, "foo"},
|
||||
{Added, testType("foo")},
|
||||
}
|
||||
|
||||
fd := fakeDecoder{make(chan Event, 5)}
|
||||
|
||||
@@ -18,6 +18,8 @@ package watch
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// Mux distributes event notifications among any number of watchers. Every event
|
||||
@@ -88,7 +90,7 @@ func (m *Mux) closeAll() {
|
||||
}
|
||||
|
||||
// Action distributes the given event among all watchers.
|
||||
func (m *Mux) Action(action EventType, obj interface{}) {
|
||||
func (m *Mux) Action(action EventType, obj runtime.Object) {
|
||||
m.incoming <- Event{action, obj}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,16 +22,19 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type myType struct {
|
||||
ID string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (*myType) IsAnAPIObject() {}
|
||||
|
||||
func TestMux(t *testing.T) {
|
||||
type myType struct {
|
||||
ID string
|
||||
Value string
|
||||
}
|
||||
table := []Event{
|
||||
{Added, myType{"foo", "hello world 1"}},
|
||||
{Added, myType{"bar", "hello world 2"}},
|
||||
{Modified, myType{"foo", "goodbye world 3"}},
|
||||
{Deleted, myType{"bar", "hello world 4"}},
|
||||
{Added, &myType{"foo", "hello world 1"}},
|
||||
{Added, &myType{"bar", "hello world 2"}},
|
||||
{Modified, &myType{"foo", "goodbye world 3"}},
|
||||
{Deleted, &myType{"bar", "hello world 4"}},
|
||||
}
|
||||
|
||||
// The mux we're testing
|
||||
|
||||
@@ -18,6 +18,8 @@ package watch
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// Interface can be implemented by anything that knows how to watch and report changes.
|
||||
@@ -47,7 +49,7 @@ type Event struct {
|
||||
|
||||
// If Type == Deleted, then this is the state of the object
|
||||
// immediately before deletion.
|
||||
Object interface{}
|
||||
Object runtime.Object
|
||||
}
|
||||
|
||||
// FakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
|
||||
@@ -78,21 +80,21 @@ func (f *FakeWatcher) ResultChan() <-chan Event {
|
||||
}
|
||||
|
||||
// Add sends an add event.
|
||||
func (f *FakeWatcher) Add(obj interface{}) {
|
||||
func (f *FakeWatcher) Add(obj runtime.Object) {
|
||||
f.result <- Event{Added, obj}
|
||||
}
|
||||
|
||||
// Modify sends a modify event.
|
||||
func (f *FakeWatcher) Modify(obj interface{}) {
|
||||
func (f *FakeWatcher) Modify(obj runtime.Object) {
|
||||
f.result <- Event{Modified, obj}
|
||||
}
|
||||
|
||||
// Delete sends a delete event.
|
||||
func (f *FakeWatcher) Delete(lastValue interface{}) {
|
||||
func (f *FakeWatcher) Delete(lastValue runtime.Object) {
|
||||
f.result <- Event{Deleted, lastValue}
|
||||
}
|
||||
|
||||
// Action sends an event of the requested type, for table-based testing.
|
||||
func (f *FakeWatcher) Action(action EventType, obj interface{}) {
|
||||
func (f *FakeWatcher) Action(action EventType, obj runtime.Object) {
|
||||
f.result <- Event{action, obj}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,21 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testType string
|
||||
|
||||
func (testType) IsAnAPIObject() {}
|
||||
|
||||
func TestFake(t *testing.T) {
|
||||
f := NewFake()
|
||||
|
||||
table := []struct {
|
||||
t EventType
|
||||
s string
|
||||
s testType
|
||||
}{
|
||||
{Added, "foo"},
|
||||
{Modified, "qux"},
|
||||
{Modified, "bar"},
|
||||
{Deleted, "bar"},
|
||||
{Added, testType("foo")},
|
||||
{Modified, testType("qux")},
|
||||
{Modified, testType("bar")},
|
||||
{Deleted, testType("bar")},
|
||||
}
|
||||
|
||||
// Prove that f implements Interface by phrasing this as a function.
|
||||
@@ -43,7 +47,7 @@ func TestFake(t *testing.T) {
|
||||
if e, a := expect.t, got.Type; e != a {
|
||||
t.Fatalf("Expected %v, got %v", e, a)
|
||||
}
|
||||
if a, ok := got.Object.(string); !ok || a != expect.s {
|
||||
if a, ok := got.Object.(testType); !ok || a != expect.s {
|
||||
t.Fatalf("Expected %v, got %v", expect.s, a)
|
||||
}
|
||||
}
|
||||
@@ -54,10 +58,10 @@ func TestFake(t *testing.T) {
|
||||
}
|
||||
|
||||
sender := func() {
|
||||
f.Add("foo")
|
||||
f.Action(Modified, "qux")
|
||||
f.Modify("bar")
|
||||
f.Delete("bar")
|
||||
f.Add(testType("foo"))
|
||||
f.Action(Modified, testType("qux"))
|
||||
f.Modify(testType("bar"))
|
||||
f.Delete(testType("bar"))
|
||||
f.Stop()
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ func TestPollMinions(t *testing.T) {
|
||||
ml := &api.MinionList{Items: item.minions}
|
||||
handler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: runtime.EncodeOrDie(ml),
|
||||
ResponseBody: runtime.DefaultScheme.EncodeOrDie(ml),
|
||||
T: t,
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
@@ -140,7 +140,7 @@ func TestDefaultErrorFunc(t *testing.T) {
|
||||
testPod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
|
||||
handler := util.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: runtime.EncodeOrDie(testPod),
|
||||
ResponseBody: runtime.DefaultScheme.EncodeOrDie(testPod),
|
||||
T: t,
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
@@ -259,7 +259,7 @@ func TestBind(t *testing.T) {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
expectedBody := runtime.EncodeOrDie(item.binding)
|
||||
expectedBody := runtime.DefaultScheme.EncodeOrDie(item.binding)
|
||||
handler.ValidateRequest(t, "/api/v1beta1/bindings", "POST", &expectedBody)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func TestClient(t *testing.T) {
|
||||
}
|
||||
|
||||
// get a validation error
|
||||
pod := api.Pod{
|
||||
pod := &api.Pod{
|
||||
DesiredState: api.PodState{
|
||||
Manifest: api.ContainerManifest{
|
||||
Version: "v1beta2",
|
||||
|
||||
@@ -33,17 +33,22 @@ func init() {
|
||||
|
||||
type stringCodec struct{}
|
||||
|
||||
func (c stringCodec) Encode(obj interface{}) ([]byte, error) {
|
||||
return []byte(obj.(string)), nil
|
||||
type fakeAPIObject string
|
||||
|
||||
func (*fakeAPIObject) IsAnAPIObject() {}
|
||||
|
||||
func (c stringCodec) Encode(obj runtime.Object) ([]byte, error) {
|
||||
return []byte(*obj.(*fakeAPIObject)), nil
|
||||
}
|
||||
|
||||
func (c stringCodec) Decode(data []byte) (interface{}, error) {
|
||||
return string(data), nil
|
||||
func (c stringCodec) Decode(data []byte) (runtime.Object, error) {
|
||||
o := fakeAPIObject(data)
|
||||
return &o, nil
|
||||
}
|
||||
|
||||
func (c stringCodec) DecodeInto(data []byte, obj interface{}) error {
|
||||
o := obj.(*string)
|
||||
*o = string(data)
|
||||
func (c stringCodec) DecodeInto(data []byte, obj runtime.Object) error {
|
||||
o := obj.(*fakeAPIObject)
|
||||
*o = fakeAPIObject(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -51,7 +56,8 @@ func TestSetObj(t *testing.T) {
|
||||
client := newEtcdClient()
|
||||
helper := tools.EtcdHelper{Client: client, Codec: stringCodec{}}
|
||||
withEtcdKey(func(key string) {
|
||||
if err := helper.SetObj(key, "object"); err != nil {
|
||||
fakeObject := fakeAPIObject("object")
|
||||
if err := helper.SetObj(key, &fakeObject); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
resp, err := client.Get(key, false, false)
|
||||
@@ -72,7 +78,7 @@ func TestExtractObj(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
s := ""
|
||||
s := fakeAPIObject("")
|
||||
if err := helper.ExtractObj(key, &s, false); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -84,9 +90,9 @@ func TestExtractObj(t *testing.T) {
|
||||
|
||||
func TestWatch(t *testing.T) {
|
||||
client := newEtcdClient()
|
||||
helper := tools.EtcdHelper{Client: client, Codec: runtime.Codec, ResourceVersioner: runtime.ResourceVersioner}
|
||||
helper := tools.EtcdHelper{Client: client, Codec: runtime.DefaultCodec, ResourceVersioner: runtime.DefaultResourceVersioner}
|
||||
withEtcdKey(func(key string) {
|
||||
resp, err := client.Set(key, runtime.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
resp, err := client.Set(key, runtime.DefaultScheme.EncodeOrDie(&api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user