Changed PodInfo to be a list

This change is to make API consistent with our convention.

Fixes #3622
This commit is contained in:
Piotr Szczesniak
2015-03-25 12:09:35 +01:00
parent 8183a4805e
commit 31901ed9d0
14 changed files with 392 additions and 185 deletions

View File

@@ -558,6 +558,7 @@ func inspectContainer(client DockerInterface, dockerID, containerName, tPath str
glog.V(3).Infof("Container inspect result: %+v", *inspectResult)
result.status = api.ContainerStatus{
Name: containerName,
Image: inspectResult.Config.Image,
ImageID: DockerPrefix + inspectResult.Image,
ContainerID: DockerPrefix + dockerID,
@@ -618,7 +619,7 @@ func inspectContainer(client DockerInterface, dockerID, containerName, tPath str
// infrastructure container
func GetDockerPodStatus(client DockerInterface, manifest api.PodSpec, podFullName string, uid types.UID) (*api.PodStatus, error) {
var podStatus api.PodStatus
podStatus.Info = api.PodInfo{}
statuses := make(map[string]api.ContainerStatus)
expectedContainers := make(map[string]api.Container)
for _, container := range manifest.Containers {
@@ -655,9 +656,9 @@ func GetDockerPodStatus(client DockerInterface, manifest api.PodSpec, podFullNam
terminationMessagePath = c.TerminationMessagePath
}
// We assume docker return us a list of containers in time order
if containerStatus, found := podStatus.Info[dockerContainerName]; found {
if containerStatus, found := statuses[dockerContainerName]; found {
containerStatus.RestartCount += 1
podStatus.Info[dockerContainerName] = containerStatus
statuses[dockerContainerName] = containerStatus
continue
}
@@ -670,20 +671,20 @@ func GetDockerPodStatus(client DockerInterface, manifest api.PodSpec, podFullNam
// Found network container
podStatus.PodIP = result.ip
} else {
podStatus.Info[dockerContainerName] = result.status
statuses[dockerContainerName] = result.status
}
}
if len(podStatus.Info) == 0 && podStatus.PodIP == "" {
if len(statuses) == 0 && podStatus.PodIP == "" {
return nil, ErrNoContainersInPod
}
// Not all containers expected are created, check if there are
// image related issues
if len(podStatus.Info) < len(manifest.Containers) {
if len(statuses) < len(manifest.Containers) {
var containerStatus api.ContainerStatus
for _, container := range manifest.Containers {
if _, found := podStatus.Info[container.Name]; found {
if _, found := statuses[container.Name]; found {
continue
}
@@ -705,10 +706,15 @@ func GetDockerPodStatus(client DockerInterface, manifest api.PodSpec, podFullNam
}
}
podStatus.Info[container.Name] = containerStatus
statuses[container.Name] = containerStatus
}
}
podStatus.ContainerStatuses = make([]api.ContainerStatus, 0)
for _, status := range statuses {
podStatus.ContainerStatuses = append(podStatus.ContainerStatuses, status)
}
return &podStatus, nil
}

View File

@@ -1825,15 +1825,14 @@ func (kl *Kubelet) validatePodPhase(podStatus *api.PodStatus) error {
}
func (kl *Kubelet) validateContainerStatus(podStatus *api.PodStatus, containerName string) (dockerID string, err error) {
for cName, cStatus := range podStatus.Info {
if containerName == cName {
if cStatus.State.Waiting != nil {
return "", fmt.Errorf("container %q is in waiting state.", containerName)
}
return strings.Replace(podStatus.Info[containerName].ContainerID, dockertools.DockerPrefix, "", 1), nil
}
cStatus, found := api.GetContainerStatus(podStatus.ContainerStatuses, containerName)
if !found {
return "", fmt.Errorf("container %q not found in pod", containerName)
}
return "", fmt.Errorf("container %q not found in pod", containerName)
if cStatus.State.Waiting != nil {
return "", fmt.Errorf("container %q is in waiting state.", containerName)
}
return strings.Replace(cStatus.ContainerID, dockertools.DockerPrefix, "", 1), nil
}
// GetKubeletContainerLogs returns logs from the container
@@ -1963,7 +1962,7 @@ func (kl *Kubelet) tryUpdateNodeStatus() error {
}
// getPhase returns the phase of a pod given its container info.
func getPhase(spec *api.PodSpec, info api.PodInfo) api.PodPhase {
func getPhase(spec *api.PodSpec, info []api.ContainerStatus) api.PodPhase {
running := 0
waiting := 0
stopped := 0
@@ -1971,7 +1970,7 @@ func getPhase(spec *api.PodSpec, info api.PodInfo) api.PodPhase {
succeeded := 0
unknown := 0
for _, container := range spec.Containers {
if containerStatus, ok := info[container.Name]; ok {
if containerStatus, ok := api.GetContainerStatus(info, container.Name); ok {
if containerStatus.State.Running != nil {
running++
} else if containerStatus.State.Termination != nil {
@@ -2025,7 +2024,7 @@ func getPhase(spec *api.PodSpec, info api.PodInfo) api.PodPhase {
}
// getPodReadyCondition returns ready condition if all containers in a pod are ready, else it returns an unready condition.
func getPodReadyCondition(spec *api.PodSpec, info api.PodInfo) []api.PodCondition {
func getPodReadyCondition(spec *api.PodSpec, statuses []api.ContainerStatus) []api.PodCondition {
ready := []api.PodCondition{{
Type: api.PodReady,
Status: api.ConditionTrue,
@@ -2034,11 +2033,11 @@ func getPodReadyCondition(spec *api.PodSpec, info api.PodInfo) []api.PodConditio
Type: api.PodReady,
Status: api.ConditionFalse,
}}
if info == nil {
if statuses == nil {
return unready
}
for _, container := range spec.Containers {
if containerStatus, ok := info[container.Name]; ok {
if containerStatus, ok := api.GetContainerStatus(statuses, container.Name); ok {
if !containerStatus.Ready {
return unready
}
@@ -2093,13 +2092,16 @@ func (kl *Kubelet) generatePodStatusByPod(pod *api.Pod) (api.PodStatus, error) {
}
// Assume info is ready to process
podStatus.Phase = getPhase(spec, podStatus.Info)
podStatus.Phase = getPhase(spec, podStatus.ContainerStatuses)
for _, c := range spec.Containers {
containerStatus := podStatus.Info[c.Name]
containerStatus.Ready = kl.readiness.IsReady(containerStatus)
podStatus.Info[c.Name] = containerStatus
for i, st := range podStatus.ContainerStatuses {
if st.Name == c.Name {
podStatus.ContainerStatuses[i].Ready = kl.readiness.IsReady(st)
break
}
}
}
podStatus.Conditions = append(podStatus.Conditions, getPodReadyCondition(spec, podStatus.Info)...)
podStatus.Conditions = append(podStatus.Conditions, getPodReadyCondition(spec, podStatus.ContainerStatuses)...)
podStatus.Host = kl.GetHostname()
hostIP, err := kl.GetHostIP()
if err != nil {

View File

@@ -2182,6 +2182,43 @@ func TestMakeEnvironmentVariables(t *testing.T) {
}
}
func runningState(cName string) api.ContainerStatus {
return api.ContainerStatus{
Name: cName,
State: api.ContainerState{
Running: &api.ContainerStateRunning{},
},
}
}
func stoppedState(cName string) api.ContainerStatus {
return api.ContainerStatus{
Name: cName,
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{},
},
}
}
func succeededState(cName string) api.ContainerStatus {
return api.ContainerStatus{
Name: cName,
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{
ExitCode: 0,
},
},
}
}
func failedState(cName string) api.ContainerStatus {
return api.ContainerStatus{
Name: cName,
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{
ExitCode: -1,
},
},
}
}
func TestPodPhaseWithRestartAlways(t *testing.T) {
desiredState := api.PodSpec{
Containers: []api.Container{
@@ -2193,16 +2230,6 @@ func TestPodPhaseWithRestartAlways(t *testing.T) {
currentState := api.PodStatus{
Host: "machine",
}
runningState := api.ContainerStatus{
State: api.ContainerState{
Running: &api.ContainerStateRunning{},
},
}
stoppedState := api.ContainerStatus{
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{},
},
}
tests := []struct {
pod *api.Pod
@@ -2214,9 +2241,9 @@ func TestPodPhaseWithRestartAlways(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
"containerB": runningState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
runningState("containerB"),
},
Host: "machine",
},
@@ -2228,9 +2255,9 @@ func TestPodPhaseWithRestartAlways(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": stoppedState,
"containerB": stoppedState,
ContainerStatuses: []api.ContainerStatus{
stoppedState("containerA"),
stoppedState("containerB"),
},
Host: "machine",
},
@@ -2242,9 +2269,9 @@ func TestPodPhaseWithRestartAlways(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
"containerB": stoppedState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
stoppedState("containerB"),
},
Host: "machine",
},
@@ -2256,8 +2283,8 @@ func TestPodPhaseWithRestartAlways(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
},
Host: "machine",
},
@@ -2267,7 +2294,7 @@ func TestPodPhaseWithRestartAlways(t *testing.T) {
},
}
for _, test := range tests {
if status := getPhase(&test.pod.Spec, test.pod.Status.Info); status != test.status {
if status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses); status != test.status {
t.Errorf("In test %s, expected %v, got %v", test.test, test.status, status)
}
}
@@ -2284,25 +2311,6 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
currentState := api.PodStatus{
Host: "machine",
}
runningState := api.ContainerStatus{
State: api.ContainerState{
Running: &api.ContainerStateRunning{},
},
}
succeededState := api.ContainerStatus{
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{
ExitCode: 0,
},
},
}
failedState := api.ContainerStatus{
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{
ExitCode: -1,
},
},
}
tests := []struct {
pod *api.Pod
@@ -2314,9 +2322,9 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
"containerB": runningState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
runningState("containerB"),
},
Host: "machine",
},
@@ -2328,9 +2336,9 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": succeededState,
"containerB": succeededState,
ContainerStatuses: []api.ContainerStatus{
succeededState("containerA"),
succeededState("containerB"),
},
Host: "machine",
},
@@ -2342,9 +2350,9 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": failedState,
"containerB": failedState,
ContainerStatuses: []api.ContainerStatus{
failedState("containerA"),
failedState("containerB"),
},
Host: "machine",
},
@@ -2356,9 +2364,9 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
"containerB": succeededState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
succeededState("containerB"),
},
Host: "machine",
},
@@ -2370,8 +2378,8 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
},
Host: "machine",
},
@@ -2381,7 +2389,7 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
},
}
for _, test := range tests {
if status := getPhase(&test.pod.Spec, test.pod.Status.Info); status != test.status {
if status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses); status != test.status {
t.Errorf("In test %s, expected %v, got %v", test.test, test.status, status)
}
}
@@ -2398,25 +2406,6 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
currentState := api.PodStatus{
Host: "machine",
}
runningState := api.ContainerStatus{
State: api.ContainerState{
Running: &api.ContainerStateRunning{},
},
}
succeededState := api.ContainerStatus{
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{
ExitCode: 0,
},
},
}
failedState := api.ContainerStatus{
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{
ExitCode: -1,
},
},
}
tests := []struct {
pod *api.Pod
@@ -2428,9 +2417,9 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
"containerB": runningState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
runningState("containerB"),
},
Host: "machine",
},
@@ -2442,9 +2431,9 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": succeededState,
"containerB": succeededState,
ContainerStatuses: []api.ContainerStatus{
succeededState("containerA"),
succeededState("containerB"),
},
Host: "machine",
},
@@ -2456,9 +2445,9 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": failedState,
"containerB": failedState,
ContainerStatuses: []api.ContainerStatus{
failedState("containerA"),
failedState("containerB"),
},
Host: "machine",
},
@@ -2470,9 +2459,9 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
"containerB": succeededState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
succeededState("containerB"),
},
Host: "machine",
},
@@ -2484,8 +2473,8 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
&api.Pod{
Spec: desiredState,
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"containerA": runningState,
ContainerStatuses: []api.ContainerStatus{
runningState("containerA"),
},
Host: "machine",
},
@@ -2495,12 +2484,25 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
},
}
for _, test := range tests {
if status := getPhase(&test.pod.Spec, test.pod.Status.Info); status != test.status {
if status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses); status != test.status {
t.Errorf("In test %s, expected %v, got %v", test.test, test.status, status)
}
}
}
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 TestGetPodReadyCondition(t *testing.T) {
ready := []api.PodCondition{{
Type: api.PodReady,
@@ -2512,7 +2514,7 @@ func TestGetPodReadyCondition(t *testing.T) {
}}
tests := []struct {
spec *api.PodSpec
info api.PodInfo
info []api.ContainerStatus
expected []api.PodCondition
}{
{
@@ -2522,7 +2524,7 @@ func TestGetPodReadyCondition(t *testing.T) {
},
{
spec: &api.PodSpec{},
info: api.PodInfo{},
info: []api.ContainerStatus{},
expected: ready,
},
{
@@ -2531,7 +2533,7 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "1234"},
},
},
info: api.PodInfo{},
info: []api.ContainerStatus{},
expected: unready,
},
{
@@ -2540,8 +2542,8 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "1234"},
},
},
info: api.PodInfo{
"1234": api.ContainerStatus{Ready: true},
info: []api.ContainerStatus{
getReadyStatus("1234"),
},
expected: ready,
},
@@ -2552,9 +2554,9 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "5678"},
},
},
info: api.PodInfo{
"1234": api.ContainerStatus{Ready: true},
"5678": api.ContainerStatus{Ready: true},
info: []api.ContainerStatus{
getReadyStatus("1234"),
getReadyStatus("5678"),
},
expected: ready,
},
@@ -2565,8 +2567,8 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "5678"},
},
},
info: api.PodInfo{
"1234": api.ContainerStatus{Ready: true},
info: []api.ContainerStatus{
getReadyStatus("1234"),
},
expected: unready,
},
@@ -2577,9 +2579,9 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "5678"},
},
},
info: api.PodInfo{
"1234": api.ContainerStatus{Ready: true},
"5678": api.ContainerStatus{Ready: false},
info: []api.ContainerStatus{
getReadyStatus("1234"),
getNotReadyStatus("5678"),
},
expected: unready,
},
@@ -3084,26 +3086,47 @@ func TestValidateContainerStatus(t *testing.T) {
kubelet := testKubelet.kubelet
containerName := "x"
testCases := []struct {
podInfo api.PodInfo
success bool
statuses []api.ContainerStatus
success bool
}{
{
podInfo: api.PodInfo{containerName: api.ContainerStatus{State: api.ContainerState{Running: &api.ContainerStateRunning{}}}},
statuses: []api.ContainerStatus{
{
Name: containerName,
State: api.ContainerState{
Running: &api.ContainerStateRunning{},
},
},
},
success: true,
},
{
podInfo: api.PodInfo{containerName: api.ContainerStatus{State: api.ContainerState{Termination: &api.ContainerStateTerminated{}}}},
statuses: []api.ContainerStatus{
{
Name: containerName,
State: api.ContainerState{
Termination: &api.ContainerStateTerminated{},
},
},
},
success: true,
},
{
podInfo: api.PodInfo{containerName: api.ContainerStatus{State: api.ContainerState{Waiting: &api.ContainerStateWaiting{}}}},
statuses: []api.ContainerStatus{
{
Name: containerName,
State: api.ContainerState{
Waiting: &api.ContainerStateWaiting{},
},
},
},
success: false,
},
}
for i, tc := range testCases {
_, err := kubelet.validateContainerStatus(&api.PodStatus{
Info: tc.podInfo,
ContainerStatuses: tc.statuses,
}, containerName)
if tc.success {
if err != nil {
@@ -3114,7 +3137,7 @@ func TestValidateContainerStatus(t *testing.T) {
}
}
if _, err := kubelet.validateContainerStatus(&api.PodStatus{
Info: testCases[0].podInfo,
ContainerStatuses: testCases[0].statuses,
}, "blah"); err == nil {
t.Errorf("expected error with invalid container name")
}

View File

@@ -166,8 +166,8 @@ func getPodName(name, namespace string) string {
func TestPodStatus(t *testing.T) {
fw := newServerTest()
expected := api.PodStatus{
Info: map[string]api.ContainerStatus{
"goodpod": {},
ContainerStatuses: []api.ContainerStatus{
{Name: "goodpod"},
},
}
fw.fakeKubelet.statusFunc = func(name string) (api.PodStatus, error) {