Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update PodReady condition when updating container readiness #18240

Merged
merged 1 commit into from
Dec 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 1 addition & 54 deletions pkg/kubelet/kubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -3012,59 +3012,6 @@ func GetPhase(spec *api.PodSpec, info []api.ContainerStatus) api.PodPhase {
}
}

func readyPodCondition(isPodReady bool, reason, message string) []api.PodCondition {
condition := api.PodCondition{
Type: api.PodReady,
}
if isPodReady {
condition.Status = api.ConditionTrue
} else {
condition.Status = api.ConditionFalse
}
condition.Reason = reason
condition.Message = message
return []api.PodCondition{condition}
}

// getPodReadyCondition returns ready condition if all containers in a pod are ready, else it returns an unready condition.
func getPodReadyCondition(spec *api.PodSpec, containerStatuses []api.ContainerStatus, podPhase api.PodPhase) []api.PodCondition {
// Find if all containers are ready or not.
if containerStatuses == nil {
return readyPodCondition(false, "UnknownContainerStatuses", "")
}
unknownContainers := []string{}
unreadyContainers := []string{}
for _, container := range spec.Containers {
if containerStatus, ok := api.GetContainerStatus(containerStatuses, container.Name); ok {
if !containerStatus.Ready {
unreadyContainers = append(unreadyContainers, container.Name)
}
} else {
unknownContainers = append(unknownContainers, container.Name)
}
}

// In case of unexist unknowContainers, If pod has derminated successed and it has unreadyContainers, just return PodCompleted
if podPhase == api.PodSucceeded && len(unknownContainers) == 0 {
return readyPodCondition(false, fmt.Sprint("PodCompleted"), "")
}

unreadyMessages := []string{}
if len(unknownContainers) > 0 {
unreadyMessages = append(unreadyMessages, fmt.Sprintf("containers with unknown status: %s", unknownContainers))
}
if len(unreadyContainers) > 0 {
unreadyMessages = append(unreadyMessages, fmt.Sprintf("containers with unready status: %s", unreadyContainers))
}
unreadyMessage := strings.Join(unreadyMessages, ", ")
if unreadyMessage != "" {
// return unready status.
return readyPodCondition(false, "ContainersNotReady", unreadyMessage)
}
// return ready status.
return readyPodCondition(true, "", "")
}

// By passing the pod directly, this method avoids pod lookup, which requires
// grabbing a lock.
func (kl *Kubelet) generatePodStatus(pod *api.Pod) (api.PodStatus, error) {
Expand Down Expand Up @@ -3110,7 +3057,7 @@ func (kl *Kubelet) generatePodStatus(pod *api.Pod) (api.PodStatus, error) {
podStatus.Phase = GetPhase(spec, podStatus.ContainerStatuses)
kl.probeManager.UpdatePodStatus(pod.UID, podStatus)

podStatus.Conditions = append(podStatus.Conditions, getPodReadyCondition(spec, podStatus.ContainerStatuses, podStatus.Phase)...)
podStatus.Conditions = append(podStatus.Conditions, status.GeneratePodReadyCondition(spec, podStatus.ContainerStatuses, podStatus.Phase))

if !kl.standaloneMode {
hostIP, err := kl.GetHostIP()
Expand Down
113 changes: 0 additions & 113 deletions pkg/kubelet/kubelet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1909,119 +1909,6 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
}
}

func getReadyStatus(cName string) api.ContainerStatus {
return api.ContainerStatus{
Name: cName,
Ready: true,
}
}
func getNotReadyStatus(cName string) api.ContainerStatus {
return api.ContainerStatus{
Name: cName,
Ready: false,
}
}
func getReadyCondition(status api.ConditionStatus, reason, message string) []api.PodCondition {
return []api.PodCondition{{
Type: api.PodReady,
Status: status,
Reason: reason,
Message: message,
}}
}

func TestGetPodReadyCondition(t *testing.T) {
tests := []struct {
spec *api.PodSpec
containerStatuses []api.ContainerStatus
podPhase api.PodPhase
expected []api.PodCondition
}{
{
spec: nil,
containerStatuses: nil,
podPhase: api.PodRunning,
expected: getReadyCondition(api.ConditionFalse, "UnknownContainerStatuses", ""),
},
{
spec: &api.PodSpec{},
containerStatuses: []api.ContainerStatus{},
podPhase: api.PodRunning,
expected: getReadyCondition(api.ConditionTrue, "", ""),
},
{
spec: &api.PodSpec{
Containers: []api.Container{
{Name: "1234"},
},
},
containerStatuses: []api.ContainerStatus{},
podPhase: api.PodRunning,
expected: getReadyCondition(api.ConditionFalse, "ContainersNotReady", "containers with unknown status: [1234]"),
},
{
spec: &api.PodSpec{
Containers: []api.Container{
{Name: "1234"},
{Name: "5678"},
},
},
containerStatuses: []api.ContainerStatus{
getReadyStatus("1234"),
getReadyStatus("5678"),
},
podPhase: api.PodRunning,
expected: getReadyCondition(api.ConditionTrue, "", ""),
},
{
spec: &api.PodSpec{
Containers: []api.Container{
{Name: "1234"},
{Name: "5678"},
},
},
containerStatuses: []api.ContainerStatus{
getReadyStatus("1234"),
},
podPhase: api.PodRunning,
expected: getReadyCondition(api.ConditionFalse, "ContainersNotReady", "containers with unknown status: [5678]"),
},
{
spec: &api.PodSpec{
Containers: []api.Container{
{Name: "1234"},
{Name: "5678"},
},
},
containerStatuses: []api.ContainerStatus{
getReadyStatus("1234"),
getNotReadyStatus("5678"),
},
podPhase: api.PodRunning,
expected: getReadyCondition(api.ConditionFalse, "ContainersNotReady", "containers with unready status: [5678]"),
},
{
spec: &api.PodSpec{
Containers: []api.Container{
{Name: "1234"},
},
},
containerStatuses: []api.ContainerStatus{
getNotReadyStatus("1234"),
},
podPhase: api.PodSucceeded,
expected: getReadyCondition(api.ConditionFalse, "PodCompleted", ""),
},
}

for i, test := range tests {
condition := getPodReadyCondition(test.spec, test.containerStatuses, test.podPhase)
if !reflect.DeepEqual(condition, test.expected) {
t.Errorf("On test case %v, expected:\n%+v\ngot\n%+v\n", i, test.expected, condition)
}
}
}

func TestExecInContainerNoSuchPod(t *testing.T) {
testKubelet := newTestKubelet(t)
kubelet := testKubelet.kubelet
Expand Down
79 changes: 79 additions & 0 deletions pkg/kubelet/status/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package status

import (
"fmt"
"strings"

"k8s.io/kubernetes/pkg/api"
)

// GeneratePodReadyCondition returns ready condition if all containers in a pod are ready, else it
// returns an unready condition.
func GeneratePodReadyCondition(spec *api.PodSpec, containerStatuses []api.ContainerStatus, podPhase api.PodPhase) api.PodCondition {
// Find if all containers are ready or not.
if containerStatuses == nil {
return api.PodCondition{
Type: api.PodReady,
Status: api.ConditionFalse,
Reason: "UnknownContainerStatuses",
}
}
unknownContainers := []string{}
unreadyContainers := []string{}
for _, container := range spec.Containers {
if containerStatus, ok := api.GetContainerStatus(containerStatuses, container.Name); ok {
if !containerStatus.Ready {
unreadyContainers = append(unreadyContainers, container.Name)
}
} else {
unknownContainers = append(unknownContainers, container.Name)
}
}

// If all containers are known and succeeded, just return PodCompleted.
if podPhase == api.PodSucceeded && len(unknownContainers) == 0 {
return api.PodCondition{
Type: api.PodReady,
Status: api.ConditionFalse,
Reason: "PodCompleted",
}
}

unreadyMessages := []string{}
if len(unknownContainers) > 0 {
unreadyMessages = append(unreadyMessages, fmt.Sprintf("containers with unknown status: %s", unknownContainers))
}
if len(unreadyContainers) > 0 {
unreadyMessages = append(unreadyMessages, fmt.Sprintf("containers with unready status: %s", unreadyContainers))
}
unreadyMessage := strings.Join(unreadyMessages, ", ")
if unreadyMessage != "" {
return api.PodCondition{
Type: api.PodReady,
Status: api.ConditionFalse,
Reason: "ContainersNotReady",
Message: unreadyMessage,
}
}

return api.PodCondition{
Type: api.PodReady,
Status: api.ConditionTrue,
}
}