func GetPodStatus()

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
}