Commit 156000ef authored by Clayton Coleman's avatar Clayton Coleman

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
parent c688bd40
......@@ -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.
......
......@@ -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 {
......
......@@ -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 {
......
......@@ -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.
......
......@@ -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"))
}
......
......@@ -1033,14 +1033,20 @@ func TestValidateMinion(t *testing.T) {
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
successCases := []api.Minion{
{
ObjectMeta: api.ObjectMeta{Name: "abc"},
HostIP: "something",
ObjectMeta: api.ObjectMeta{
Name: "abc",
Labels: validSelector,
},
Status: api.NodeStatus{
HostIP: "something",
},
},
{
ObjectMeta: api.ObjectMeta{Name: "abc"},
Status: api.NodeStatus{
HostIP: "something",
},
},
}
for _, successCase := range successCases {
if errs := ValidateMinion(&successCase); len(errs) != 0 {
......@@ -1050,14 +1056,20 @@ func TestValidateMinion(t *testing.T) {
errorCases := map[string]api.Minion{
"zero-length Name": {
ObjectMeta: api.ObjectMeta{Name: ""},
HostIP: "something",
ObjectMeta: api.ObjectMeta{
Name: "",
Labels: validSelector,
},
Status: api.NodeStatus{
HostIP: "something",
},
},
"invalid-labels": {
ObjectMeta: api.ObjectMeta{Name: "abc-123"},
ObjectMeta: api.ObjectMeta{
Name: "abc-123",
Labels: invalidSelector,
},
},
}
for k, v := range errorCases {
errs := ValidateMinion(&v)
......
......@@ -592,8 +592,10 @@ func TestCreateMinion(t *testing.T) {
ObjectMeta: api.ObjectMeta{
Name: "minion-1",
},
Status: api.NodeStatus{
HostIP: "123.321.456.654",
NodeResources: api.NodeResources{
},
Spec: api.NodeSpec{
Capacity: api.ResourceList{
resources.CPU: util.NewIntOrStringFromInt(1000),
resources.Memory: util.NewIntOrStringFromInt(1024 * 1024),
......
......@@ -71,7 +71,9 @@ func (s *MinionController) SyncStatic(period time.Duration) error {
}
_, err := s.kubeClient.Minions().Create(&api.Minion{
ObjectMeta: api.ObjectMeta{Name: minionID},
NodeResources: *s.staticResources,
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
......
......@@ -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
}
......
......@@ -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
}
......
......@@ -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,14 +163,20 @@ 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",
ObjectMeta: api.ObjectMeta{
Name: "",
Labels: validSelector,
},
Status: api.NodeStatus{
HostIP: "something",
},
},
"invalid-labels": {
ObjectMeta: api.ObjectMeta{Name: "abc-123"},
ObjectMeta: api.ObjectMeta{
Name: "abc-123",
Labels: invalidSelector,
},
},
}
for _, failureCase := range failureCases {
c, err := storage.Create(ctx, &failureCase)
......
......@@ -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
}
......
......@@ -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
......
......@@ -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")
......
......@@ -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{
......
......@@ -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),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment