From 176f34ea0728183a85b7d4687368f1f45c41b131 Mon Sep 17 00:00:00 2001 From: Minhan Xia Date: Fri, 1 Jun 2018 18:32:07 -0700 Subject: [PATCH] Generate ContainersReady condition --- pkg/kubelet/status/generate.go | 36 ++++++++--- pkg/kubelet/status/generate_test.go | 92 +++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 8 deletions(-) diff --git a/pkg/kubelet/status/generate.go b/pkg/kubelet/status/generate.go index 30ec57b92a4..8d9415d2247 100644 --- a/pkg/kubelet/status/generate.go +++ b/pkg/kubelet/status/generate.go @@ -32,14 +32,13 @@ const ( ReadinessGatesNotReady = "ReadinessGatesNotReady" ) -// GeneratePodReadyCondition returns "Ready" condition of a pod. -// The status of "Ready" condition is "True", if all containers in a pod are ready -// AND all matching conditions specified in the ReadinessGates have status equal to "True". -func GeneratePodReadyCondition(spec *v1.PodSpec, conditions []v1.PodCondition, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { +// GenerateContainersReadyCondition returns the status of "ContainersReady" condition. +// The status of "ContainersReady" condition is true when all containers are ready. +func GenerateContainersReadyCondition(spec *v1.PodSpec, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { // Find if all containers are ready or not. if containerStatuses == nil { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: UnknownContainerStatuses, } @@ -59,7 +58,7 @@ func GeneratePodReadyCondition(spec *v1.PodSpec, conditions []v1.PodCondition, c // If all containers are known and succeeded, just return PodCompleted. if podPhase == v1.PodSucceeded && len(unknownContainers) == 0 { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: PodCompleted, } @@ -76,16 +75,37 @@ func GeneratePodReadyCondition(spec *v1.PodSpec, conditions []v1.PodCondition, c unreadyMessage := strings.Join(unreadyMessages, ", ") if unreadyMessage != "" { return v1.PodCondition{ - Type: v1.PodReady, + Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: ContainersNotReady, Message: unreadyMessage, } } + return v1.PodCondition{ + Type: v1.ContainersReady, + Status: v1.ConditionTrue, + } +} + +// GeneratePodReadyCondition returns "Ready" condition of a pod. +// The status of "Ready" condition is "True", if all containers in a pod are ready +// AND all matching conditions specified in the ReadinessGates have status equal to "True". +func GeneratePodReadyCondition(spec *v1.PodSpec, conditions []v1.PodCondition, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition { + containersReady := GenerateContainersReadyCondition(spec, containerStatuses, podPhase) + // If the status of ContainersReady is not True, return the same status, reason and message as ContainersReady. + if containersReady.Status != v1.ConditionTrue { + return v1.PodCondition{ + Type: v1.PodReady, + Status: containersReady.Status, + Reason: containersReady.Reason, + Message: containersReady.Message, + } + } + // Evaluate corresponding conditions specified in readiness gate // Generate message if any readiness gate is not satisfied. - unreadyMessages = []string{} + unreadyMessages := []string{} for _, rg := range spec.ReadinessGates { _, c := podutil.GetPodConditionFromList(conditions, rg.ConditionType) if c == nil { diff --git a/pkg/kubelet/status/generate_test.go b/pkg/kubelet/status/generate_test.go index 46ea7df97fd..a8a191d1bc0 100644 --- a/pkg/kubelet/status/generate_test.go +++ b/pkg/kubelet/status/generate_test.go @@ -24,6 +24,98 @@ import ( "k8s.io/api/core/v1" ) +func TestGenerateContainersReadyCondition(t *testing.T) { + tests := []struct { + spec *v1.PodSpec + containerStatuses []v1.ContainerStatus + podPhase v1.PodPhase + expectReady v1.PodCondition + }{ + { + spec: nil, + containerStatuses: nil, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, UnknownContainerStatuses, ""), + }, + { + spec: &v1.PodSpec{}, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + }, + containerStatuses: []v1.ContainerStatus{}, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [1234]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + getReadyStatus("5678"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionTrue, "", ""), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unknown status: [5678]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + {Name: "5678"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getReadyStatus("1234"), + getNotReadyStatus("5678"), + }, + podPhase: v1.PodRunning, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, ContainersNotReady, "containers with unready status: [5678]"), + }, + { + spec: &v1.PodSpec{ + Containers: []v1.Container{ + {Name: "1234"}, + }, + }, + containerStatuses: []v1.ContainerStatus{ + getNotReadyStatus("1234"), + }, + podPhase: v1.PodSucceeded, + expectReady: getPodCondition(v1.ContainersReady, v1.ConditionFalse, PodCompleted, ""), + }, + } + + for i, test := range tests { + ready := GenerateContainersReadyCondition(test.spec, test.containerStatuses, test.podPhase) + if !reflect.DeepEqual(ready, test.expectReady) { + t.Errorf("On test case %v, expectReady:\n%+v\ngot\n%+v\n", i, test.expectReady, ready) + } + } +} + func TestGeneratePodReadyCondition(t *testing.T) { tests := []struct { spec *v1.PodSpec