diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 1e20bf6d4e7..6e8fdcf5692 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -126,6 +126,10 @@ kube::log::status "Testing kubectl(minions)" "${kube_cmd[@]}" get minions "${kube_flags[@]}" "${kube_cmd[@]}" get minions 127.0.0.1 "${kube_flags[@]}" +kube::log::status "Testing kubectl(nodes)" +"${kube_cmd[@]}" get nodes "${kube_flags[@]}" +"${kube_cmd[@]}" describe nodes 127.0.0.1 "${kube_flags[@]}" + kube::log::status "TEST PASSED" # Start proxy diff --git a/pkg/api/v1beta1/conversion_test.go b/pkg/api/v1beta1/conversion_test.go index 3e16ba5da44..e2093f5241b 100644 --- a/pkg/api/v1beta1/conversion_test.go +++ b/pkg/api/v1beta1/conversion_test.go @@ -141,7 +141,7 @@ func TestMinionListConversionToNew(t *testing.T) { oldMinion := func(id string) current.Minion { return current.Minion{TypeMeta: current.TypeMeta{ID: id}} } - newMinion := func(id string) newer.Node { + newNode := func(id string) newer.Node { return newer.Node{ObjectMeta: newer.ObjectMeta{Name: id}} } oldMinions := []current.Minion{ @@ -149,8 +149,8 @@ func TestMinionListConversionToNew(t *testing.T) { oldMinion("bar"), } newMinions := []newer.Node{ - newMinion("foo"), - newMinion("bar"), + newNode("foo"), + newNode("bar"), } table := []struct { @@ -188,7 +188,7 @@ func TestMinionListConversionToOld(t *testing.T) { oldMinion := func(id string) current.Minion { return current.Minion{TypeMeta: current.TypeMeta{ID: id}} } - newMinion := func(id string) newer.Node { + newNode := func(id string) newer.Node { return newer.Node{ObjectMeta: newer.ObjectMeta{Name: id}} } oldMinions := []current.Minion{ @@ -196,8 +196,8 @@ func TestMinionListConversionToOld(t *testing.T) { oldMinion("bar"), } newMinions := []newer.Node{ - newMinion("foo"), - newMinion("bar"), + newNode("foo"), + newNode("bar"), } newML := &newer.NodeList{Items: newMinions} diff --git a/pkg/client/client.go b/pkg/client/client.go index ee90d5af0ff..dc6d7f3e3e0 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -32,7 +32,7 @@ type Interface interface { ServicesNamespacer EndpointsNamespacer VersionInterface - MinionsInterface + NodesInterface EventNamespacer } @@ -40,8 +40,8 @@ func (c *Client) ReplicationControllers(namespace string) ReplicationControllerI return newReplicationControllers(c, namespace) } -func (c *Client) Minions() MinionInterface { - return newMinions(c) +func (c *Client) Nodes() NodeInterface { + return newNodes(c, c.preV1Beta3) } func (c *Client) Events(namespace string) EventInterface { @@ -75,6 +75,9 @@ type APIStatus interface { // Client is the implementation of a Kubernetes client. type Client struct { *RESTClient + + // preV1Beta3 is true for v1beta1 and v1beta2 + preV1Beta3 bool } // ServerVersion retrieves and parses the server's version. diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index a643cb708e8..1ad5aad089b 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -28,6 +28,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/resources" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -59,6 +60,7 @@ type testClient struct { Response Response Error bool Created bool + Version string server *httptest.Server handler *util.FakeHandler // For query args, an optional function to validate the contents @@ -77,9 +79,13 @@ func (c *testClient) Setup() *testClient { } c.server = httptest.NewServer(c.handler) if c.Client == nil { + version := c.Version + if len(version) == 0 { + version = testapi.Version() + } c.Client = NewOrDie(&Config{ Host: c.server.URL, - Version: "v1beta1", + Version: version, }) } c.QueryValidator = map[string]func(string, string) bool{} @@ -606,7 +612,7 @@ func TestListMinions(t *testing.T) { Request: testRequest{Method: "GET", Path: "/minions"}, Response: Response{StatusCode: 200, Body: &api.NodeList{ListMeta: api.ListMeta{ResourceVersion: "1"}}}, } - response, err := c.Setup().Minions().List() + response, err := c.Setup().Nodes().List() c.Validate(t, response, err) } @@ -615,7 +621,7 @@ func TestGetMinion(t *testing.T) { Request: testRequest{Method: "GET", Path: "/minions/1"}, Response: Response{StatusCode: 200, Body: &api.Node{ObjectMeta: api.ObjectMeta{Name: "minion-1"}}}, } - response, err := c.Setup().Minions().Get("1") + response, err := c.Setup().Nodes().Get("1") c.Validate(t, response, err) } @@ -641,7 +647,7 @@ func TestCreateMinion(t *testing.T) { Body: requestMinion, }, } - receivedMinion, err := c.Setup().Minions().Create(requestMinion) + receivedMinion, err := c.Setup().Nodes().Create(requestMinion) c.Validate(t, receivedMinion, err) } @@ -650,6 +656,17 @@ func TestDeleteMinion(t *testing.T) { Request: testRequest{Method: "DELETE", Path: "/minions/foo"}, Response: Response{StatusCode: 200}, } - err := c.Setup().Minions().Delete("foo") + err := c.Setup().Nodes().Delete("foo") + c.Validate(t, nil, err) +} + +func TestNewMinionPath(t *testing.T) { + c := &testClient{ + Request: testRequest{Method: "DELETE", Path: "/nodes/foo"}, + Response: Response{StatusCode: 200}, + } + cl := c.Setup() + cl.preV1Beta3 = false + err := cl.Nodes().Delete("foo") c.Validate(t, nil, err) } diff --git a/pkg/client/fake.go b/pkg/client/fake.go index a97d756c445..e0ca630e796 100644 --- a/pkg/client/fake.go +++ b/pkg/client/fake.go @@ -49,8 +49,8 @@ func (c *Fake) ReplicationControllers(namespace string) ReplicationControllerInt return &FakeReplicationControllers{Fake: c, Namespace: namespace} } -func (c *Fake) Minions() MinionInterface { - return &FakeMinions{Fake: c} +func (c *Fake) Nodes() NodeInterface { + return &FakeNodes{Fake: c} } func (c *Fake) Events(namespace string) EventInterface { diff --git a/pkg/client/fake_minions.go b/pkg/client/fake_minions.go index e35cd922897..aa1d2c04926 100644 --- a/pkg/client/fake_minions.go +++ b/pkg/client/fake_minions.go @@ -18,30 +18,36 @@ package client import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" ) -// FakeMinions implements MinionInterface. Meant to be embedded into a struct to get a default +// FakeNodes implements MinionInterface. Meant to be embedded into a struct to get a default // implementation. This makes faking out just the method you want to test easier. -type FakeMinions struct { +type FakeNodes struct { Fake *Fake } -func (c *FakeMinions) Get(name string) (*api.Node, error) { +func (c *FakeNodes) Get(name string) (*api.Node, error) { c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "get-minion", Value: name}) - return &api.Node{}, nil + for i := range c.Fake.MinionsList.Items { + if c.Fake.MinionsList.Items[i].Name == name { + return &c.Fake.MinionsList.Items[i], nil + } + } + return nil, errors.NewNotFound("Minions", name) } -func (c *FakeMinions) List() (*api.NodeList, error) { +func (c *FakeNodes) List() (*api.NodeList, error) { c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "list-minions", Value: nil}) return &c.Fake.MinionsList, nil } -func (c *FakeMinions) Create(minion *api.Node) (*api.Node, error) { +func (c *FakeNodes) Create(minion *api.Node) (*api.Node, error) { c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "create-minion", Value: minion}) return &api.Node{}, nil } -func (c *FakeMinions) Delete(id string) error { +func (c *FakeNodes) Delete(id string) error { c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "delete-minion", Value: id}) return nil } diff --git a/pkg/client/helper.go b/pkg/client/helper.go index 2c64e2a5165..0f7b2e34a90 100644 --- a/pkg/client/helper.go +++ b/pkg/client/helper.go @@ -87,7 +87,9 @@ func New(c *Config) (*Client, error) { if err != nil { return nil, err } - return &Client{client}, nil + version := defaultVersionFor(&config) + isPreV1Beta3 := (version == "v1beta1" || version == "v1beta2") + return &Client{client, isPreV1Beta3}, nil } // NewOrDie creates a Kubernetes client and panics if the provided API version is not recognized. diff --git a/pkg/client/minions.go b/pkg/client/minions.go index 88120899248..540adc1ad90 100644 --- a/pkg/client/minions.go +++ b/pkg/client/minions.go @@ -18,49 +18,58 @@ package client import "github.com/GoogleCloudPlatform/kubernetes/pkg/api" -type MinionsInterface interface { - Minions() MinionInterface +type NodesInterface interface { + Nodes() NodeInterface } -type MinionInterface interface { +type NodeInterface interface { Get(id string) (result *api.Node, err error) Create(minion *api.Node) (*api.Node, error) List() (*api.NodeList, error) Delete(id string) error } -// minions implements Minions interface -type minions struct { - r *Client +// nodes implements NodesInterface +type nodes struct { + r *Client + preV1Beta3 bool } -// newMinions returns a minions -func newMinions(c *Client) *minions { - return &minions{c} +// newNodes returns a nodes object. Uses "minions" as the +// URL resource name for v1beta1 and v1beta2. +func newNodes(c *Client, isPreV1Beta3 bool) *nodes { + return &nodes{c, isPreV1Beta3} +} + +func (c *nodes) resourceName() string { + if c.preV1Beta3 { + return "minions" + } + return "nodes" } // Create creates a new minion. -func (c *minions) Create(minion *api.Node) (*api.Node, error) { +func (c *nodes) Create(minion *api.Node) (*api.Node, error) { result := &api.Node{} - err := c.r.Post().Path("minions").Body(minion).Do().Into(result) + err := c.r.Post().Path(c.resourceName()).Body(minion).Do().Into(result) return result, err } -// List lists all the minions in the cluster. -func (c *minions) List() (*api.NodeList, error) { +// List lists all the nodes in the cluster. +func (c *nodes) List() (*api.NodeList, error) { result := &api.NodeList{} - err := c.r.Get().Path("minions").Do().Into(result) + err := c.r.Get().Path(c.resourceName()).Do().Into(result) return result, err } // Get gets an existing minion -func (c *minions) Get(id string) (*api.Node, error) { +func (c *nodes) Get(id string) (*api.Node, error) { result := &api.Node{} - err := c.r.Get().Path("minions").Path(id).Do().Into(result) + err := c.r.Get().Path(c.resourceName()).Path(id).Do().Into(result) return result, err } // Delete deletes an existing minion. -func (c *minions) Delete(id string) error { - return c.r.Delete().Path("minions").Path(id).Do().Error() +func (c *nodes) Delete(id string) error { + return c.r.Delete().Path(c.resourceName()).Path(id).Do().Error() } diff --git a/pkg/cloudprovider/controller/minioncontroller.go b/pkg/cloudprovider/controller/minioncontroller.go index 8d2c4d7d695..8bb4f879587 100644 --- a/pkg/cloudprovider/controller/minioncontroller.go +++ b/pkg/cloudprovider/controller/minioncontroller.go @@ -73,7 +73,7 @@ func (s *MinionController) SyncStatic(period time.Duration) error { if registered.Has(minionID) { continue } - _, err := s.kubeClient.Minions().Create(&api.Node{ + _, err := s.kubeClient.Nodes().Create(&api.Node{ ObjectMeta: api.ObjectMeta{Name: minionID}, Spec: api.NodeSpec{ Capacity: s.staticResources.Capacity, @@ -97,7 +97,7 @@ func (s *MinionController) SyncCloud() error { if err != nil { return err } - minions, err := s.kubeClient.Minions().List() + minions, err := s.kubeClient.Nodes().List() if err != nil { return err } @@ -110,7 +110,7 @@ func (s *MinionController) SyncCloud() error { for _, minion := range matches.Items { if _, ok := minionMap[minion.Name]; !ok { glog.Infof("Create minion in registry: %s", minion.Name) - _, err = s.kubeClient.Minions().Create(&minion) + _, err = s.kubeClient.Nodes().Create(&minion) if err != nil { glog.Errorf("Create minion error: %s", minion.Name) } @@ -120,7 +120,7 @@ func (s *MinionController) SyncCloud() error { for minionID := range minionMap { glog.Infof("Delete minion from registry: %s", minionID) - err = s.kubeClient.Minions().Delete(minionID) + err = s.kubeClient.Nodes().Delete(minionID) if err != nil { glog.Errorf("Delete minion error: %s", minionID) } diff --git a/pkg/cloudprovider/controller/minioncontroller_test.go b/pkg/cloudprovider/controller/minioncontroller_test.go index bb40b7898d0..66ed3cd5bd1 100644 --- a/pkg/cloudprovider/controller/minioncontroller_test.go +++ b/pkg/cloudprovider/controller/minioncontroller_test.go @@ -26,13 +26,13 @@ import ( fake_cloud "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake" ) -func newMinion(name string) *api.Node { +func newNode(name string) *api.Node { return &api.Node{ObjectMeta: api.ObjectMeta{Name: name}} } type FakeMinionHandler struct { client.Fake - client.FakeMinions + client.FakeNodes // Input: Hooks determine if request is valid or not CreateHook func(*FakeMinionHandler, *api.Node) bool @@ -44,7 +44,7 @@ type FakeMinionHandler struct { RequestCount int } -func (c *FakeMinionHandler) Minions() client.MinionInterface { +func (c *FakeMinionHandler) Nodes() client.NodeInterface { return c } @@ -75,7 +75,7 @@ func (m *FakeMinionHandler) List() (*api.NodeList, error) { } func (m *FakeMinionHandler) Delete(id string) error { - m.DeletedMinions = append(m.DeletedMinions, newMinion(id)) + m.DeletedMinions = append(m.DeletedMinions, newNode(id)) m.RequestCount++ return nil } @@ -129,7 +129,7 @@ func TestSyncStaticCreateMinionWithError(t *testing.T) { func TestSyncCloudCreateMinion(t *testing.T) { fakeMinionHandler := &FakeMinionHandler{ - Existing: []*api.Node{newMinion("minion0")}, + Existing: []*api.Node{newNode("minion0")}, } instances := []string{"minion0", "minion1"} fakeCloud := fake_cloud.FakeCloud{ @@ -153,7 +153,7 @@ func TestSyncCloudCreateMinion(t *testing.T) { func TestSyncCloudDeleteMinion(t *testing.T) { fakeMinionHandler := &FakeMinionHandler{ - Existing: []*api.Node{newMinion("minion0"), newMinion("minion1")}, + Existing: []*api.Node{newNode("minion0"), newNode("minion1")}, } instances := []string{"minion0"} fakeCloud := fake_cloud.FakeCloud{ @@ -177,7 +177,7 @@ func TestSyncCloudDeleteMinion(t *testing.T) { func TestSyncCloudRegexp(t *testing.T) { fakeMinionHandler := &FakeMinionHandler{ - Existing: []*api.Node{newMinion("minion0")}, + Existing: []*api.Node{newNode("minion0")}, } instances := []string{"minion0", "minion1", "node0"} fakeCloud := fake_cloud.FakeCloud{ diff --git a/pkg/kubectl/describe.go b/pkg/kubectl/describe.go index 8543d44f3d4..66d363ca226 100644 --- a/pkg/kubectl/describe.go +++ b/pkg/kubectl/describe.go @@ -176,7 +176,7 @@ type MinionDescriber struct { } func (d *MinionDescriber) Describe(namespace, name string) (string, error) { - mc := d.Minions() + mc := d.Nodes() minion, err := mc.Get(name) if err != nil { return "", err diff --git a/pkg/master/master.go b/pkg/master/master.go index f184e12d5d4..fce494f1821 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -316,7 +316,7 @@ func (m *Master) init(c *Config) { PodCache: podCache, PodInfoGetter: c.KubeletClient, Registry: m.podRegistry, - Minions: m.client.Minions(), + Nodes: m.client.Nodes(), }), "replicationControllers": controller.NewREST(m.controllerRegistry, m.podRegistry), "services": service.NewREST(m.serviceRegistry, c.Cloud, m.minionRegistry, m.portalNet), diff --git a/pkg/registry/pod/rest.go b/pkg/registry/pod/rest.go index c3c14b60067..ba03cbe8272 100644 --- a/pkg/registry/pod/rest.go +++ b/pkg/registry/pod/rest.go @@ -60,7 +60,7 @@ type REST struct { podInfoGetter client.PodInfoGetter podPollPeriod time.Duration registry Registry - minions client.MinionInterface + nodes client.NodeInterface ipCache ipCache clock clock } @@ -70,7 +70,7 @@ type RESTConfig struct { PodCache client.PodInfoGetter PodInfoGetter client.PodInfoGetter Registry Registry - Minions client.MinionInterface + Nodes client.NodeInterface } // NewREST returns a new REST. @@ -81,7 +81,7 @@ func NewREST(config *RESTConfig) *REST { podInfoGetter: config.PodInfoGetter, podPollPeriod: time.Second * 10, registry: config.Registry, - minions: config.Minions, + nodes: config.Nodes, ipCache: ipCache{}, clock: realClock{}, } @@ -125,7 +125,7 @@ func (rs *REST) Get(ctx api.Context, id string) (runtime.Object, error) { } if rs.podCache != nil || rs.podInfoGetter != nil { rs.fillPodInfo(pod) - status, err := getPodStatus(pod, rs.minions) + status, err := getPodStatus(pod, rs.nodes) if err != nil { return pod, err } @@ -169,7 +169,7 @@ func (rs *REST) List(ctx api.Context, label, field labels.Selector) (runtime.Obj for i := range pods.Items { pod := &pods.Items[i] rs.fillPodInfo(pod) - status, err := getPodStatus(pod, rs.minions) + status, err := getPodStatus(pod, rs.nodes) if err != nil { return pod, err } diff --git a/pkg/registry/pod/rest_test.go b/pkg/registry/pod/rest_test.go index eee750f601c..ac2faeea627 100644 --- a/pkg/registry/pod/rest_test.go +++ b/pkg/registry/pod/rest_test.go @@ -499,7 +499,7 @@ func TestMakePodStatus(t *testing.T) { }, } for _, test := range tests { - if status, err := getPodStatus(test.pod, fakeClient.Minions()); status != test.status { + if status, err := getPodStatus(test.pod, fakeClient.Nodes()); status != test.status { t.Errorf("In test %s, expected %v, got %v", test.test, test.status, status) if err != nil { t.Errorf("In test %s, unexpected error: %v", test.test, err) diff --git a/pkg/scheduler/predicates.go b/pkg/scheduler/predicates.go index f21cac453fd..f6c7c2ebdb5 100644 --- a/pkg/scheduler/predicates.go +++ b/pkg/scheduler/predicates.go @@ -48,7 +48,7 @@ type ClientNodeInfo struct { } func (nodes ClientNodeInfo) GetNodeInfo(nodeID string) (*api.Node, error) { - return nodes.Minions().Get(nodeID) + return nodes.Nodes().Get(nodeID) } func isVolumeConflict(volume api.Volume, pod *api.Pod) bool {