in images/controller/pkg/broker.go [46:152]
func GetPodStatus(namespace, selector string) (StatusResponse, error) {
var resp StatusResponse
var err error
type getPodsSpec struct {
Items []struct {
Metadata struct {
DeletionTimestamp *string `json:"deletionTimestamp"`
Annotations map[string]string `json:"annotations"`
} `json:"metadata"`
Spec map[string]interface{} `json:"spec"`
Status struct {
PodIP string `json:"podIP"`
Conditions []struct {
Type string `json:"type"`
Status string `json:"status"`
} `json:"conditions"`
ContainerStatuses []struct {
ContainerID string `json:"containerID"`
Image string `json:"image"`
Name string `json:"name"`
} `json:"containerStatuses"`
} `json:"status"`
} `json:"items"`
}
cmd := exec.Command("sh", "-c", fmt.Sprintf("kubectl get pod -n %s -l %s -o json 1>&2", namespace, selector))
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
return resp, fmt.Errorf("failed to get pods: %s, %v", string(stdoutStderr), err)
}
var podResp getPodsSpec
if err := json.Unmarshal(stdoutStderr, &podResp); err != nil {
return resp, fmt.Errorf("failed to parse pod spec: %v", err)
}
resp.Code = http.StatusOK
resp.Nodes = make([]string, 0)
resp.Containers = make(map[string]string, 0)
resp.Images = make(map[string]string, 0)
resp.SessionKeys = make([]string, 0)
resp.BrokerObjects = make([]string, 0)
podStatus := PodStatusResponse{}
for _, item := range podResp.Items {
// Status is terminating if metadata.deletionTimestamp is set.
// https://github.com/kubernetes/kubernetes/issues/22839
if item.Metadata.DeletionTimestamp != nil {
resp.Status = "terminating"
return resp, err
}
if sessionKey, ok := item.Metadata.Annotations["app.broker/session-key"]; ok {
resp.SessionKeys = append(resp.SessionKeys, sessionKey)
}
if brokerObjects, ok := item.Metadata.Annotations["app.broker/last-applied-object-types"]; ok {
resp.BrokerObjects = strings.Split(brokerObjects, ",")
}
for _, cond := range item.Status.Conditions {
if cond.Type == "Ready" {
if cond.Status == "True" {
resp.PodIPs = append(resp.PodIPs, item.Status.PodIP)
nodeName := item.Spec["nodeName"]
if nodeName != nil {
resp.Nodes = append(resp.Nodes, nodeName.(string))
}
podStatus.Ready++
} else {
podStatus.Waiting++
}
} else if cond.Type == "PodScheduled" && cond.Status == "False" {
podStatus.Waiting++
}
}
for _, containerStatus := range item.Status.ContainerStatuses {
resp.Containers[containerStatus.Name] = containerStatus.ContainerID
resp.Images[containerStatus.Name] = containerStatus.Image
}
}
// Status is shutdown if no pods matched selector
if len(podResp.Items) == 0 {
resp.Status = "shutdown"
}
// Populate status when we have at least 1 ready pod.
if podStatus.Ready > 0 {
resp.PodStatus = &podStatus
}
// Status is waiting until all pods are ready.
if podStatus.Waiting > 0 {
resp.Status = "waiting"
}
// Status is ready when no pods are waiting and we have at least 1 ready pod.
if podStatus.Waiting == 0 && podStatus.Ready > 0 {
resp.Status = "ready"
}
return resp, err
}