func describeService(service *api.Service, endpoints *api.Endpoints, events *api.EventList) (string, error) { if endpoints == nil { endpoints = &api.Endpoints{} } return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", service.Name) fmt.Fprintf(out, "Namespace:\t%s\n", service.Namespace) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(service.Labels)) fmt.Fprintf(out, "Selector:\t%s\n", labels.FormatLabels(service.Spec.Selector)) fmt.Fprintf(out, "Type:\t%s\n", service.Spec.Type) fmt.Fprintf(out, "IP:\t%s\n", service.Spec.ClusterIP) if len(service.Status.LoadBalancer.Ingress) > 0 { list := buildIngressString(service.Status.LoadBalancer.Ingress) fmt.Fprintf(out, "LoadBalancer Ingress:\t%s\n", list) } for i := range service.Spec.Ports { sp := &service.Spec.Ports[i] name := sp.Name if name == "" { name = "<unnamed>" } fmt.Fprintf(out, "Port:\t%s\t%d/%s\n", name, sp.Port, sp.Protocol) if sp.NodePort != 0 { fmt.Fprintf(out, "NodePort:\t%s\t%d/%s\n", name, sp.NodePort, sp.Protocol) } fmt.Fprintf(out, "Endpoints:\t%s\n", formatEndpoints(endpoints, sets.NewString(sp.Name))) } fmt.Fprintf(out, "Session Affinity:\t%s\n", service.Spec.SessionAffinity) if events != nil { DescribeEvents(events, out) } return nil }) }
func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { if withNamespace { return fmt.Errorf("persistentVolume is not namespaced") } name := pv.Name claimRefUID := "" if pv.Spec.ClaimRef != nil { claimRefUID += pv.Spec.ClaimRef.Namespace claimRefUID += "/" claimRefUID += pv.Spec.ClaimRef.Name } modesStr := api.GetAccessModesAsString(pv.Spec.AccessModes) aQty := pv.Spec.Capacity[api.ResourceStorage] aSize := aQty.String() if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", name, labels.FormatLabels(pv.Labels), aSize, modesStr, pv.Status.Phase, claimRefUID, pv.Status.Reason, translateTimestamp(pv.CreationTimestamp), ); err != nil { return err } _, err := fmt.Fprint(w, appendLabels(pv.Labels, columnLabels)) return err }
func (d *PersistentVolumeDescriber) Describe(namespace, name string) (string, error) { c := d.PersistentVolumes() pv, err := c.Get(name) if err != nil { return "", err } storage := pv.Spec.Capacity[api.ResourceStorage] return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", pv.Name) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(pv.Labels)) fmt.Fprintf(out, "Status:\t%s\n", pv.Status.Phase) if pv.Spec.ClaimRef != nil { fmt.Fprintf(out, "Claim:\t%s\n", pv.Spec.ClaimRef.Namespace+"/"+pv.Spec.ClaimRef.Name) } else { fmt.Fprintf(out, "Claim:\t%s\n", "") } fmt.Fprintf(out, "Reclaim Policy:\t%v\n", pv.Spec.PersistentVolumeReclaimPolicy) fmt.Fprintf(out, "Access Modes:\t%s\n", volume.GetAccessModesAsString(pv.Spec.AccessModes)) fmt.Fprintf(out, "Capacity:\t%s\n", storage.String()) fmt.Fprintf(out, "Message:\t%s\n", pv.Status.Message) return nil }) }
func printService(svc *api.Service, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { name := svc.Name namespace := svc.Namespace internalIP := svc.Spec.ClusterIP externalIP := getServiceExternalIP(svc) if withNamespace { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { return err } } if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s", name, internalIP, externalIP, makePortString(svc.Spec.Ports), labels.FormatLabels(svc.Spec.Selector), translateTimestamp(svc.CreationTimestamp), ); err != nil { return err } if _, err := fmt.Fprint(w, appendLabels(svc.Labels, columnLabels)); err != nil { return err } return nil }
func describePod(pod *api.Pod, rcs []api.ReplicationController, events *api.EventList) (string, error) { return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", pod.Name) fmt.Fprintf(out, "Namespace:\t%s\n", pod.Namespace) fmt.Fprintf(out, "Image(s):\t%s\n", makeImageList(&pod.Spec)) fmt.Fprintf(out, "Node:\t%s\n", pod.Spec.NodeName+"/"+pod.Status.HostIP) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(pod.Labels)) if pod.DeletionTimestamp != nil { fmt.Fprintf(out, "Status:\tTerminating (expires %s)\n", pod.DeletionTimestamp.Time.Format(time.RFC1123Z)) fmt.Fprintf(out, "Termination Grace Period:\t%ds\n", pod.DeletionGracePeriodSeconds) } else { fmt.Fprintf(out, "Status:\t%s\n", string(pod.Status.Phase)) } fmt.Fprintf(out, "Reason:\t%s\n", pod.Status.Reason) fmt.Fprintf(out, "Message:\t%s\n", pod.Status.Message) fmt.Fprintf(out, "IP:\t%s\n", pod.Status.PodIP) fmt.Fprintf(out, "Replication Controllers:\t%s\n", printReplicationControllersByLabels(rcs)) fmt.Fprintf(out, "Containers:\n") describeContainers(pod, out) if len(pod.Status.Conditions) > 0 { fmt.Fprint(out, "Conditions:\n Type\tStatus\n") for _, c := range pod.Status.Conditions { fmt.Fprintf(out, " %v \t%v \n", c.Type, c.Status) } } describeVolumes(pod.Spec.Volumes, out) if events != nil { DescribeEvents(events, out) } return nil }) }
func printNode(node *api.Node, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { if withNamespace { return fmt.Errorf("node is not namespaced") } conditionMap := make(map[api.NodeConditionType]*api.NodeCondition) NodeAllConditions := []api.NodeConditionType{api.NodeReady} for i := range node.Status.Conditions { cond := node.Status.Conditions[i] conditionMap[cond.Type] = &cond } var status []string for _, validCondition := range NodeAllConditions { if condition, ok := conditionMap[validCondition]; ok { if condition.Status == api.ConditionTrue { status = append(status, string(condition.Type)) } else { status = append(status, "Not"+string(condition.Type)) } } } if len(status) == 0 { status = append(status, "Unknown") } if node.Spec.Unschedulable { status = append(status, "SchedulingDisabled") } if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", node.Name, labels.FormatLabels(node.Labels), strings.Join(status, ","), translateTimestamp(node.CreationTimestamp)); err != nil { return err } _, err := fmt.Fprint(w, appendLabels(node.Labels, columnLabels)) return err }
func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string) (string, error) { c := d.PersistentVolumeClaims(namespace) pvc, err := c.Get(name) if err != nil { return "", err } labels := labels.FormatLabels(pvc.Labels) storage := pvc.Spec.Resources.Requests[api.ResourceStorage] capacity := "" accessModes := "" if pvc.Spec.VolumeName != "" { accessModes = api.GetAccessModesAsString(pvc.Status.AccessModes) storage = pvc.Status.Capacity[api.ResourceStorage] capacity = storage.String() } return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", pvc.Name) fmt.Fprintf(out, "Namespace:\t%s\n", pvc.Namespace) fmt.Fprintf(out, "Status:\t%v\n", pvc.Status.Phase) fmt.Fprintf(out, "Volume:\t%s\n", pvc.Spec.VolumeName) fmt.Fprintf(out, "Labels:\t%s\n", labels) fmt.Fprintf(out, "Capacity:\t%s\n", capacity) fmt.Fprintf(out, "Access Modes:\t%s\n", accessModes) return nil }) }
func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { name := pvc.Name namespace := pvc.Namespace if withNamespace { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { return err } } labels := labels.FormatLabels(pvc.Labels) phase := pvc.Status.Phase storage := pvc.Spec.Resources.Requests[api.ResourceStorage] capacity := "" accessModes := "" if pvc.Spec.VolumeName != "" { accessModes = api.GetAccessModesAsString(pvc.Status.AccessModes) storage = pvc.Status.Capacity[api.ResourceStorage] capacity = storage.String() } if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s", name, labels, phase, pvc.Spec.VolumeName, capacity, accessModes, translateTimestamp(pvc.CreationTimestamp)); err != nil { return err } _, err := fmt.Fprint(w, appendLabels(pvc.Labels, columnLabels)) return err }
func describeNode(node *api.Node, pods []*api.Pod, events *api.EventList) (string, error) { return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", node.Name) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(node.Labels)) fmt.Fprintf(out, "CreationTimestamp:\t%s\n", node.CreationTimestamp.Time.Format(time.RFC1123Z)) fmt.Fprintf(out, "Phase:\t%v\n", node.Status.Phase) if len(node.Status.Conditions) > 0 { fmt.Fprint(out, "Conditions:\n Type\tStatus\tLastHeartbeatTime\tLastTransitionTime\tReason\tMessage\n") fmt.Fprint(out, " ────\t──────\t─────────────────\t──────────────────\t──────\t───────\n") for _, c := range node.Status.Conditions { fmt.Fprintf(out, " %v \t%v \t%s \t%s \t%v \t%v\n", c.Type, c.Status, c.LastHeartbeatTime.Time.Format(time.RFC1123Z), c.LastTransitionTime.Time.Format(time.RFC1123Z), c.Reason, c.Message) } } var addresses []string for _, address := range node.Status.Addresses { addresses = append(addresses, address.Address) } fmt.Fprintf(out, "Addresses:\t%s\n", strings.Join(addresses, ",")) if len(node.Status.Capacity) > 0 { fmt.Fprintf(out, "Capacity:\n") for resource, value := range node.Status.Capacity { fmt.Fprintf(out, " %s:\t%s\n", resource, value.String()) } } fmt.Fprintf(out, "System Info:\n") fmt.Fprintf(out, " Machine ID:\t%s\n", node.Status.NodeInfo.MachineID) fmt.Fprintf(out, " System UUID:\t%s\n", node.Status.NodeInfo.SystemUUID) fmt.Fprintf(out, " Boot ID:\t%s\n", node.Status.NodeInfo.BootID) fmt.Fprintf(out, " Kernel Version:\t%s\n", node.Status.NodeInfo.KernelVersion) fmt.Fprintf(out, " OS Image:\t%s\n", node.Status.NodeInfo.OsImage) fmt.Fprintf(out, " Container Runtime Version:\t%s\n", node.Status.NodeInfo.ContainerRuntimeVersion) fmt.Fprintf(out, " Kubelet Version:\t%s\n", node.Status.NodeInfo.KubeletVersion) fmt.Fprintf(out, " Kube-Proxy Version:\t%s\n", node.Status.NodeInfo.KubeProxyVersion) if len(node.Spec.PodCIDR) > 0 { fmt.Fprintf(out, "PodCIDR:\t%s\n", node.Spec.PodCIDR) } if len(node.Spec.ExternalID) > 0 { fmt.Fprintf(out, "ExternalID:\t%s\n", node.Spec.ExternalID) } if err := describeNodeResource(pods, node, out); err != nil { return err } if events != nil { DescribeEvents(events, out) } return nil }) }
func printDaemonSet(ds *experimental.DaemonSet, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { name := ds.Name namespace := ds.Namespace containers := ds.Spec.Template.Spec.Containers var firstContainer api.Container if len(containers) > 0 { firstContainer, containers = containers[0], containers[1:] } if withNamespace { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { return err } } if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s", name, firstContainer.Name, firstContainer.Image, labels.FormatLabels(ds.Spec.Selector), labels.FormatLabels(ds.Spec.Template.Spec.NodeSelector), ); err != nil { return err } if _, err := fmt.Fprint(w, appendLabels(ds.Labels, columnLabels)); err != nil { return err } // Lay out all the other containers on separate lines. extraLinePrefix := "\t" if withNamespace { extraLinePrefix = "\t\t" } for _, container := range containers { _, err := fmt.Fprintf(w, "%s%s\t%s\t%s\t%s", extraLinePrefix, container.Name, container.Image, "", "") if err != nil { return err } if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { return err } } return nil }
func printNamespace(item *api.Namespace, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { if withNamespace { return fmt.Errorf("namespace is not namespaced") } if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", item.Name, labels.FormatLabels(item.Labels), item.Status.Phase, translateTimestamp(item.CreationTimestamp)); err != nil { return err } _, err := fmt.Fprint(w, appendLabels(item.Labels, columnLabels)) return err }
func describeReplicationController(controller *api.ReplicationController, events *api.EventList, running, waiting, succeeded, failed int) (string, error) { return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", controller.Name) fmt.Fprintf(out, "Namespace:\t%s\n", controller.Namespace) if controller.Spec.Template != nil { fmt.Fprintf(out, "Image(s):\t%s\n", makeImageList(&controller.Spec.Template.Spec)) } else { fmt.Fprintf(out, "Image(s):\t%s\n", "<no template>") } fmt.Fprintf(out, "Selector:\t%s\n", labels.FormatLabels(controller.Spec.Selector)) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(controller.Labels)) fmt.Fprintf(out, "Replicas:\t%d current / %d desired\n", controller.Status.Replicas, controller.Spec.Replicas) fmt.Fprintf(out, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed) if controller.Spec.Template != nil { describeVolumes(controller.Spec.Template.Spec.Volumes, out) } if events != nil { DescribeEvents(events, out) } return nil }) }
func describeSecret(secret *api.Secret) (string, error) { return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", secret.Name) fmt.Fprintf(out, "Namespace:\t%s\n", secret.Namespace) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(secret.Labels)) fmt.Fprintf(out, "Annotations:\t%s\n", labels.FormatLabels(secret.Annotations)) fmt.Fprintf(out, "\nType:\t%s\n", secret.Type) fmt.Fprintf(out, "\nData\n====\n") for k, v := range secret.Data { switch { case k == api.ServiceAccountTokenKey && secret.Type == api.SecretTypeServiceAccountToken: fmt.Fprintf(out, "%s:\t%s\n", k, string(v)) default: fmt.Fprintf(out, "%s:\t%d bytes\n", k, len(v)) } } return nil }) }
func describeServiceAccount(serviceAccount *api.ServiceAccount, tokens []api.Secret) (string, error) { return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", serviceAccount.Name) fmt.Fprintf(out, "Namespace:\t%s\n", serviceAccount.Namespace) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(serviceAccount.Labels)) fmt.Fprintln(out) var ( emptyHeader = " " pullHeader = "Image pull secrets:" mountHeader = "Mountable secrets: " tokenHeader = "Tokens: " pullSecretNames = []string{} mountSecretNames = []string{} tokenSecretNames = []string{} ) for _, s := range serviceAccount.ImagePullSecrets { pullSecretNames = append(pullSecretNames, s.Name) } for _, s := range serviceAccount.Secrets { mountSecretNames = append(mountSecretNames, s.Name) } for _, s := range tokens { tokenSecretNames = append(tokenSecretNames, s.Name) } types := map[string][]string{ pullHeader: pullSecretNames, mountHeader: mountSecretNames, tokenHeader: tokenSecretNames, } for header, names := range types { if len(names) == 0 { fmt.Fprintf(out, "%s\t<none>\n", header) } else { prefix := header for _, name := range names { fmt.Fprintf(out, "%s\t%s\n", prefix, name) prefix = emptyHeader } } fmt.Fprintln(out) } return nil }) }
func describeNamespace(namespace *api.Namespace, resourceQuotaList *api.ResourceQuotaList, limitRangeList *api.LimitRangeList) (string, error) { return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", namespace.Name) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(namespace.Labels)) fmt.Fprintf(out, "Status:\t%s\n", string(namespace.Status.Phase)) if resourceQuotaList != nil { fmt.Fprintf(out, "\n") DescribeResourceQuotas(resourceQuotaList, out) } if limitRangeList != nil { fmt.Fprintf(out, "\n") DescribeLimitRanges(limitRangeList, out) } return nil }) }
func printJob(job *experimental.Job, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { containers := job.Spec.Template.Spec.Containers var firstContainer api.Container if len(containers) > 0 { firstContainer = containers[0] } _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\n", job.Name, firstContainer.Name, firstContainer.Image, labels.FormatLabels(job.Spec.Selector), job.Status.Successful) if err != nil { return err } return nil }
func printReplicationController(controller *api.ReplicationController, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { name := controller.Name namespace := controller.Namespace containers := controller.Spec.Template.Spec.Containers var firstContainer api.Container if len(containers) > 0 { firstContainer, containers = containers[0], containers[1:] } if withNamespace { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { return err } } if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\t%s", name, firstContainer.Name, firstContainer.Image, labels.FormatLabels(controller.Spec.Selector), controller.Spec.Replicas, translateTimestamp(controller.CreationTimestamp), ); err != nil { return err } if _, err := fmt.Fprint(w, appendLabels(controller.Labels, columnLabels)); err != nil { return err } // Lay out all the other containers on separate lines. extraLinePrefix := "\t" if withNamespace { extraLinePrefix = "\t\t" } for _, container := range containers { _, err := fmt.Fprintf(w, "%s%s\t%s\t%s\t%s", extraLinePrefix, container.Name, container.Image, "", "") if err != nil { return err } if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { return err } } return nil }
func (d *PersistentVolumeDescriber) Describe(namespace, name string) (string, error) { c := d.PersistentVolumes() pv, err := c.Get(name) if err != nil { return "", err } storage := pv.Spec.Capacity[api.ResourceStorage] return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", pv.Name) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(pv.Labels)) fmt.Fprintf(out, "Status:\t%s\n", pv.Status.Phase) if pv.Spec.ClaimRef != nil { fmt.Fprintf(out, "Claim:\t%s\n", pv.Spec.ClaimRef.Namespace+"/"+pv.Spec.ClaimRef.Name) } else { fmt.Fprintf(out, "Claim:\t%s\n", "") } fmt.Fprintf(out, "Reclaim Policy:\t%v\n", pv.Spec.PersistentVolumeReclaimPolicy) fmt.Fprintf(out, "Access Modes:\t%s\n", api.GetAccessModesAsString(pv.Spec.AccessModes)) fmt.Fprintf(out, "Capacity:\t%s\n", storage.String()) fmt.Fprintf(out, "Message:\t%s\n", pv.Status.Message) fmt.Fprintf(out, "Source:\n") switch { case pv.Spec.HostPath != nil: printHostPathVolumeSource(pv.Spec.HostPath, out) case pv.Spec.GCEPersistentDisk != nil: printGCEPersistentDiskVolumeSource(pv.Spec.GCEPersistentDisk, out) case pv.Spec.AWSElasticBlockStore != nil: printAWSElasticBlockStoreVolumeSource(pv.Spec.AWSElasticBlockStore, out) case pv.Spec.NFS != nil: printNFSVolumeSource(pv.Spec.NFS, out) case pv.Spec.ISCSI != nil: printISCSIVolumeSource(pv.Spec.ISCSI, out) case pv.Spec.Glusterfs != nil: printGlusterfsVolumeSource(pv.Spec.Glusterfs, out) case pv.Spec.RBD != nil: printRBDVolumeSource(pv.Spec.RBD, out) } return nil }) }
func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string) (string, error) { hpa, err := d.client.Experimental().HorizontalPodAutoscalers(namespace).Get(name) if err != nil { return "", err } return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", hpa.Name) fmt.Fprintf(out, "Namespace:\t%s\n", hpa.Namespace) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(hpa.Labels)) fmt.Fprintf(out, "CreationTimestamp:\t%s\n", hpa.CreationTimestamp.Time.Format(time.RFC1123Z)) fmt.Fprintf(out, "Reference:\t%s/%s/%s/%s\n", hpa.Spec.ScaleRef.Kind, hpa.Spec.ScaleRef.Namespace, hpa.Spec.ScaleRef.Name, hpa.Spec.ScaleRef.Subresource) fmt.Fprintf(out, "Target resource consumption:\t%s %s\n", hpa.Spec.Target.Quantity.String(), hpa.Spec.Target.Resource) fmt.Fprintf(out, "Current resource consumption:\t") if hpa.Status != nil && hpa.Status.CurrentConsumption != nil { fmt.Fprintf(out, "%s %s\n", hpa.Status.CurrentConsumption.Quantity.String(), hpa.Status.CurrentConsumption.Resource) } else { fmt.Fprintf(out, "<not available>\n") } fmt.Fprintf(out, "Min pods:\t%d\n", hpa.Spec.MinCount) fmt.Fprintf(out, "Max pods:\t%d\n", hpa.Spec.MaxCount) // TODO: switch to scale subresource once the required code is submitted. if strings.ToLower(hpa.Spec.ScaleRef.Kind) == "replicationcontroller" { fmt.Fprintf(out, "ReplicationController pods:\t") rc, err := d.client.ReplicationControllers(hpa.Spec.ScaleRef.Namespace).Get(hpa.Spec.ScaleRef.Name) if err == nil { fmt.Fprintf(out, "%d current / %d desired\n", rc.Status.Replicas, rc.Spec.Replicas) } else { fmt.Fprintf(out, "failed to check Replication Controller\n") } } return nil }) }
func describeNode(node *api.Node, pods []*api.Pod, events *api.EventList) (string, error) { return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", node.Name) fmt.Fprintf(out, "Labels:\t%s\n", labels.FormatLabels(node.Labels)) fmt.Fprintf(out, "CreationTimestamp:\t%s\n", node.CreationTimestamp.Time.Format(time.RFC1123Z)) if len(node.Status.Conditions) > 0 { fmt.Fprint(out, "Conditions:\n Type\tStatus\tLastHeartbeatTime\tLastTransitionTime\tReason\tMessage\n") for _, c := range node.Status.Conditions { fmt.Fprintf(out, " %v \t%v \t%s \t%s \t%v \t%v\n", c.Type, c.Status, c.LastHeartbeatTime.Time.Format(time.RFC1123Z), c.LastTransitionTime.Time.Format(time.RFC1123Z), c.Reason, c.Message) } } var addresses []string for _, address := range node.Status.Addresses { addresses = append(addresses, address.Address) } fmt.Fprintf(out, "Addresses:\t%s\n", strings.Join(addresses, ",")) if len(node.Status.Capacity) > 0 { fmt.Fprintf(out, "Capacity:\n") for resource, value := range node.Status.Capacity { fmt.Fprintf(out, " %s:\t%s\n", resource, value.String()) } } runningPods := filterNonRunningPods(pods) reqs, err := getPodsTotalRequests(runningPods) if err != nil { return err } fmt.Fprintf(out, "Allocated resources (total requests):\n") for reqResource, reqValue := range reqs { fmt.Fprintf(out, " %s:\t%s\n", reqResource, reqValue.String()) } fmt.Fprintf(out, " pods:\t%d\n", len(runningPods)) fmt.Fprintf(out, "Version:\n") fmt.Fprintf(out, " Kernel Version:\t%s\n", node.Status.NodeInfo.KernelVersion) fmt.Fprintf(out, " OS Image:\t%s\n", node.Status.NodeInfo.OsImage) fmt.Fprintf(out, " Container Runtime Version:\t%s\n", node.Status.NodeInfo.ContainerRuntimeVersion) fmt.Fprintf(out, " Kubelet Version:\t%s\n", node.Status.NodeInfo.KubeletVersion) fmt.Fprintf(out, " Kube-Proxy Version:\t%s\n", node.Status.NodeInfo.KubeProxyVersion) if len(node.Spec.PodCIDR) > 0 { fmt.Fprintf(out, "PodCIDR:\t%s\n", node.Spec.PodCIDR) } if len(node.Spec.ExternalID) > 0 { fmt.Fprintf(out, "ExternalID:\t%s\n", node.Spec.ExternalID) } fmt.Fprintf(out, "Pods:\t(%d in total)\n", len(pods)) fmt.Fprint(out, " Namespace\tName\t\tCPU(milliCPU)\t\tMemory(bytes)\n") totalMilliCPU := int64(0) totalMemory := int64(0) fractionPodCPU := float64(0) fractionPodMemory := float64(0) fractionTotalCPU := float64(0) fractionTotalMemory := float64(0) for _, pod := range pods { podTotalMilliCPU := int64(0) podTotalMemory := int64(0) for ix := range pod.Spec.Containers { limits := pod.Spec.Containers[ix].Resources.Limits podTotalMilliCPU += limits.Cpu().MilliValue() podTotalMemory += limits.Memory().Value() } totalMilliCPU += podTotalMilliCPU totalMemory += podTotalMemory fractionPodCPU = float64(podTotalMilliCPU) / float64(node.Status.Capacity.Cpu().MilliValue()) * 100 fractionPodMemory = float64(podTotalMemory) / float64(node.Status.Capacity.Memory().Value()) * 100 fmt.Fprintf(out, " %s\t%s\t\t%d (%d%% of total)\t\t%d (%d%% of total)\n", pod.Namespace, pod.Name, podTotalMilliCPU, int64(fractionPodCPU), podTotalMemory, int64(fractionPodMemory)) } fmt.Fprint(out, "TotalResourceLimits:\n") fractionTotalCPU = float64(totalMilliCPU) / float64(node.Status.Capacity.Cpu().MilliValue()) * 100 fractionTotalMemory = float64(totalMemory) / float64(node.Status.Capacity.Memory().Value()) * 100 fmt.Fprintf(out, " CPU(milliCPU):\t\t%d (%d%% of total)\n", totalMilliCPU, int64(fractionTotalCPU)) fmt.Fprintf(out, " Memory(bytes):\t\t%d (%d%% of total)\n", totalMemory, int64(fractionTotalMemory)) if events != nil { DescribeEvents(events, out) } return nil }) }