From 119f654a13f1b8d2a11eb275f54f0329389a94a2 Mon Sep 17 00:00:00 2001 From: markturansky Date: Wed, 5 Nov 2014 10:22:54 -0500 Subject: [PATCH] Refactor PodStatus to PodCondition in internal API for v1beta3 --- pkg/api/latest/latest_test.go | 8 +++-- pkg/api/serialization_test.go | 8 +++-- pkg/api/types.go | 25 +++++++++------ pkg/api/v1beta1/conversion.go | 38 +++++++++++++++++++++++ pkg/api/v1beta2/conversion.go | 39 +++++++++++++++++++++++- pkg/api/v1beta3/types.go | 4 +-- pkg/client/client_test.go | 10 +++--- pkg/controller/replication_controller.go | 3 +- pkg/kubectl/describe.go | 14 +++++---- pkg/registry/etcd/etcd.go | 2 +- pkg/registry/pod/rest.go | 14 ++++----- pkg/registry/pod/rest_test.go | 14 ++++----- plugin/pkg/scheduler/scheduler.go | 6 ++-- 13 files changed, 139 insertions(+), 46 deletions(-) diff --git a/pkg/api/latest/latest_test.go b/pkg/api/latest/latest_test.go index 301f2ff05d8..0587ad2c2ad 100644 --- a/pkg/api/latest/latest_test.go +++ b/pkg/api/latest/latest_test.go @@ -26,8 +26,8 @@ import ( _ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" _ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" - "github.com/fsouza/go-dockerclient" - "github.com/google/gofuzz" + docker "github.com/fsouza/go-dockerclient" + fuzz "github.com/google/gofuzz" ) // apiObjectFuzzer can randomly populate api objects. @@ -71,6 +71,10 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs( j.ResourceVersion = strconv.FormatUint(c.RandUint64()>>8, 10) j.FieldPath = c.RandString() }, + func(j *internal.PodCondition, c fuzz.Continue) { + statuses := []internal.PodCondition{internal.PodPending, internal.PodRunning, internal.PodFailed} + *j = statuses[c.Rand.Intn(len(statuses))] + }, func(intstr *util.IntOrString, c fuzz.Continue) { // util.IntOrString will panic if its kind is set wrong. if c.RandBool() { diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index 16a0e72e1e7..8a94b1f118d 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -31,8 +31,8 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" - "github.com/fsouza/go-dockerclient" - "github.com/google/gofuzz" + docker "github.com/fsouza/go-dockerclient" + fuzz "github.com/google/gofuzz" ) var fuzzIters = flag.Int("fuzz_iters", 40, "How many fuzzing iterations to do.") @@ -86,6 +86,10 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs( j.ResourceVersion = strconv.FormatUint(c.RandUint64()>>8, 10) j.SelfLink = c.RandString() }, + func(j *api.PodCondition, c fuzz.Continue) { + statuses := []api.PodCondition{api.PodPending, api.PodRunning, api.PodFailed} + *j = statuses[c.Rand.Intn(len(statuses))] + }, func(intstr *util.IntOrString, c fuzz.Continue) { // util.IntOrString will panic if its kind is set wrong. if c.RandBool() { diff --git a/pkg/api/types.go b/pkg/api/types.go index 94fcff274f4..23ee8582d18 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -331,17 +331,24 @@ type Lifecycle struct { // The below types are used by kube_client and api_server. -// PodStatus represents a status of a pod. -type PodStatus string +// PodCondition is a label for the condition of a pod at the current time. +type PodCondition string // These are the valid statuses of pods. const ( - // PodWaiting means that we're waiting for the pod to begin running. - PodWaiting PodStatus = "Waiting" - // PodRunning means that the pod is up and running. - PodRunning PodStatus = "Running" - // PodTerminated means that the pod has stopped. - PodTerminated PodStatus = "Terminated" + // PodPending means the pod has been accepted by the system, but one or more of the containers + // has not been started. This includes time before being bound to a node, as well as time spent + // pulling images onto the host. + PodPending PodCondition = "Pending" + // PodRunning means the pod has been bound to a node and all of the containers have been started. + // At least one container is still running or is in the process of being restarted. + PodRunning PodCondition = "Running" + // PodSucceeded means that all containers in the pod have voluntarily terminated + // with a container exit code of 0, and the system is not going to restart any of these containers. + PodSucceeded PodCondition = "Succeeded" + // PodFailed means that all containers in the pod have terminated, and at least one container has + // terminated in a failure (exited with a non-zero exit code or was stopped by the system). + PodFailed PodCondition = "Failed" ) type ContainerStateWaiting struct { @@ -408,7 +415,7 @@ type RestartPolicy struct { // PodState is the state of a pod, used as either input (desired state) or output (current state). type PodState struct { Manifest ContainerManifest `json:"manifest,omitempty" yaml:"manifest,omitempty"` - Status PodStatus `json:"status,omitempty" yaml:"status,omitempty"` + Status PodCondition `json:"status,omitempty" yaml:"status,omitempty"` Host string `json:"host,omitempty" yaml:"host,omitempty"` HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"` PodIP string `json:"podIP,omitempty" yaml:"podIP,omitempty"` diff --git a/pkg/api/v1beta1/conversion.go b/pkg/api/v1beta1/conversion.go index 0b238cc68fb..401091e53fc 100644 --- a/pkg/api/v1beta1/conversion.go +++ b/pkg/api/v1beta1/conversion.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta1 import ( + "errors" "strconv" newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api" @@ -159,6 +160,43 @@ func init() { return nil }, + // Convert all to the new PodCondition constants + func(in *newer.PodCondition, out *PodStatus, s conversion.Scope) error { + switch *in { + case "": + *out = "" + case newer.PodPending: + *out = PodWaiting + case newer.PodRunning: + *out = PodRunning + case newer.PodSucceeded: + *out = PodTerminated + case newer.PodFailed: + *out = PodTerminated + default: + return errors.New("The string provided is not a valid PodCondition constant value") + } + + return nil + }, + + func(in *PodStatus, out *newer.PodCondition, s conversion.Scope) error { + switch *in { + case "": + *out = "" + case PodWaiting: + *out = newer.PodPending + case PodRunning: + *out = newer.PodRunning + case PodTerminated: + // Older API versions did not contain enough info to map to PodFailed + *out = newer.PodFailed + default: + return errors.New("The string provided is not a valid PodCondition constant value") + } + return nil + }, + // Convert all the standard objects func(in *newer.Pod, out *Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { diff --git a/pkg/api/v1beta2/conversion.go b/pkg/api/v1beta2/conversion.go index 3051c968c62..78f2a4b65fc 100644 --- a/pkg/api/v1beta2/conversion.go +++ b/pkg/api/v1beta2/conversion.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta2 import ( + "errors" "strconv" newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api" @@ -89,7 +90,43 @@ func init() { return s.Convert(&in.Annotations, &out.Annotations, 0) }, - // Convert all the standard objects + // Convert all to the new PodCondition constants + func(in *newer.PodCondition, out *PodStatus, s conversion.Scope) error { + switch *in { + case "": + *out = "" + case newer.PodPending: + *out = PodWaiting + case newer.PodRunning: + *out = PodRunning + case newer.PodSucceeded: + *out = PodTerminated + case newer.PodFailed: + *out = PodTerminated + default: + return errors.New("The string provided is not a valid PodCondition constant value") + } + + return nil + }, + + func(in *PodStatus, out *newer.PodCondition, s conversion.Scope) error { + switch *in { + case "": + *out = "" + case PodWaiting: + *out = newer.PodPending + case PodRunning: + *out = newer.PodRunning + case PodTerminated: + // Older API versions did not contain enough info to map to PodFailed + *out = newer.PodFailed + default: + return errors.New("The string provided is not a valid PodCondition constant value") + } + return nil + }, + // Convert all the standard objects func(in *newer.Pod, out *Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index cb5b4ace730..7be1b377dc1 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -374,8 +374,8 @@ const ( // PodRunning means the pod has been bound to a node and all of the containers have been started. // At least one container is still running or is in the process of being restarted. PodRunning PodCondition = "Running" - // PodSucceeded means that all containers in the pod have voluntarily terminated with a container - // exit code of 0. + // PodSucceeded means that all containers in the pod have voluntarily terminated + // with a container exit code of 0, and the system is not going to restart any of these containers. PodSucceeded PodCondition = "Succeeded" // PodFailed means that all containers in the pod have terminated, and at least one container has // terminated in a failure (exited with a non-zero exit code or was stopped by the system). diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index fc06570ed48..4c14aa61ba1 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -165,7 +165,7 @@ func TestListPods(t *testing.T) { Items: []api.Pod{ { CurrentState: api.PodState{ - Status: "Foobar", + Status: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Labels: map[string]string{ @@ -198,7 +198,7 @@ func TestListPodsLabels(t *testing.T) { Items: []api.Pod{ { CurrentState: api.PodState{ - Status: "Foobar", + Status: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Labels: map[string]string{ @@ -226,7 +226,7 @@ func TestGetPod(t *testing.T) { StatusCode: 200, Body: &api.Pod{ CurrentState: api.PodState{ - Status: "Foobar", + Status: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Labels: map[string]string{ @@ -253,7 +253,7 @@ func TestDeletePod(t *testing.T) { func TestCreatePod(t *testing.T) { requestPod := &api.Pod{ CurrentState: api.PodState{ - Status: "Foobar", + Status: api.PodRunning, }, ObjectMeta: api.ObjectMeta{ Labels: map[string]string{ @@ -284,7 +284,7 @@ func TestUpdatePod(t *testing.T) { }, }, CurrentState: api.PodState{ - Status: "Foobar", + Status: api.PodRunning, }, } c := &testClient{ diff --git a/pkg/controller/replication_controller.go b/pkg/controller/replication_controller.go index 13a3187d8b7..211b1d0bfd1 100644 --- a/pkg/controller/replication_controller.go +++ b/pkg/controller/replication_controller.go @@ -134,7 +134,8 @@ func (rm *ReplicationManager) watchControllers(resourceVersion *string) { func (rm *ReplicationManager) filterActivePods(pods []api.Pod) []api.Pod { var result []api.Pod for _, value := range pods { - if api.PodTerminated != value.CurrentState.Status { + if api.PodSucceeded != value.CurrentState.Status && + api.PodFailed != value.CurrentState.Status { result = append(result, value) } } diff --git a/pkg/kubectl/describe.go b/pkg/kubectl/describe.go index 9960a1f4749..8e8ae09a76d 100644 --- a/pkg/kubectl/describe.go +++ b/pkg/kubectl/describe.go @@ -120,7 +120,7 @@ func (d *ReplicationControllerDescriber) Describe(namespace, name string) (strin return "", err } - running, waiting, terminated, err := getPodStatusForReplicationController(pc, controller) + running, waiting, succeeded, failed, err := getPodStatusForReplicationController(pc, controller) if err != nil { return "", err } @@ -131,7 +131,7 @@ func (d *ReplicationControllerDescriber) Describe(namespace, name string) (strin fmt.Fprintf(out, "Selector:\t%s\n", formatLabels(controller.DesiredState.ReplicaSelector)) fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(controller.Labels)) fmt.Fprintf(out, "Replicas:\t%d current / %d desired\n", controller.CurrentState.Replicas, controller.DesiredState.Replicas) - fmt.Fprintf(out, "Pods Status:\t%d Running / %d Waiting / %d Terminated\n", running, waiting, terminated) + fmt.Fprintf(out, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed) return nil }) } @@ -216,7 +216,7 @@ func getReplicationControllersForLabels(c client.ReplicationControllerInterface, return list } -func getPodStatusForReplicationController(c client.PodInterface, controller *api.ReplicationController) (running, waiting, terminated int, err error) { +func getPodStatusForReplicationController(c client.PodInterface, controller *api.ReplicationController) (running, waiting, succeeded, failed int, err error) { rcPods, err := c.List(labels.SelectorFromSet(controller.DesiredState.ReplicaSelector)) if err != nil { return @@ -224,10 +224,12 @@ func getPodStatusForReplicationController(c client.PodInterface, controller *api for _, pod := range rcPods.Items { if pod.CurrentState.Status == api.PodRunning { running++ - } else if pod.CurrentState.Status == api.PodWaiting { + } else if pod.CurrentState.Status == api.PodPending { waiting++ - } else if pod.CurrentState.Status == api.PodTerminated { - terminated++ + } else if pod.CurrentState.Status == api.PodSucceeded { + succeeded++ + } else if pod.CurrentState.Status == api.PodFailed { + failed++ } } return diff --git a/pkg/registry/etcd/etcd.go b/pkg/registry/etcd/etcd.go index 65befb3fc82..359866a6570 100644 --- a/pkg/registry/etcd/etcd.go +++ b/pkg/registry/etcd/etcd.go @@ -183,7 +183,7 @@ func makeContainerKey(machine string) string { // CreatePod creates a pod based on a specification. func (r *Registry) CreatePod(ctx api.Context, pod *api.Pod) error { // Set current status to "Waiting". - pod.CurrentState.Status = api.PodWaiting + pod.CurrentState.Status = api.PodPending pod.CurrentState.Host = "" // DesiredState.Host == "" is a signal to the scheduler that this pod needs scheduling. pod.DesiredState.Status = api.PodRunning diff --git a/pkg/registry/pod/rest.go b/pkg/registry/pod/rest.go index df0dac71026..3f51d10904e 100644 --- a/pkg/registry/pod/rest.go +++ b/pkg/registry/pod/rest.go @@ -267,9 +267,9 @@ func getInstanceIPFromCloud(cloud cloudprovider.Interface, host string) string { return addr.String() } -func getPodStatus(pod *api.Pod, minions client.MinionInterface) (api.PodStatus, error) { +func getPodStatus(pod *api.Pod, minions client.MinionInterface) (api.PodCondition, error) { if pod.CurrentState.Host == "" { - return api.PodWaiting, nil + return api.PodPending, nil } if minions != nil { res, err := minions.List() @@ -285,13 +285,13 @@ func getPodStatus(pod *api.Pod, minions client.MinionInterface) (api.PodStatus, } } if !found { - return api.PodTerminated, nil + return api.PodFailed, nil } } else { glog.Errorf("Unexpected missing minion interface, status may be in-accurate") } if pod.CurrentState.Info == nil { - return api.PodWaiting, nil + return api.PodPending, nil } running := 0 stopped := 0 @@ -313,10 +313,10 @@ func getPodStatus(pod *api.Pod, minions client.MinionInterface) (api.PodStatus, case running > 0 && unknown == 0: return api.PodRunning, nil case running == 0 && stopped > 0 && unknown == 0: - return api.PodTerminated, nil + return api.PodFailed, nil case running == 0 && stopped == 0 && unknown > 0: - return api.PodWaiting, nil + return api.PodPending, nil default: - return api.PodWaiting, nil + return api.PodPending, nil } } diff --git a/pkg/registry/pod/rest_test.go b/pkg/registry/pod/rest_test.go index d173bf61b55..8e38b1c6306 100644 --- a/pkg/registry/pod/rest_test.go +++ b/pkg/registry/pod/rest_test.go @@ -418,10 +418,10 @@ func TestMakePodStatus(t *testing.T) { tests := []struct { pod *api.Pod - status api.PodStatus + status api.PodCondition test string }{ - {&api.Pod{DesiredState: desiredState, CurrentState: currentState}, api.PodWaiting, "waiting"}, + {&api.Pod{DesiredState: desiredState, CurrentState: currentState}, api.PodPending, "waiting"}, { &api.Pod{ DesiredState: desiredState, @@ -429,7 +429,7 @@ func TestMakePodStatus(t *testing.T) { Host: "machine-2", }, }, - api.PodTerminated, + api.PodFailed, "no info, but bad machine", }, { @@ -457,7 +457,7 @@ func TestMakePodStatus(t *testing.T) { Host: "machine-two", }, }, - api.PodTerminated, + api.PodFailed, "all running but minion is missing", }, { @@ -471,7 +471,7 @@ func TestMakePodStatus(t *testing.T) { Host: "machine", }, }, - api.PodTerminated, + api.PodFailed, "all stopped", }, { @@ -485,7 +485,7 @@ func TestMakePodStatus(t *testing.T) { Host: "machine-two", }, }, - api.PodTerminated, + api.PodFailed, "all stopped but minion missing", }, { @@ -512,7 +512,7 @@ func TestMakePodStatus(t *testing.T) { Host: "machine", }, }, - api.PodWaiting, + api.PodPending, "mixed state #2", }, } diff --git a/plugin/pkg/scheduler/scheduler.go b/plugin/pkg/scheduler/scheduler.go index 2828145d981..2341e60deff 100644 --- a/plugin/pkg/scheduler/scheduler.go +++ b/plugin/pkg/scheduler/scheduler.go @@ -68,7 +68,7 @@ func (s *Scheduler) scheduleOne() { pod := s.config.NextPod() dest, err := s.config.Algorithm.Schedule(*pod, s.config.MinionLister) if err != nil { - record.Eventf(pod, "", string(api.PodWaiting), "failedScheduling", "Error scheduling: %v", err) + record.Eventf(pod, "", string(api.PodPending), "failedScheduling", "Error scheduling: %v", err) s.config.Error(pod, err) return } @@ -78,9 +78,9 @@ func (s *Scheduler) scheduleOne() { Host: dest, } if err := s.config.Binder.Bind(b); err != nil { - record.Eventf(pod, "", string(api.PodWaiting), "failedScheduling", "Binding rejected: %v", err) + record.Eventf(pod, "", string(api.PodPending), "failedScheduling", "Binding rejected: %v", err) s.config.Error(pod, err) return } - record.Eventf(pod, "", string(api.PodWaiting), "scheduled", "Successfully assigned %v to %v", pod.Name, dest) + record.Eventf(pod, "", string(api.PodPending), "scheduled", "Successfully assigned %v to %v", pod.Name, dest) }