Merge pull request #5915 from piosz/api

Changed PodInfo to be a list
pull/6/head
Brian Grant 2015-03-26 12:46:50 -07:00
commit 3b0db99692
14 changed files with 392 additions and 185 deletions

View File

@ -95,12 +95,9 @@ func (fakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.Pod
return r, err
}
r.Status.PodIP = "1.2.3.4"
m := make(api.PodInfo)
for k, v := range r.Status.Info {
v.Ready = true
m[k] = v
for i := range r.Status.ContainerStatuses {
r.Status.ContainerStatuses[i].Ready = true
}
r.Status.Info = m
return r, nil
}

View File

@ -40,3 +40,21 @@ func (self *ResourceList) Memory() *resource.Quantity {
}
return &resource.Quantity{}
}
func GetContainerStatus(statuses []ContainerStatus, name string) (ContainerStatus, bool) {
for i := range statuses {
if statuses[i].Name == name {
return statuses[i], true
}
}
return ContainerStatus{}, false
}
func GetExistingContainerStatus(statuses []ContainerStatus, name string) ContainerStatus {
for i := range statuses {
if statuses[i].Name == name {
return statuses[i]
}
}
return ContainerStatus{}
}

View File

@ -593,6 +593,8 @@ type ContainerState struct {
}
type ContainerStatus struct {
// Each container in a pod must have a unique name.
Name string `name of the container; must be a DNS_LABEL and unique within the pod; cannot be updated"`
// TODO(dchen1107): Should we rename PodStatus to a more generic name or have a separate states
// defined for container?
State ContainerState `json:"state,omitempty"`
@ -646,15 +648,12 @@ type PodCondition struct {
Status ConditionStatus `json:"status"`
}
// PodInfo contains one entry for every container with available info.
type PodInfo map[string]ContainerStatus
// PodContainerInfo is a wrapper for PodInfo that can be encode/decoded
// DEPRECATED: Replaced with PodStatusResult
type PodContainerInfo struct {
TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ContainerInfo PodInfo `json:"containerInfo"`
ContainerInfo []ContainerStatus `json:"containerInfo"`
}
// RestartPolicy describes how the container should be restarted.
@ -726,13 +725,12 @@ type PodStatus struct {
HostIP string `json:"hostIP,omitempty"`
PodIP string `json:"podIP,omitempty"`
// The key of this map is the *name* of the container within the manifest; it has one
// entry per container in the manifest. The value of this map is currently the output
// of `docker inspect`. This output format is *not* final and should not be relied
// upon.
// The list has one entry per container in the manifest. Each entry is
// currently the output of `docker inspect`. This output format is *not*
// final and should not be relied upon.
// TODO: Make real decisions about what our info should look like. Re-enable fuzz test
// when we have done this.
Info PodInfo `json:"info,omitempty"`
ContainerStatuses []ContainerStatus `json:"containerStatuses,omitempty"`
}
// PodStatusResult is a wrapper for PodStatus returned by kubelet that can be encode/decoded

View File

@ -188,7 +188,7 @@ func init() {
if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil {
return err
}
if err := s.Convert(&in.Info, &out.Info, 0); err != nil {
if err := s.Convert(&in.ContainerStatuses, &out.Info, 0); err != nil {
return err
}
out.Message = in.Message
@ -204,7 +204,7 @@ func init() {
if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil {
return err
}
if err := s.Convert(&in.Info, &out.Info, 0); err != nil {
if err := s.Convert(&in.Info, &out.ContainerStatuses, 0); err != nil {
return err
}
@ -229,6 +229,78 @@ func init() {
return nil
},
func(in *[]newer.ContainerStatus, out *PodInfo, s conversion.Scope) error {
*out = make(map[string]ContainerStatus)
for _, st := range *in {
v := ContainerStatus{}
if err := s.Convert(&st, &v, 0); err != nil {
return err
}
(*out)[st.Name] = v
}
return nil
},
func(in *PodInfo, out *[]newer.ContainerStatus, s conversion.Scope) error {
for k, v := range *in {
st := newer.ContainerStatus{}
if err := s.Convert(&v, &st, 0); err != nil {
return err
}
st.Name = k
*out = append(*out, st)
}
return nil
},
func(in *newer.ContainerStatus, out *ContainerStatus, s conversion.Scope) error {
if err := s.Convert(&in.State, &out.State, 0); err != nil {
return err
}
if err := s.Convert(&in.LastTerminationState, &out.LastTerminationState, 0); err != nil {
return err
}
if err := s.Convert(&in.Ready, &out.Ready, 0); err != nil {
return err
}
if err := s.Convert(&in.RestartCount, &out.RestartCount, 0); err != nil {
return err
}
if err := s.Convert(&in.Image, &out.Image, 0); err != nil {
return err
}
if err := s.Convert(&in.ImageID, &out.ImageID, 0); err != nil {
return err
}
if err := s.Convert(&in.ContainerID, &out.ContainerID, 0); err != nil {
return err
}
return nil
},
func(in *ContainerStatus, out *newer.ContainerStatus, s conversion.Scope) error {
if err := s.Convert(&in.State, &out.State, 0); err != nil {
return err
}
if err := s.Convert(&in.LastTerminationState, &out.LastTerminationState, 0); err != nil {
return err
}
if err := s.Convert(&in.Ready, &out.Ready, 0); err != nil {
return err
}
if err := s.Convert(&in.RestartCount, &out.RestartCount, 0); err != nil {
return err
}
if err := s.Convert(&in.Image, &out.Image, 0); err != nil {
return err
}
if err := s.Convert(&in.ImageID, &out.ImageID, 0); err != nil {
return err
}
if err := s.Convert(&in.ContainerID, &out.ContainerID, 0); err != nil {
return err
}
return nil
},
// Convert all to the new PodPhase constants
func(in *newer.PodPhase, out *PodStatus, s conversion.Scope) error {
switch *in {

View File

@ -484,7 +484,7 @@ func init() {
if err := s.Convert(&in.Phase, &out.Status, 0); err != nil {
return err
}
if err := s.Convert(&in.Info, &out.Info, 0); err != nil {
if err := s.Convert(&in.ContainerStatuses, &out.Info, 0); err != nil {
return err
}
if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil {
@ -500,7 +500,7 @@ func init() {
if err := s.Convert(&in.Status, &out.Phase, 0); err != nil {
return err
}
if err := s.Convert(&in.Info, &out.Info, 0); err != nil {
if err := s.Convert(&in.Info, &out.ContainerStatuses, 0); err != nil {
return err
}
if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil {
@ -513,6 +513,78 @@ func init() {
return nil
},
func(in *[]newer.ContainerStatus, out *PodInfo, s conversion.Scope) error {
*out = make(map[string]ContainerStatus)
for _, st := range *in {
v := ContainerStatus{}
if err := s.Convert(&st, &v, 0); err != nil {
return err
}
(*out)[st.Name] = v
}
return nil
},
func(in *PodInfo, out *[]newer.ContainerStatus, s conversion.Scope) error {
for k, v := range *in {
st := newer.ContainerStatus{}
if err := s.Convert(&v, &st, 0); err != nil {
return err
}
st.Name = k
*out = append(*out, st)
}
return nil
},
func(in *newer.ContainerStatus, out *ContainerStatus, s conversion.Scope) error {
if err := s.Convert(&in.State, &out.State, 0); err != nil {
return err
}
if err := s.Convert(&in.LastTerminationState, &out.LastTerminationState, 0); err != nil {
return err
}
if err := s.Convert(&in.Ready, &out.Ready, 0); err != nil {
return err
}
if err := s.Convert(&in.RestartCount, &out.RestartCount, 0); err != nil {
return err
}
if err := s.Convert(&in.Image, &out.Image, 0); err != nil {
return err
}
if err := s.Convert(&in.ImageID, &out.ImageID, 0); err != nil {
return err
}
if err := s.Convert(&in.ContainerID, &out.ContainerID, 0); err != nil {
return err
}
return nil
},
func(in *ContainerStatus, out *newer.ContainerStatus, s conversion.Scope) error {
if err := s.Convert(&in.State, &out.State, 0); err != nil {
return err
}
if err := s.Convert(&in.LastTerminationState, &out.LastTerminationState, 0); err != nil {
return err
}
if err := s.Convert(&in.Ready, &out.Ready, 0); err != nil {
return err
}
if err := s.Convert(&in.RestartCount, &out.RestartCount, 0); err != nil {
return err
}
if err := s.Convert(&in.Image, &out.Image, 0); err != nil {
return err
}
if err := s.Convert(&in.ImageID, &out.ImageID, 0); err != nil {
return err
}
if err := s.Convert(&in.ContainerID, &out.ContainerID, 0); err != nil {
return err
}
return nil
},
func(in *newer.PodStatusResult, out *PodStatusResult, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err

View File

@ -607,6 +607,8 @@ type ContainerState struct {
}
type ContainerStatus struct {
// Required: This must be a DNS_LABEL. Each container in a pod must have a unique name.
Name string `json:"name" description:"name of the container; must be a DNS_LABEL and unique within the pod; cannot be updated"`
// TODO(dchen1107): Should we rename PodStatus to a more generic name or have a separate states
// defined for container?
State ContainerState `json:"state,omitempty" description:"details about the container's current condition"`
@ -663,9 +665,6 @@ type PodCondition struct {
Status ConditionStatus `json:"status" description:"status of the condition, one of Full, None, Unknown"`
}
// PodInfo contains one entry for every container with available info.
type PodInfo map[string]ContainerStatus
// RestartPolicy describes how the container should be restarted.
// Only one of the following restart policies may be specified.
// If none of the following policies is specified, the default one
@ -727,13 +726,12 @@ type PodStatus struct {
HostIP string `json:"hostIP,omitempty" description:"IP address of the host to which the pod is assigned; empty if not yet scheduled"`
PodIP string `json:"podIP,omitempty" description:"IP address allocated to the pod; routable at least within the cluster; empty if not yet allocated"`
// The key of this map is the *name* of the container within the manifest; it has one
// entry per container in the manifest. The value of this map is currently the output
// The list has one entry per container in the manifest. Each entry is currently the output
// of `docker inspect`. This output format is *not* final and should not be relied
// upon.
// TODO: Make real decisions about what our info should look like. Re-enable fuzz test
// when we have done this.
Info PodInfo `json:"info,omitempty" description:"map of container name to container status"`
ContainerStatuses []ContainerStatus `json:"containerStatuses,omitempty" description:"list of container statuses"`
}
// PodStatusResult is a wrapper for PodStatus returned by kubelet that can be encode/decoded

View File

@ -33,9 +33,9 @@ import (
func TestHTTPKubeletClient(t *testing.T) {
expectObj := api.PodStatusResult{
Status: api.PodStatus{
Info: map[string]api.ContainerStatus{
"myID1": {},
"myID2": {},
ContainerStatuses: []api.ContainerStatus{
{Name: "myID1"},
{Name: "myID2"},
},
},
}
@ -73,15 +73,17 @@ func TestHTTPKubeletClient(t *testing.T) {
}
// reflect.DeepEqual(expectObj, gotObj) doesn't handle blank times well
if len(gotObj.Status.Info) != len(expectObj.Status.Info) {
if len(gotObj.Status.ContainerStatuses) != len(expectObj.Status.ContainerStatuses) {
t.Errorf("Unexpected response. Expected: %#v, received %#v", expectObj, gotObj)
}
}
func TestHTTPKubeletClientNotFound(t *testing.T) {
expectObj := api.PodContainerInfo{
ContainerInfo: map[string]api.ContainerStatus{
"myID": {},
ContainerInfo: []api.ContainerStatus{
{
Name: "myID",
},
},
}
_, err := json.Marshal(expectObj)
@ -120,8 +122,10 @@ func TestHTTPKubeletClientNotFound(t *testing.T) {
func TestHTTPKubeletClientError(t *testing.T) {
expectObj := api.PodContainerInfo{
ContainerInfo: map[string]api.ContainerStatus{
"myID": {},
ContainerInfo: []api.ContainerStatus{
{
Name: "myID",
},
},
}
_, err := json.Marshal(expectObj)

View File

@ -327,11 +327,15 @@ func TestTemplateStrings(t *testing.T) {
expect string
}{
"nilInfo": {api.Pod{}, "false"},
"emptyInfo": {api.Pod{Status: api.PodStatus{Info: api.PodInfo{}}}, "false"},
"emptyInfo": {api.Pod{Status: api.PodStatus{ContainerStatuses: []api.ContainerStatus{}}}, "false"},
"fooExists": {
api.Pod{
Status: api.PodStatus{
Info: api.PodInfo{"foo": api.ContainerStatus{}},
ContainerStatuses: []api.ContainerStatus{
{
Name: "foo",
},
},
},
},
"false",
@ -339,7 +343,11 @@ func TestTemplateStrings(t *testing.T) {
"barExists": {
api.Pod{
Status: api.PodStatus{
Info: api.PodInfo{"bar": api.ContainerStatus{}},
ContainerStatuses: []api.ContainerStatus{
{
Name: "bar",
},
},
},
},
"false",
@ -347,9 +355,13 @@ func TestTemplateStrings(t *testing.T) {
"bothExist": {
api.Pod{
Status: api.PodStatus{
Info: api.PodInfo{
"foo": api.ContainerStatus{},
"bar": api.ContainerStatus{},
ContainerStatuses: []api.ContainerStatus{
{
Name: "foo",
},
{
Name: "bar",
},
},
},
},
@ -358,9 +370,12 @@ func TestTemplateStrings(t *testing.T) {
"oneValid": {
api.Pod{
Status: api.PodStatus{
Info: api.PodInfo{
"foo": api.ContainerStatus{},
"bar": api.ContainerStatus{
ContainerStatuses: []api.ContainerStatus{
{
Name: "foo",
},
{
Name: "bar",
State: api.ContainerState{
Running: &api.ContainerStateRunning{
StartedAt: util.Time{},
@ -375,15 +390,17 @@ func TestTemplateStrings(t *testing.T) {
"bothValid": {
api.Pod{
Status: api.PodStatus{
Info: api.PodInfo{
"foo": api.ContainerStatus{
ContainerStatuses: []api.ContainerStatus{
{
Name: "foo",
State: api.ContainerState{
Running: &api.ContainerStateRunning{
StartedAt: util.Time{},
},
},
},
"bar": api.ContainerStatus{
{
Name: "bar",
State: api.ContainerState{
Running: &api.ContainerStateRunning{
StartedAt: util.Time{},

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

@ -1770,15 +1770,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 {
cStatus, found := api.GetContainerStatus(podStatus.ContainerStatuses, containerName)
if !found {
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(podStatus.Info[containerName].ContainerID, dockertools.DockerPrefix, "", 1), nil
}
}
return "", fmt.Errorf("container %q not found in pod", containerName)
return strings.Replace(cStatus.ContainerID, dockertools.DockerPrefix, "", 1), nil
}
// GetKubeletContainerLogs returns logs from the container
@ -1908,7 +1907,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
@ -1916,7 +1915,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 {
@ -1970,7 +1969,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,
@ -1979,11 +1978,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
}
@ -2038,13 +2037,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

@ -2183,6 +2183,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{
@ -2194,16 +2231,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
@ -2215,9 +2242,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",
},
@ -2229,9 +2256,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",
},
@ -2243,9 +2270,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",
},
@ -2257,8 +2284,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",
},
@ -2268,7 +2295,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)
}
}
@ -2285,25 +2312,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
@ -2315,9 +2323,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",
},
@ -2329,9 +2337,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",
},
@ -2343,9 +2351,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",
},
@ -2357,9 +2365,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",
},
@ -2371,8 +2379,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",
},
@ -2382,7 +2390,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)
}
}
@ -2399,25 +2407,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
@ -2429,9 +2418,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",
},
@ -2443,9 +2432,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",
},
@ -2457,9 +2446,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",
},
@ -2471,9 +2460,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",
},
@ -2485,8 +2474,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",
},
@ -2496,12 +2485,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,
@ -2513,7 +2515,7 @@ func TestGetPodReadyCondition(t *testing.T) {
}}
tests := []struct {
spec *api.PodSpec
info api.PodInfo
info []api.ContainerStatus
expected []api.PodCondition
}{
{
@ -2523,7 +2525,7 @@ func TestGetPodReadyCondition(t *testing.T) {
},
{
spec: &api.PodSpec{},
info: api.PodInfo{},
info: []api.ContainerStatus{},
expected: ready,
},
{
@ -2532,7 +2534,7 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "1234"},
},
},
info: api.PodInfo{},
info: []api.ContainerStatus{},
expected: unready,
},
{
@ -2541,8 +2543,8 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "1234"},
},
},
info: api.PodInfo{
"1234": api.ContainerStatus{Ready: true},
info: []api.ContainerStatus{
getReadyStatus("1234"),
},
expected: ready,
},
@ -2553,9 +2555,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,
},
@ -2566,8 +2568,8 @@ func TestGetPodReadyCondition(t *testing.T) {
{Name: "5678"},
},
},
info: api.PodInfo{
"1234": api.ContainerStatus{Ready: true},
info: []api.ContainerStatus{
getReadyStatus("1234"),
},
expected: unready,
},
@ -2578,9 +2580,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,
},
@ -3085,26 +3087,47 @@ func TestValidateContainerStatus(t *testing.T) {
kubelet := testKubelet.kubelet
containerName := "x"
testCases := []struct {
podInfo api.PodInfo
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 {
@ -3115,7 +3138,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) {

View File

@ -57,7 +57,7 @@ func runLivenessTest(c *client.Client, podDescr *api.Pod) {
By("checking the pod's current state and verifying that restartCount is present")
pod, err := c.Pods(ns).Get(podDescr.Name)
expectNoError(err, fmt.Sprintf("getting pod %s in namespace %s", podDescr.Name, ns))
initialRestartCount := pod.Status.Info["liveness"].RestartCount
initialRestartCount := api.GetExistingContainerStatus(pod.Status.ContainerStatuses, "liveness").RestartCount
By(fmt.Sprintf("Initial restart count of pod %s is %d", podDescr.Name, initialRestartCount))
// Wait for at most 48 * 5 = 240s = 4 minutes until restartCount is incremented
@ -67,7 +67,7 @@ func runLivenessTest(c *client.Client, podDescr *api.Pod) {
time.Sleep(5 * time.Second)
pod, err = c.Pods(ns).Get(podDescr.Name)
expectNoError(err, fmt.Sprintf("getting pod %s", podDescr.Name))
restartCount := pod.Status.Info["liveness"].RestartCount
restartCount := api.GetExistingContainerStatus(pod.Status.ContainerStatuses, "liveness").RestartCount
By(fmt.Sprintf("Restart count of pod %s in namespace %s is now %d", podDescr.Name, ns, restartCount))
if restartCount > initialRestartCount {
By(fmt.Sprintf("Restart count of pod %s in namespace %s increased from %d to %d during the test", podDescr.Name, ns, initialRestartCount, restartCount))

View File

@ -101,7 +101,7 @@ func waitForPodNotPending(c *client.Client, ns, podName string) error {
func waitForPodSuccessInNamespace(c *client.Client, podName string, contName string, namespace string) error {
return waitForPodCondition(c, namespace, podName, "success or failure", func(pod *api.Pod) (bool, error) {
// Cannot use pod.Status.Phase == api.PodSucceeded/api.PodFailed due to #2632
ci, ok := pod.Status.Info[contName]
ci, ok := api.GetContainerStatus(pod.Status.ContainerStatuses, contName)
if !ok {
Logf("No Status.Info for container %s in pod %s yet", contName, podName)
} else {