From 156000ef6d7b71ef45617a330964cf0acddf67c4 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Wed, 19 Nov 2014 17:39:10 -0500 Subject: [PATCH] Move the internal minion representation to match v1beta3 Moves to 'Spec' and 'Status' internally and removes duplicate fields. Moves Capacity into Spec and drops use of NodeResources --- pkg/api/types.go | 34 +++++++++++++------ pkg/api/v1beta1/conversion.go | 12 +++---- pkg/api/v1beta2/conversion.go | 12 +++---- pkg/api/v1beta3/types.go | 17 ++++------ pkg/api/validation/validation.go | 2 -- pkg/api/validation/validation_test.go | 30 +++++++++++----- pkg/client/client_test.go | 6 ++-- .../controller/minioncontroller.go | 8 +++-- pkg/master/master.go | 2 +- pkg/registry/minion/rest.go | 2 +- pkg/registry/minion/rest_test.go | 18 ++++++---- pkg/registry/registrytest/minion.go | 2 +- pkg/scheduler/predicates.go | 4 +-- pkg/scheduler/predicates_test.go | 4 +-- pkg/scheduler/priorities.go | 4 +-- pkg/scheduler/priorities_test.go | 2 +- 16 files changed, 93 insertions(+), 66 deletions(-) diff --git a/pkg/api/types.go b/pkg/api/types.go index 71590f31451..278f76b808a 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -637,30 +637,42 @@ type EndpointsList struct { Items []Endpoints `json:"items" yaml:"items"` } -// NodeResources represents resources on a Kubernetes system node +// NodeSpec describes the attributes that a node is created with. +type NodeSpec struct { + // Capacity represents the available resources of a node + Capacity ResourceList `json:"capacity,omitempty" yaml:"capacity,omitempty"` +} + +// NodeStatus is information about the current status of a node. +type NodeStatus struct { + // Queried from cloud provider, if available. + HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"` +} + +// NodeResources is an object for conveying resource information about a node. // see https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/resources.md for more details. +// TODO: Use ResourceList instead? type NodeResources struct { - // Capacity represents the available resources. + // Capacity represents the available resources of a node Capacity ResourceList `json:"capacity,omitempty" yaml:"capacity,omitempty"` } type ResourceName string -// TODO Replace this with a more complete "Quantity" struct type ResourceList map[ResourceName]util.IntOrString -// Minion is a worker node in Kubernetenes. -// The name of the minion according to etcd is in ID. +// Minion is a worker node in Kubernetenes +// The name of the minion according to etcd is in ObjectMeta.Name. +// TODO: Rename to Node type Minion struct { TypeMeta `json:",inline" yaml:",inline"` ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"` - // Queried from cloud provider, if available. - HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"` - // Resources available on the node - NodeResources NodeResources `json:"resources,omitempty" yaml:"resources,omitempty"` - // Labels for the node - Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + // Spec defines the behavior of a node. + Spec NodeSpec `json:"spec,omitempty" yaml:"spec,omitempty"` + + // Status describes the current status of a Node + Status NodeStatus `json:"status,omitempty" yaml:"status,omitempty"` } // MinionList is a list of minions. diff --git a/pkg/api/v1beta1/conversion.go b/pkg/api/v1beta1/conversion.go index 3c143367068..35d23d30ada 100644 --- a/pkg/api/v1beta1/conversion.go +++ b/pkg/api/v1beta1/conversion.go @@ -498,12 +498,12 @@ func init() { if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } - if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { + if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } - out.HostIP = in.HostIP - return s.Convert(&in.NodeResources, &out.NodeResources, 0) + out.HostIP = in.Status.HostIP + return s.Convert(&in.Spec.Capacity, &out.NodeResources.Capacity, 0) }, func(in *Minion, out *newer.Minion, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { @@ -512,12 +512,12 @@ func init() { if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } - if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { + if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } - out.HostIP = in.HostIP - return s.Convert(&in.NodeResources, &out.NodeResources, 0) + out.Status.HostIP = in.HostIP + return s.Convert(&in.NodeResources.Capacity, &out.Spec.Capacity, 0) }, func(in *newer.BoundPod, out *BoundPod, s conversion.Scope) error { diff --git a/pkg/api/v1beta2/conversion.go b/pkg/api/v1beta2/conversion.go index a11c35e2fb2..0688a1726bd 100644 --- a/pkg/api/v1beta2/conversion.go +++ b/pkg/api/v1beta2/conversion.go @@ -427,12 +427,12 @@ func init() { if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } - if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { + if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } - out.HostIP = in.HostIP - return s.Convert(&in.NodeResources, &out.NodeResources, 0) + out.HostIP = in.Status.HostIP + return s.Convert(&in.Spec.Capacity, &out.NodeResources.Capacity, 0) }, func(in *Minion, out *newer.Minion, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { @@ -441,12 +441,12 @@ func init() { if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } - if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { + if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } - out.HostIP = in.HostIP - return s.Convert(&in.NodeResources, &out.NodeResources, 0) + out.Status.HostIP = in.HostIP + return s.Convert(&in.NodeResources.Capacity, &out.Spec.Capacity, 0) }, func(in *newer.BoundPod, out *BoundPod, s conversion.Scope) error { diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index 866ce9c97d4..bdd8243851d 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -664,24 +664,22 @@ type EndpointsList struct { // NodeSpec describes the attributes that a node is created with. type NodeSpec struct { + // Capacity represents the available resources of a node + // see https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/resources.md for more details. + Capacity ResourceList `json:"capacity,omitempty" yaml:"capacity,omitempty"` } // NodeStatus is information about the current status of a node. type NodeStatus struct { -} - -// NodeResources represents resources on a Kubernetes system node -// see https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/resources.md for more details. -type NodeResources struct { - // Capacity represents the available resources. - Capacity ResourceList `json:"capacity,omitempty" yaml:"capacity,omitempty"` + // Queried from cloud provider, if available. + HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"` } type ResourceName string type ResourceList map[ResourceName]util.IntOrString -// Node is a worker node in Kubernetenes. +// Node is a worker node in Kubernetes. // The name of the node according to etcd is in ID. type Node struct { TypeMeta `json:",inline" yaml:",inline"` @@ -692,9 +690,6 @@ type Node struct { // Status describes the current status of a Node Status NodeStatus `json:"status,omitempty" yaml:"status,omitempty"` - - // NodeResources describe the resoruces available on the node. - NodeResources NodeResources `json:"resources,omitempty" yaml:"resources,omitempty"` } // NodeList is a list of minions. diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 13358066f5d..e98e83fc2cc 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -544,9 +544,7 @@ func ValidateMinion(minion *api.Minion) errs.ValidationErrorList { // ValidateMinionUpdate tests to make sure a minion update can be applied. Modifies oldMinion. func ValidateMinionUpdate(oldMinion *api.Minion, minion *api.Minion) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} - // TODO: why we need two labels for minion. oldMinion.Labels = minion.Labels - oldMinion.ObjectMeta.Labels = minion.ObjectMeta.Labels if !reflect.DeepEqual(oldMinion, minion) { allErrs = append(allErrs, fmt.Errorf("Update contains more than labels changes")) } diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index 6e92c37dcb5..2608cdf054d 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -1033,13 +1033,19 @@ func TestValidateMinion(t *testing.T) { invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} successCases := []api.Minion{ { - ObjectMeta: api.ObjectMeta{Name: "abc"}, - HostIP: "something", - Labels: validSelector, + ObjectMeta: api.ObjectMeta{ + Name: "abc", + Labels: validSelector, + }, + Status: api.NodeStatus{ + HostIP: "something", + }, }, { ObjectMeta: api.ObjectMeta{Name: "abc"}, - HostIP: "something", + Status: api.NodeStatus{ + HostIP: "something", + }, }, } for _, successCase := range successCases { @@ -1050,13 +1056,19 @@ func TestValidateMinion(t *testing.T) { errorCases := map[string]api.Minion{ "zero-length Name": { - ObjectMeta: api.ObjectMeta{Name: ""}, - HostIP: "something", - Labels: validSelector, + ObjectMeta: api.ObjectMeta{ + Name: "", + Labels: validSelector, + }, + Status: api.NodeStatus{ + HostIP: "something", + }, }, "invalid-labels": { - ObjectMeta: api.ObjectMeta{Name: "abc-123"}, - Labels: invalidSelector, + ObjectMeta: api.ObjectMeta{ + Name: "abc-123", + Labels: invalidSelector, + }, }, } for k, v := range errorCases { diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 8cf2bcc29bf..e4365d4dd39 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -592,8 +592,10 @@ func TestCreateMinion(t *testing.T) { ObjectMeta: api.ObjectMeta{ Name: "minion-1", }, - HostIP: "123.321.456.654", - NodeResources: api.NodeResources{ + Status: api.NodeStatus{ + HostIP: "123.321.456.654", + }, + Spec: api.NodeSpec{ Capacity: api.ResourceList{ resources.CPU: util.NewIntOrStringFromInt(1000), resources.Memory: util.NewIntOrStringFromInt(1024 * 1024), diff --git a/pkg/cloudprovider/controller/minioncontroller.go b/pkg/cloudprovider/controller/minioncontroller.go index f22d1ce3123..fb3c36b62b1 100644 --- a/pkg/cloudprovider/controller/minioncontroller.go +++ b/pkg/cloudprovider/controller/minioncontroller.go @@ -70,8 +70,10 @@ func (s *MinionController) SyncStatic(period time.Duration) error { continue } _, err := s.kubeClient.Minions().Create(&api.Minion{ - ObjectMeta: api.ObjectMeta{Name: minionID}, - NodeResources: *s.staticResources, + ObjectMeta: api.ObjectMeta{Name: minionID}, + Spec: api.NodeSpec{ + Capacity: s.staticResources.Capacity, + }, }) if err == nil { registered.Insert(minionID) @@ -145,7 +147,7 @@ func (s *MinionController) cloudMinions() (*api.MinionList, error) { resources = s.staticResources } if resources != nil { - result.Items[i].NodeResources = *resources + result.Items[i].Spec.Capacity = resources.Capacity } } return result, nil diff --git a/pkg/master/master.go b/pkg/master/master.go index 42e05d9add6..74f5fa5afcd 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -429,7 +429,7 @@ func (m *Master) getServersToValidate(c *Config) map[string]apiserver.Server { glog.Errorf("Failed to list minions: %v", err) } for ix, node := range nodes.Items { - serversToValidate[fmt.Sprintf("node-%d", ix)] = apiserver.Server{Addr: node.HostIP, Port: 10250, Path: "/healthz"} + serversToValidate[fmt.Sprintf("node-%d", ix)] = apiserver.Server{Addr: node.Status.HostIP, Port: 10250, Path: "/healthz"} } return serversToValidate } diff --git a/pkg/registry/minion/rest.go b/pkg/registry/minion/rest.go index 07093e63a38..c3f8076083c 100644 --- a/pkg/registry/minion/rest.go +++ b/pkg/registry/minion/rest.go @@ -135,7 +135,7 @@ func (rs *REST) ResourceLocation(ctx api.Context, id string) (string, error) { if err != nil { return "", err } - host := minion.HostIP + host := minion.Status.HostIP if host == "" { host = minion.Name } diff --git a/pkg/registry/minion/rest_test.go b/pkg/registry/minion/rest_test.go index 4153f7be3db..e74ec3f8c71 100644 --- a/pkg/registry/minion/rest_test.go +++ b/pkg/registry/minion/rest_test.go @@ -130,7 +130,7 @@ func TestMinionStorageInvalidUpdate(t *testing.T) { if !ok { t.Fatalf("Object is not a minion: %#v", obj) } - minion.HostIP = "1.2.3.4" + minion.Status.HostIP = "1.2.3.4" if _, err = storage.Update(ctx, minion); err == nil { t.Error("Unexpected non-error.") } @@ -163,13 +163,19 @@ func TestMinionStorageValidatesCreate(t *testing.T) { invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} failureCases := map[string]api.Minion{ "zero-length Name": { - ObjectMeta: api.ObjectMeta{Name: ""}, - HostIP: "something", - Labels: validSelector, + ObjectMeta: api.ObjectMeta{ + Name: "", + Labels: validSelector, + }, + Status: api.NodeStatus{ + HostIP: "something", + }, }, "invalid-labels": { - ObjectMeta: api.ObjectMeta{Name: "abc-123"}, - Labels: invalidSelector, + ObjectMeta: api.ObjectMeta{ + Name: "abc-123", + Labels: invalidSelector, + }, }, } for _, failureCase := range failureCases { diff --git a/pkg/registry/registrytest/minion.go b/pkg/registry/registrytest/minion.go index 536cc37d31f..889e8f1e818 100644 --- a/pkg/registry/registrytest/minion.go +++ b/pkg/registry/registrytest/minion.go @@ -35,7 +35,7 @@ func MakeMinionList(minions []string, nodeResources api.NodeResources) *api.Mini } for i := range minions { list.Items[i].Name = minions[i] - list.Items[i].NodeResources = nodeResources + list.Items[i].Spec.Capacity = nodeResources.Capacity } return &list } diff --git a/pkg/scheduler/predicates.go b/pkg/scheduler/predicates.go index b3138b19239..782ca86399d 100644 --- a/pkg/scheduler/predicates.go +++ b/pkg/scheduler/predicates.go @@ -122,8 +122,8 @@ func (r *ResourceFit) PodFitsResources(pod api.Pod, existingPods []api.Pod, node } // TODO: convert to general purpose resource matching, when pods ask for resources - totalMilliCPU := int(resources.GetFloatResource(info.NodeResources.Capacity, resources.CPU, 0) * 1000) - totalMemory := resources.GetIntegerResource(info.NodeResources.Capacity, resources.Memory, 0) + totalMilliCPU := int(resources.GetFloatResource(info.Spec.Capacity, resources.CPU, 0) * 1000) + totalMemory := resources.GetIntegerResource(info.Spec.Capacity, resources.Memory, 0) fitsCPU := totalMilliCPU == 0 || (totalMilliCPU-milliCPURequested) >= podRequest.milliCPU fitsMemory := totalMemory == 0 || (totalMemory-memoryRequested) >= podRequest.memory diff --git a/pkg/scheduler/predicates_test.go b/pkg/scheduler/predicates_test.go index b8e54f5b2d4..0b80ef0a000 100644 --- a/pkg/scheduler/predicates_test.go +++ b/pkg/scheduler/predicates_test.go @@ -111,7 +111,7 @@ func TestPodFitsResources(t *testing.T) { }, } for _, test := range tests { - node := api.Minion{NodeResources: makeResources(10, 20)} + node := api.Minion{Spec: api.NodeSpec{Capacity: makeResources(10, 20).Capacity}} fit := ResourceFit{FakeNodeInfo(node)} fits, err := fit.PodFitsResources(test.pod, test.existingPods, "machine") @@ -335,7 +335,7 @@ func TestPodFitsSelector(t *testing.T) { }, } for _, test := range tests { - node := api.Minion{Labels: test.labels} + node := api.Minion{ObjectMeta: api.ObjectMeta{Labels: test.labels}} fit := NodeSelector{FakeNodeInfo(node)} fits, err := fit.PodSelectorMatches(test.pod, []api.Pod{}, "machine") diff --git a/pkg/scheduler/priorities.go b/pkg/scheduler/priorities.go index 8b9ff19b99d..baa65c96b22 100644 --- a/pkg/scheduler/priorities.go +++ b/pkg/scheduler/priorities.go @@ -41,8 +41,8 @@ func calculateOccupancy(node api.Minion, pods []api.Pod) HostPriority { } } - percentageCPU := calculatePercentage(totalCPU, resources.GetIntegerResource(node.NodeResources.Capacity, resources.CPU, 0)) - percentageMemory := calculatePercentage(totalMemory, resources.GetIntegerResource(node.NodeResources.Capacity, resources.Memory, 0)) + percentageCPU := calculatePercentage(totalCPU, resources.GetIntegerResource(node.Spec.Capacity, resources.CPU, 0)) + percentageMemory := calculatePercentage(totalMemory, resources.GetIntegerResource(node.Spec.Capacity, resources.Memory, 0)) glog.V(4).Infof("Least Requested Priority, AbsoluteRequested: (%d, %d) Percentage:(%d\\%m, %d\\%)", totalCPU, totalMemory, percentageCPU, percentageMemory) return HostPriority{ diff --git a/pkg/scheduler/priorities_test.go b/pkg/scheduler/priorities_test.go index e17f46b6491..2cde2ff5d52 100644 --- a/pkg/scheduler/priorities_test.go +++ b/pkg/scheduler/priorities_test.go @@ -28,7 +28,7 @@ import ( func makeMinion(node string, cpu, memory int) api.Minion { return api.Minion{ ObjectMeta: api.ObjectMeta{Name: node}, - NodeResources: api.NodeResources{ + Spec: api.NodeSpec{ Capacity: api.ResourceList{ resources.CPU: util.NewIntOrStringFromInt(cpu), resources.Memory: util.NewIntOrStringFromInt(memory),