Refactor PodStatus to PodCondition in internal API for v1beta3

This commit is contained in:
markturansky 2014-11-05 10:22:54 -05:00
parent 3bd10d4fb4
commit 119f654a13
13 changed files with 139 additions and 46 deletions

View File

@ -26,8 +26,8 @@ import (
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" _ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2" _ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
"github.com/google/gofuzz" fuzz "github.com/google/gofuzz"
) )
// apiObjectFuzzer can randomly populate api objects. // 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.ResourceVersion = strconv.FormatUint(c.RandUint64()>>8, 10)
j.FieldPath = c.RandString() 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) { func(intstr *util.IntOrString, c fuzz.Continue) {
// util.IntOrString will panic if its kind is set wrong. // util.IntOrString will panic if its kind is set wrong.
if c.RandBool() { if c.RandBool() {

View File

@ -31,8 +31,8 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
"github.com/google/gofuzz" fuzz "github.com/google/gofuzz"
) )
var fuzzIters = flag.Int("fuzz_iters", 40, "How many fuzzing iterations to do.") 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.ResourceVersion = strconv.FormatUint(c.RandUint64()>>8, 10)
j.SelfLink = c.RandString() 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) { func(intstr *util.IntOrString, c fuzz.Continue) {
// util.IntOrString will panic if its kind is set wrong. // util.IntOrString will panic if its kind is set wrong.
if c.RandBool() { if c.RandBool() {

View File

@ -331,17 +331,24 @@ type Lifecycle struct {
// The below types are used by kube_client and api_server. // The below types are used by kube_client and api_server.
// PodStatus represents a status of a pod. // PodCondition is a label for the condition of a pod at the current time.
type PodStatus string type PodCondition string
// These are the valid statuses of pods. // These are the valid statuses of pods.
const ( const (
// PodWaiting means that we're waiting for the pod to begin running. // PodPending means the pod has been accepted by the system, but one or more of the containers
PodWaiting PodStatus = "Waiting" // has not been started. This includes time before being bound to a node, as well as time spent
// PodRunning means that the pod is up and running. // pulling images onto the host.
PodRunning PodStatus = "Running" PodPending PodCondition = "Pending"
// PodTerminated means that the pod has stopped. // PodRunning means the pod has been bound to a node and all of the containers have been started.
PodTerminated PodStatus = "Terminated" // 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 { 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). // PodState is the state of a pod, used as either input (desired state) or output (current state).
type PodState struct { type PodState struct {
Manifest ContainerManifest `json:"manifest,omitempty" yaml:"manifest,omitempty"` 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"` Host string `json:"host,omitempty" yaml:"host,omitempty"`
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"` HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
PodIP string `json:"podIP,omitempty" yaml:"podIP,omitempty"` PodIP string `json:"podIP,omitempty" yaml:"podIP,omitempty"`

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1beta1 package v1beta1
import ( import (
"errors"
"strconv" "strconv"
newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api" newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@ -159,6 +160,43 @@ func init() {
return nil 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 // Convert all the standard objects
func(in *newer.Pod, out *Pod, s conversion.Scope) error { func(in *newer.Pod, out *Pod, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1beta2 package v1beta2
import ( import (
"errors"
"strconv" "strconv"
newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api" newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@ -89,7 +90,43 @@ func init() {
return s.Convert(&in.Annotations, &out.Annotations, 0) 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 // Convert all the standard objects
func(in *newer.Pod, out *Pod, s conversion.Scope) error { func(in *newer.Pod, out *Pod, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {

View File

@ -374,8 +374,8 @@ const (
// PodRunning means the pod has been bound to a node and all of the containers have been started. // 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. // At least one container is still running or is in the process of being restarted.
PodRunning PodCondition = "Running" PodRunning PodCondition = "Running"
// PodSucceeded means that all containers in the pod have voluntarily terminated with a container // PodSucceeded means that all containers in the pod have voluntarily terminated
// exit code of 0. // with a container exit code of 0, and the system is not going to restart any of these containers.
PodSucceeded PodCondition = "Succeeded" PodSucceeded PodCondition = "Succeeded"
// PodFailed means that all containers in the pod have terminated, and at least one container has // 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). // terminated in a failure (exited with a non-zero exit code or was stopped by the system).

View File

@ -165,7 +165,7 @@ func TestListPods(t *testing.T) {
Items: []api.Pod{ Items: []api.Pod{
{ {
CurrentState: api.PodState{ CurrentState: api.PodState{
Status: "Foobar", Status: api.PodRunning,
}, },
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Labels: map[string]string{ Labels: map[string]string{
@ -198,7 +198,7 @@ func TestListPodsLabels(t *testing.T) {
Items: []api.Pod{ Items: []api.Pod{
{ {
CurrentState: api.PodState{ CurrentState: api.PodState{
Status: "Foobar", Status: api.PodRunning,
}, },
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Labels: map[string]string{ Labels: map[string]string{
@ -226,7 +226,7 @@ func TestGetPod(t *testing.T) {
StatusCode: 200, StatusCode: 200,
Body: &api.Pod{ Body: &api.Pod{
CurrentState: api.PodState{ CurrentState: api.PodState{
Status: "Foobar", Status: api.PodRunning,
}, },
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Labels: map[string]string{ Labels: map[string]string{
@ -253,7 +253,7 @@ func TestDeletePod(t *testing.T) {
func TestCreatePod(t *testing.T) { func TestCreatePod(t *testing.T) {
requestPod := &api.Pod{ requestPod := &api.Pod{
CurrentState: api.PodState{ CurrentState: api.PodState{
Status: "Foobar", Status: api.PodRunning,
}, },
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Labels: map[string]string{ Labels: map[string]string{
@ -284,7 +284,7 @@ func TestUpdatePod(t *testing.T) {
}, },
}, },
CurrentState: api.PodState{ CurrentState: api.PodState{
Status: "Foobar", Status: api.PodRunning,
}, },
} }
c := &testClient{ c := &testClient{

View File

@ -134,7 +134,8 @@ func (rm *ReplicationManager) watchControllers(resourceVersion *string) {
func (rm *ReplicationManager) filterActivePods(pods []api.Pod) []api.Pod { func (rm *ReplicationManager) filterActivePods(pods []api.Pod) []api.Pod {
var result []api.Pod var result []api.Pod
for _, value := range pods { 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) result = append(result, value)
} }
} }

View File

@ -120,7 +120,7 @@ func (d *ReplicationControllerDescriber) Describe(namespace, name string) (strin
return "", err return "", err
} }
running, waiting, terminated, err := getPodStatusForReplicationController(pc, controller) running, waiting, succeeded, failed, err := getPodStatusForReplicationController(pc, controller)
if err != nil { if err != nil {
return "", err 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, "Selector:\t%s\n", formatLabels(controller.DesiredState.ReplicaSelector))
fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(controller.Labels)) 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, "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 return nil
}) })
} }
@ -216,7 +216,7 @@ func getReplicationControllersForLabels(c client.ReplicationControllerInterface,
return list 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)) rcPods, err := c.List(labels.SelectorFromSet(controller.DesiredState.ReplicaSelector))
if err != nil { if err != nil {
return return
@ -224,10 +224,12 @@ func getPodStatusForReplicationController(c client.PodInterface, controller *api
for _, pod := range rcPods.Items { for _, pod := range rcPods.Items {
if pod.CurrentState.Status == api.PodRunning { if pod.CurrentState.Status == api.PodRunning {
running++ running++
} else if pod.CurrentState.Status == api.PodWaiting { } else if pod.CurrentState.Status == api.PodPending {
waiting++ waiting++
} else if pod.CurrentState.Status == api.PodTerminated { } else if pod.CurrentState.Status == api.PodSucceeded {
terminated++ succeeded++
} else if pod.CurrentState.Status == api.PodFailed {
failed++
} }
} }
return return

View File

@ -183,7 +183,7 @@ func makeContainerKey(machine string) string {
// CreatePod creates a pod based on a specification. // CreatePod creates a pod based on a specification.
func (r *Registry) CreatePod(ctx api.Context, pod *api.Pod) error { func (r *Registry) CreatePod(ctx api.Context, pod *api.Pod) error {
// Set current status to "Waiting". // Set current status to "Waiting".
pod.CurrentState.Status = api.PodWaiting pod.CurrentState.Status = api.PodPending
pod.CurrentState.Host = "" pod.CurrentState.Host = ""
// DesiredState.Host == "" is a signal to the scheduler that this pod needs scheduling. // DesiredState.Host == "" is a signal to the scheduler that this pod needs scheduling.
pod.DesiredState.Status = api.PodRunning pod.DesiredState.Status = api.PodRunning

View File

@ -267,9 +267,9 @@ func getInstanceIPFromCloud(cloud cloudprovider.Interface, host string) string {
return addr.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 == "" { if pod.CurrentState.Host == "" {
return api.PodWaiting, nil return api.PodPending, nil
} }
if minions != nil { if minions != nil {
res, err := minions.List() res, err := minions.List()
@ -285,13 +285,13 @@ func getPodStatus(pod *api.Pod, minions client.MinionInterface) (api.PodStatus,
} }
} }
if !found { if !found {
return api.PodTerminated, nil return api.PodFailed, nil
} }
} else { } else {
glog.Errorf("Unexpected missing minion interface, status may be in-accurate") glog.Errorf("Unexpected missing minion interface, status may be in-accurate")
} }
if pod.CurrentState.Info == nil { if pod.CurrentState.Info == nil {
return api.PodWaiting, nil return api.PodPending, nil
} }
running := 0 running := 0
stopped := 0 stopped := 0
@ -313,10 +313,10 @@ func getPodStatus(pod *api.Pod, minions client.MinionInterface) (api.PodStatus,
case running > 0 && unknown == 0: case running > 0 && unknown == 0:
return api.PodRunning, nil return api.PodRunning, nil
case running == 0 && stopped > 0 && unknown == 0: case running == 0 && stopped > 0 && unknown == 0:
return api.PodTerminated, nil return api.PodFailed, nil
case running == 0 && stopped == 0 && unknown > 0: case running == 0 && stopped == 0 && unknown > 0:
return api.PodWaiting, nil return api.PodPending, nil
default: default:
return api.PodWaiting, nil return api.PodPending, nil
} }
} }

View File

@ -418,10 +418,10 @@ func TestMakePodStatus(t *testing.T) {
tests := []struct { tests := []struct {
pod *api.Pod pod *api.Pod
status api.PodStatus status api.PodCondition
test string test string
}{ }{
{&api.Pod{DesiredState: desiredState, CurrentState: currentState}, api.PodWaiting, "waiting"}, {&api.Pod{DesiredState: desiredState, CurrentState: currentState}, api.PodPending, "waiting"},
{ {
&api.Pod{ &api.Pod{
DesiredState: desiredState, DesiredState: desiredState,
@ -429,7 +429,7 @@ func TestMakePodStatus(t *testing.T) {
Host: "machine-2", Host: "machine-2",
}, },
}, },
api.PodTerminated, api.PodFailed,
"no info, but bad machine", "no info, but bad machine",
}, },
{ {
@ -457,7 +457,7 @@ func TestMakePodStatus(t *testing.T) {
Host: "machine-two", Host: "machine-two",
}, },
}, },
api.PodTerminated, api.PodFailed,
"all running but minion is missing", "all running but minion is missing",
}, },
{ {
@ -471,7 +471,7 @@ func TestMakePodStatus(t *testing.T) {
Host: "machine", Host: "machine",
}, },
}, },
api.PodTerminated, api.PodFailed,
"all stopped", "all stopped",
}, },
{ {
@ -485,7 +485,7 @@ func TestMakePodStatus(t *testing.T) {
Host: "machine-two", Host: "machine-two",
}, },
}, },
api.PodTerminated, api.PodFailed,
"all stopped but minion missing", "all stopped but minion missing",
}, },
{ {
@ -512,7 +512,7 @@ func TestMakePodStatus(t *testing.T) {
Host: "machine", Host: "machine",
}, },
}, },
api.PodWaiting, api.PodPending,
"mixed state #2", "mixed state #2",
}, },
} }

View File

@ -68,7 +68,7 @@ func (s *Scheduler) scheduleOne() {
pod := s.config.NextPod() pod := s.config.NextPod()
dest, err := s.config.Algorithm.Schedule(*pod, s.config.MinionLister) dest, err := s.config.Algorithm.Schedule(*pod, s.config.MinionLister)
if err != nil { 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) s.config.Error(pod, err)
return return
} }
@ -78,9 +78,9 @@ func (s *Scheduler) scheduleOne() {
Host: dest, Host: dest,
} }
if err := s.config.Binder.Bind(b); err != nil { 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) s.config.Error(pod, err)
return 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)
} }