k8s.io/kubernetes@v1.29.3/pkg/printers/internalversion/printers.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package internalversion 18 19 import ( 20 "bytes" 21 "fmt" 22 "net" 23 "sort" 24 "strconv" 25 "strings" 26 "time" 27 28 apiserverinternalv1alpha1 "k8s.io/api/apiserverinternal/v1alpha1" 29 appsv1beta1 "k8s.io/api/apps/v1beta1" 30 autoscalingv1 "k8s.io/api/autoscaling/v1" 31 autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" 32 batchv1 "k8s.io/api/batch/v1" 33 batchv1beta1 "k8s.io/api/batch/v1beta1" 34 certificatesv1alpha1 "k8s.io/api/certificates/v1alpha1" 35 certificatesv1beta1 "k8s.io/api/certificates/v1beta1" 36 coordinationv1 "k8s.io/api/coordination/v1" 37 apiv1 "k8s.io/api/core/v1" 38 discoveryv1beta1 "k8s.io/api/discovery/v1beta1" 39 extensionsv1beta1 "k8s.io/api/extensions/v1beta1" 40 flowcontrolv1 "k8s.io/api/flowcontrol/v1" 41 networkingv1alpha1 "k8s.io/api/networking/v1alpha1" 42 rbacv1beta1 "k8s.io/api/rbac/v1beta1" 43 resourcev1alpha2 "k8s.io/api/resource/v1alpha2" 44 schedulingv1 "k8s.io/api/scheduling/v1" 45 storagev1 "k8s.io/api/storage/v1" 46 storagev1alpha1 "k8s.io/api/storage/v1alpha1" 47 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 48 "k8s.io/apimachinery/pkg/labels" 49 "k8s.io/apimachinery/pkg/runtime" 50 "k8s.io/apimachinery/pkg/runtime/schema" 51 "k8s.io/apimachinery/pkg/util/duration" 52 "k8s.io/apimachinery/pkg/util/sets" 53 "k8s.io/client-go/util/certificate/csr" 54 "k8s.io/kubernetes/pkg/apis/admissionregistration" 55 "k8s.io/kubernetes/pkg/apis/apiserverinternal" 56 "k8s.io/kubernetes/pkg/apis/apps" 57 "k8s.io/kubernetes/pkg/apis/autoscaling" 58 "k8s.io/kubernetes/pkg/apis/batch" 59 "k8s.io/kubernetes/pkg/apis/certificates" 60 "k8s.io/kubernetes/pkg/apis/coordination" 61 api "k8s.io/kubernetes/pkg/apis/core" 62 "k8s.io/kubernetes/pkg/apis/core/helper" 63 "k8s.io/kubernetes/pkg/apis/discovery" 64 "k8s.io/kubernetes/pkg/apis/flowcontrol" 65 apihelpers "k8s.io/kubernetes/pkg/apis/flowcontrol/util" 66 "k8s.io/kubernetes/pkg/apis/networking" 67 nodeapi "k8s.io/kubernetes/pkg/apis/node" 68 "k8s.io/kubernetes/pkg/apis/policy" 69 "k8s.io/kubernetes/pkg/apis/rbac" 70 "k8s.io/kubernetes/pkg/apis/resource" 71 "k8s.io/kubernetes/pkg/apis/scheduling" 72 "k8s.io/kubernetes/pkg/apis/storage" 73 storageutil "k8s.io/kubernetes/pkg/apis/storage/util" 74 "k8s.io/kubernetes/pkg/printers" 75 "k8s.io/kubernetes/pkg/util/node" 76 ) 77 78 const ( 79 loadBalancerWidth = 16 80 81 // labelNodeRolePrefix is a label prefix for node roles 82 // It's copied over to here until it's merged in core: https://github.com/kubernetes/kubernetes/pull/39112 83 labelNodeRolePrefix = "node-role.kubernetes.io/" 84 85 // nodeLabelRole specifies the role of a node 86 nodeLabelRole = "kubernetes.io/role" 87 ) 88 89 // AddHandlers adds print handlers for default Kubernetes types dealing with internal versions. 90 func AddHandlers(h printers.PrintHandler) { 91 podColumnDefinitions := []metav1.TableColumnDefinition{ 92 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 93 {Name: "Ready", Type: "string", Description: "The aggregate readiness state of this pod for accepting traffic."}, 94 {Name: "Status", Type: "string", Description: "The aggregate status of the containers in this pod."}, 95 {Name: "Restarts", Type: "string", Description: "The number of times the containers in this pod have been restarted and when the last container in this pod has restarted."}, 96 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 97 {Name: "IP", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["podIP"]}, 98 {Name: "Node", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["nodeName"]}, 99 {Name: "Nominated Node", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["nominatedNodeName"]}, 100 {Name: "Readiness Gates", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["readinessGates"]}, 101 } 102 103 // Errors are suppressed as TableHandler already logs internally 104 _ = h.TableHandler(podColumnDefinitions, printPodList) 105 _ = h.TableHandler(podColumnDefinitions, printPod) 106 107 podTemplateColumnDefinitions := []metav1.TableColumnDefinition{ 108 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 109 {Name: "Containers", Type: "string", Description: "Names of each container in the template."}, 110 {Name: "Images", Type: "string", Description: "Images referenced by each container in the template."}, 111 {Name: "Pod Labels", Type: "string", Description: "The labels for the pod template."}, 112 } 113 _ = h.TableHandler(podTemplateColumnDefinitions, printPodTemplate) 114 _ = h.TableHandler(podTemplateColumnDefinitions, printPodTemplateList) 115 116 podDisruptionBudgetColumnDefinitions := []metav1.TableColumnDefinition{ 117 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 118 {Name: "Min Available", Type: "string", Description: "The minimum number of pods that must be available."}, 119 {Name: "Max Unavailable", Type: "string", Description: "The maximum number of pods that may be unavailable."}, 120 {Name: "Allowed Disruptions", Type: "integer", Description: "Calculated number of pods that may be disrupted at this time."}, 121 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 122 } 123 _ = h.TableHandler(podDisruptionBudgetColumnDefinitions, printPodDisruptionBudget) 124 _ = h.TableHandler(podDisruptionBudgetColumnDefinitions, printPodDisruptionBudgetList) 125 126 replicationControllerColumnDefinitions := []metav1.TableColumnDefinition{ 127 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 128 {Name: "Desired", Type: "integer", Description: apiv1.ReplicationControllerSpec{}.SwaggerDoc()["replicas"]}, 129 {Name: "Current", Type: "integer", Description: apiv1.ReplicationControllerStatus{}.SwaggerDoc()["replicas"]}, 130 {Name: "Ready", Type: "integer", Description: apiv1.ReplicationControllerStatus{}.SwaggerDoc()["readyReplicas"]}, 131 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 132 {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, 133 {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, 134 {Name: "Selector", Type: "string", Priority: 1, Description: apiv1.ReplicationControllerSpec{}.SwaggerDoc()["selector"]}, 135 } 136 _ = h.TableHandler(replicationControllerColumnDefinitions, printReplicationController) 137 _ = h.TableHandler(replicationControllerColumnDefinitions, printReplicationControllerList) 138 139 replicaSetColumnDefinitions := []metav1.TableColumnDefinition{ 140 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 141 {Name: "Desired", Type: "integer", Description: extensionsv1beta1.ReplicaSetSpec{}.SwaggerDoc()["replicas"]}, 142 {Name: "Current", Type: "integer", Description: extensionsv1beta1.ReplicaSetStatus{}.SwaggerDoc()["replicas"]}, 143 {Name: "Ready", Type: "integer", Description: extensionsv1beta1.ReplicaSetStatus{}.SwaggerDoc()["readyReplicas"]}, 144 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 145 {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, 146 {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, 147 {Name: "Selector", Type: "string", Priority: 1, Description: extensionsv1beta1.ReplicaSetSpec{}.SwaggerDoc()["selector"]}, 148 } 149 _ = h.TableHandler(replicaSetColumnDefinitions, printReplicaSet) 150 _ = h.TableHandler(replicaSetColumnDefinitions, printReplicaSetList) 151 152 daemonSetColumnDefinitions := []metav1.TableColumnDefinition{ 153 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 154 {Name: "Desired", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["desiredNumberScheduled"]}, 155 {Name: "Current", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["currentNumberScheduled"]}, 156 {Name: "Ready", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["numberReady"]}, 157 {Name: "Up-to-date", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["updatedNumberScheduled"]}, 158 {Name: "Available", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["numberAvailable"]}, 159 {Name: "Node Selector", Type: "string", Description: apiv1.PodSpec{}.SwaggerDoc()["nodeSelector"]}, 160 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 161 {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, 162 {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, 163 {Name: "Selector", Type: "string", Priority: 1, Description: extensionsv1beta1.DaemonSetSpec{}.SwaggerDoc()["selector"]}, 164 } 165 _ = h.TableHandler(daemonSetColumnDefinitions, printDaemonSet) 166 _ = h.TableHandler(daemonSetColumnDefinitions, printDaemonSetList) 167 168 jobColumnDefinitions := []metav1.TableColumnDefinition{ 169 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 170 {Name: "Completions", Type: "string", Description: batchv1.JobStatus{}.SwaggerDoc()["succeeded"]}, 171 {Name: "Duration", Type: "string", Description: "Time required to complete the job."}, 172 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 173 {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, 174 {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, 175 {Name: "Selector", Type: "string", Priority: 1, Description: batchv1.JobSpec{}.SwaggerDoc()["selector"]}, 176 } 177 _ = h.TableHandler(jobColumnDefinitions, printJob) 178 _ = h.TableHandler(jobColumnDefinitions, printJobList) 179 180 cronJobColumnDefinitions := []metav1.TableColumnDefinition{ 181 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 182 {Name: "Schedule", Type: "string", Description: batchv1beta1.CronJobSpec{}.SwaggerDoc()["schedule"]}, 183 {Name: "Suspend", Type: "boolean", Description: batchv1beta1.CronJobSpec{}.SwaggerDoc()["suspend"]}, 184 {Name: "Active", Type: "integer", Description: batchv1beta1.CronJobStatus{}.SwaggerDoc()["active"]}, 185 {Name: "Last Schedule", Type: "string", Description: batchv1beta1.CronJobStatus{}.SwaggerDoc()["lastScheduleTime"]}, 186 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 187 {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, 188 {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, 189 {Name: "Selector", Type: "string", Priority: 1, Description: batchv1.JobSpec{}.SwaggerDoc()["selector"]}, 190 } 191 _ = h.TableHandler(cronJobColumnDefinitions, printCronJob) 192 _ = h.TableHandler(cronJobColumnDefinitions, printCronJobList) 193 194 serviceColumnDefinitions := []metav1.TableColumnDefinition{ 195 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 196 {Name: "Type", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["type"]}, 197 {Name: "Cluster-IP", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["clusterIP"]}, 198 {Name: "External-IP", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["externalIPs"]}, 199 {Name: "Port(s)", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["ports"]}, 200 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 201 {Name: "Selector", Type: "string", Priority: 1, Description: apiv1.ServiceSpec{}.SwaggerDoc()["selector"]}, 202 } 203 204 _ = h.TableHandler(serviceColumnDefinitions, printService) 205 _ = h.TableHandler(serviceColumnDefinitions, printServiceList) 206 207 ingressColumnDefinitions := []metav1.TableColumnDefinition{ 208 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 209 {Name: "Class", Type: "string", Description: "The name of the IngressClass resource that should be used for additional configuration"}, 210 {Name: "Hosts", Type: "string", Description: "Hosts that incoming requests are matched against before the ingress rule"}, 211 {Name: "Address", Type: "string", Description: "Address is a list containing ingress points for the load-balancer"}, 212 {Name: "Ports", Type: "string", Description: "Ports of TLS configurations that open"}, 213 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 214 } 215 _ = h.TableHandler(ingressColumnDefinitions, printIngress) 216 _ = h.TableHandler(ingressColumnDefinitions, printIngressList) 217 218 ingressClassColumnDefinitions := []metav1.TableColumnDefinition{ 219 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 220 {Name: "Controller", Type: "string", Description: "Controller that is responsible for handling this class"}, 221 {Name: "Parameters", Type: "string", Description: "A reference to a resource with additional parameters"}, 222 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 223 } 224 _ = h.TableHandler(ingressClassColumnDefinitions, printIngressClass) 225 _ = h.TableHandler(ingressClassColumnDefinitions, printIngressClassList) 226 227 statefulSetColumnDefinitions := []metav1.TableColumnDefinition{ 228 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 229 {Name: "Ready", Type: "string", Description: "Number of the pod with ready state"}, 230 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 231 {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, 232 {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, 233 } 234 _ = h.TableHandler(statefulSetColumnDefinitions, printStatefulSet) 235 _ = h.TableHandler(statefulSetColumnDefinitions, printStatefulSetList) 236 237 endpointColumnDefinitions := []metav1.TableColumnDefinition{ 238 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 239 {Name: "Endpoints", Type: "string", Description: apiv1.Endpoints{}.SwaggerDoc()["subsets"]}, 240 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 241 } 242 _ = h.TableHandler(endpointColumnDefinitions, printEndpoints) 243 _ = h.TableHandler(endpointColumnDefinitions, printEndpointsList) 244 245 nodeColumnDefinitions := []metav1.TableColumnDefinition{ 246 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 247 {Name: "Status", Type: "string", Description: "The status of the node"}, 248 {Name: "Roles", Type: "string", Description: "The roles of the node"}, 249 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 250 {Name: "Version", Type: "string", Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kubeletVersion"]}, 251 {Name: "Internal-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]}, 252 {Name: "External-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]}, 253 {Name: "OS-Image", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["osImage"]}, 254 {Name: "Kernel-Version", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kernelVersion"]}, 255 {Name: "Container-Runtime", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["containerRuntimeVersion"]}, 256 } 257 258 _ = h.TableHandler(nodeColumnDefinitions, printNode) 259 _ = h.TableHandler(nodeColumnDefinitions, printNodeList) 260 261 eventColumnDefinitions := []metav1.TableColumnDefinition{ 262 {Name: "Last Seen", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["lastTimestamp"]}, 263 {Name: "Type", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["type"]}, 264 {Name: "Reason", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["reason"]}, 265 {Name: "Object", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["involvedObject"]}, 266 {Name: "Subobject", Type: "string", Priority: 1, Description: apiv1.Event{}.InvolvedObject.SwaggerDoc()["fieldPath"]}, 267 {Name: "Source", Type: "string", Priority: 1, Description: apiv1.Event{}.SwaggerDoc()["source"]}, 268 {Name: "Message", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["message"]}, 269 {Name: "First Seen", Type: "string", Priority: 1, Description: apiv1.Event{}.SwaggerDoc()["firstTimestamp"]}, 270 {Name: "Count", Type: "string", Priority: 1, Description: apiv1.Event{}.SwaggerDoc()["count"]}, 271 {Name: "Name", Type: "string", Priority: 1, Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 272 } 273 _ = h.TableHandler(eventColumnDefinitions, printEvent) 274 _ = h.TableHandler(eventColumnDefinitions, printEventList) 275 276 namespaceColumnDefinitions := []metav1.TableColumnDefinition{ 277 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 278 {Name: "Status", Type: "string", Description: "The status of the namespace"}, 279 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 280 } 281 _ = h.TableHandler(namespaceColumnDefinitions, printNamespace) 282 _ = h.TableHandler(namespaceColumnDefinitions, printNamespaceList) 283 284 secretColumnDefinitions := []metav1.TableColumnDefinition{ 285 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 286 {Name: "Type", Type: "string", Description: apiv1.Secret{}.SwaggerDoc()["type"]}, 287 {Name: "Data", Type: "string", Description: apiv1.Secret{}.SwaggerDoc()["data"]}, 288 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 289 } 290 _ = h.TableHandler(secretColumnDefinitions, printSecret) 291 _ = h.TableHandler(secretColumnDefinitions, printSecretList) 292 293 serviceAccountColumnDefinitions := []metav1.TableColumnDefinition{ 294 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 295 {Name: "Secrets", Type: "string", Description: apiv1.ServiceAccount{}.SwaggerDoc()["secrets"]}, 296 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 297 } 298 _ = h.TableHandler(serviceAccountColumnDefinitions, printServiceAccount) 299 _ = h.TableHandler(serviceAccountColumnDefinitions, printServiceAccountList) 300 301 persistentVolumeColumnDefinitions := []metav1.TableColumnDefinition{ 302 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 303 {Name: "Capacity", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["capacity"]}, 304 {Name: "Access Modes", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["accessModes"]}, 305 {Name: "Reclaim Policy", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["persistentVolumeReclaimPolicy"]}, 306 {Name: "Status", Type: "string", Description: apiv1.PersistentVolumeStatus{}.SwaggerDoc()["phase"]}, 307 {Name: "Claim", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["claimRef"]}, 308 {Name: "StorageClass", Type: "string", Description: "StorageClass of the pv"}, 309 {Name: "VolumeAttributesClass", Type: "string", Description: "VolumeAttributesClass of the pv"}, 310 {Name: "Reason", Type: "string", Description: apiv1.PersistentVolumeStatus{}.SwaggerDoc()["reason"]}, 311 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 312 {Name: "VolumeMode", Type: "string", Priority: 1, Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["volumeMode"]}, 313 } 314 _ = h.TableHandler(persistentVolumeColumnDefinitions, printPersistentVolume) 315 _ = h.TableHandler(persistentVolumeColumnDefinitions, printPersistentVolumeList) 316 317 persistentVolumeClaimColumnDefinitions := []metav1.TableColumnDefinition{ 318 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 319 {Name: "Status", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["phase"]}, 320 {Name: "Volume", Type: "string", Description: apiv1.PersistentVolumeClaimSpec{}.SwaggerDoc()["volumeName"]}, 321 {Name: "Capacity", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["capacity"]}, 322 {Name: "Access Modes", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["accessModes"]}, 323 {Name: "StorageClass", Type: "string", Description: "StorageClass of the pvc"}, 324 {Name: "VolumeAttributesClass", Type: "string", Description: "VolumeAttributesClass of the pvc"}, 325 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 326 {Name: "VolumeMode", Type: "string", Priority: 1, Description: apiv1.PersistentVolumeClaimSpec{}.SwaggerDoc()["volumeMode"]}, 327 } 328 _ = h.TableHandler(persistentVolumeClaimColumnDefinitions, printPersistentVolumeClaim) 329 _ = h.TableHandler(persistentVolumeClaimColumnDefinitions, printPersistentVolumeClaimList) 330 331 componentStatusColumnDefinitions := []metav1.TableColumnDefinition{ 332 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 333 {Name: "Status", Type: "string", Description: "Status of the component conditions"}, 334 {Name: "Message", Type: "string", Description: "Message of the component conditions"}, 335 {Name: "Error", Type: "string", Description: "Error of the component conditions"}, 336 } 337 _ = h.TableHandler(componentStatusColumnDefinitions, printComponentStatus) 338 _ = h.TableHandler(componentStatusColumnDefinitions, printComponentStatusList) 339 340 deploymentColumnDefinitions := []metav1.TableColumnDefinition{ 341 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 342 {Name: "Ready", Type: "string", Description: "Number of the pod with ready state"}, 343 {Name: "Up-to-date", Type: "string", Description: extensionsv1beta1.DeploymentStatus{}.SwaggerDoc()["updatedReplicas"]}, 344 {Name: "Available", Type: "string", Description: extensionsv1beta1.DeploymentStatus{}.SwaggerDoc()["availableReplicas"]}, 345 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 346 {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, 347 {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, 348 {Name: "Selector", Type: "string", Priority: 1, Description: extensionsv1beta1.DeploymentSpec{}.SwaggerDoc()["selector"]}, 349 } 350 _ = h.TableHandler(deploymentColumnDefinitions, printDeployment) 351 _ = h.TableHandler(deploymentColumnDefinitions, printDeploymentList) 352 353 horizontalPodAutoscalerColumnDefinitions := []metav1.TableColumnDefinition{ 354 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 355 {Name: "Reference", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["scaleTargetRef"]}, 356 {Name: "Targets", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["metrics"]}, 357 {Name: "MinPods", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["minReplicas"]}, 358 {Name: "MaxPods", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["maxReplicas"]}, 359 {Name: "Replicas", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerStatus{}.SwaggerDoc()["currentReplicas"]}, 360 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 361 } 362 _ = h.TableHandler(horizontalPodAutoscalerColumnDefinitions, printHorizontalPodAutoscaler) 363 _ = h.TableHandler(horizontalPodAutoscalerColumnDefinitions, printHorizontalPodAutoscalerList) 364 365 configMapColumnDefinitions := []metav1.TableColumnDefinition{ 366 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 367 {Name: "Data", Type: "string", Description: apiv1.ConfigMap{}.SwaggerDoc()["data"]}, 368 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 369 } 370 _ = h.TableHandler(configMapColumnDefinitions, printConfigMap) 371 _ = h.TableHandler(configMapColumnDefinitions, printConfigMapList) 372 373 networkPolicyColumnDefinitioins := []metav1.TableColumnDefinition{ 374 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 375 {Name: "Pod-Selector", Type: "string", Description: extensionsv1beta1.NetworkPolicySpec{}.SwaggerDoc()["podSelector"]}, 376 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 377 } 378 _ = h.TableHandler(networkPolicyColumnDefinitioins, printNetworkPolicy) 379 _ = h.TableHandler(networkPolicyColumnDefinitioins, printNetworkPolicyList) 380 381 roleBindingsColumnDefinitions := []metav1.TableColumnDefinition{ 382 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 383 {Name: "Role", Type: "string", Description: rbacv1beta1.RoleBinding{}.SwaggerDoc()["roleRef"]}, 384 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 385 {Name: "Users", Type: "string", Priority: 1, Description: "Users in the roleBinding"}, 386 {Name: "Groups", Type: "string", Priority: 1, Description: "Groups in the roleBinding"}, 387 {Name: "ServiceAccounts", Type: "string", Priority: 1, Description: "ServiceAccounts in the roleBinding"}, 388 } 389 _ = h.TableHandler(roleBindingsColumnDefinitions, printRoleBinding) 390 _ = h.TableHandler(roleBindingsColumnDefinitions, printRoleBindingList) 391 392 clusterRoleBindingsColumnDefinitions := []metav1.TableColumnDefinition{ 393 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 394 {Name: "Role", Type: "string", Description: rbacv1beta1.ClusterRoleBinding{}.SwaggerDoc()["roleRef"]}, 395 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 396 {Name: "Users", Type: "string", Priority: 1, Description: "Users in the clusterRoleBinding"}, 397 {Name: "Groups", Type: "string", Priority: 1, Description: "Groups in the clusterRoleBinding"}, 398 {Name: "ServiceAccounts", Type: "string", Priority: 1, Description: "ServiceAccounts in the clusterRoleBinding"}, 399 } 400 _ = h.TableHandler(clusterRoleBindingsColumnDefinitions, printClusterRoleBinding) 401 _ = h.TableHandler(clusterRoleBindingsColumnDefinitions, printClusterRoleBindingList) 402 403 certificateSigningRequestColumnDefinitions := []metav1.TableColumnDefinition{ 404 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 405 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 406 {Name: "SignerName", Type: "string", Description: certificatesv1beta1.CertificateSigningRequestSpec{}.SwaggerDoc()["signerName"]}, 407 {Name: "Requestor", Type: "string", Description: certificatesv1beta1.CertificateSigningRequestSpec{}.SwaggerDoc()["request"]}, 408 {Name: "RequestedDuration", Type: "string", Description: certificatesv1beta1.CertificateSigningRequestSpec{}.SwaggerDoc()["expirationSeconds"]}, 409 {Name: "Condition", Type: "string", Description: certificatesv1beta1.CertificateSigningRequestStatus{}.SwaggerDoc()["conditions"]}, 410 } 411 _ = h.TableHandler(certificateSigningRequestColumnDefinitions, printCertificateSigningRequest) 412 _ = h.TableHandler(certificateSigningRequestColumnDefinitions, printCertificateSigningRequestList) 413 414 clusterTrustBundleColumnDefinitions := []metav1.TableColumnDefinition{ 415 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 416 {Name: "SignerName", Type: "string", Description: certificatesv1alpha1.ClusterTrustBundleSpec{}.SwaggerDoc()["signerName"]}, 417 } 418 h.TableHandler(clusterTrustBundleColumnDefinitions, printClusterTrustBundle) 419 h.TableHandler(clusterTrustBundleColumnDefinitions, printClusterTrustBundleList) 420 421 leaseColumnDefinitions := []metav1.TableColumnDefinition{ 422 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 423 {Name: "Holder", Type: "string", Description: coordinationv1.LeaseSpec{}.SwaggerDoc()["holderIdentity"]}, 424 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 425 } 426 _ = h.TableHandler(leaseColumnDefinitions, printLease) 427 _ = h.TableHandler(leaseColumnDefinitions, printLeaseList) 428 429 storageClassColumnDefinitions := []metav1.TableColumnDefinition{ 430 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 431 {Name: "Provisioner", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["provisioner"]}, 432 {Name: "ReclaimPolicy", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["reclaimPolicy"]}, 433 {Name: "VolumeBindingMode", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["volumeBindingMode"]}, 434 {Name: "AllowVolumeExpansion", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["allowVolumeExpansion"]}, 435 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 436 } 437 438 _ = h.TableHandler(storageClassColumnDefinitions, printStorageClass) 439 _ = h.TableHandler(storageClassColumnDefinitions, printStorageClassList) 440 441 volumeAttributesClassColumnDefinitions := []metav1.TableColumnDefinition{ 442 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 443 {Name: "DriverName", Type: "string", Description: storagev1alpha1.VolumeAttributesClass{}.SwaggerDoc()["driverName"]}, 444 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 445 } 446 447 _ = h.TableHandler(volumeAttributesClassColumnDefinitions, printVolumeAttributesClass) 448 _ = h.TableHandler(volumeAttributesClassColumnDefinitions, printVolumeAttributesClassList) 449 450 statusColumnDefinitions := []metav1.TableColumnDefinition{ 451 {Name: "Status", Type: "string", Description: metav1.Status{}.SwaggerDoc()["status"]}, 452 {Name: "Reason", Type: "string", Description: metav1.Status{}.SwaggerDoc()["reason"]}, 453 {Name: "Message", Type: "string", Description: metav1.Status{}.SwaggerDoc()["Message"]}, 454 } 455 456 _ = h.TableHandler(statusColumnDefinitions, printStatus) 457 458 controllerRevisionColumnDefinition := []metav1.TableColumnDefinition{ 459 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 460 {Name: "Controller", Type: "string", Description: "Controller of the object"}, 461 {Name: "Revision", Type: "string", Description: appsv1beta1.ControllerRevision{}.SwaggerDoc()["revision"]}, 462 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 463 } 464 _ = h.TableHandler(controllerRevisionColumnDefinition, printControllerRevision) 465 _ = h.TableHandler(controllerRevisionColumnDefinition, printControllerRevisionList) 466 467 resourceQuotaColumnDefinitions := []metav1.TableColumnDefinition{ 468 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 469 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 470 {Name: "Request", Type: "string", Description: "Request represents a minimum amount of cpu/memory that a container may consume."}, 471 {Name: "Limit", Type: "string", Description: "Limits control the maximum amount of cpu/memory that a container may use independent of contention on the node."}, 472 } 473 _ = h.TableHandler(resourceQuotaColumnDefinitions, printResourceQuota) 474 _ = h.TableHandler(resourceQuotaColumnDefinitions, printResourceQuotaList) 475 476 priorityClassColumnDefinitions := []metav1.TableColumnDefinition{ 477 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 478 {Name: "Value", Type: "integer", Description: schedulingv1.PriorityClass{}.SwaggerDoc()["value"]}, 479 {Name: "Global-Default", Type: "boolean", Description: schedulingv1.PriorityClass{}.SwaggerDoc()["globalDefault"]}, 480 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 481 } 482 _ = h.TableHandler(priorityClassColumnDefinitions, printPriorityClass) 483 _ = h.TableHandler(priorityClassColumnDefinitions, printPriorityClassList) 484 485 runtimeClassColumnDefinitions := []metav1.TableColumnDefinition{ 486 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 487 {Name: "Handler", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["handler"]}, 488 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 489 } 490 _ = h.TableHandler(runtimeClassColumnDefinitions, printRuntimeClass) 491 _ = h.TableHandler(runtimeClassColumnDefinitions, printRuntimeClassList) 492 493 volumeAttachmentColumnDefinitions := []metav1.TableColumnDefinition{ 494 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 495 {Name: "Attacher", Type: "string", Format: "name", Description: storagev1.VolumeAttachmentSpec{}.SwaggerDoc()["attacher"]}, 496 {Name: "PV", Type: "string", Description: storagev1.VolumeAttachmentSource{}.SwaggerDoc()["persistentVolumeName"]}, 497 {Name: "Node", Type: "string", Description: storagev1.VolumeAttachmentSpec{}.SwaggerDoc()["nodeName"]}, 498 {Name: "Attached", Type: "boolean", Description: storagev1.VolumeAttachmentStatus{}.SwaggerDoc()["attached"]}, 499 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 500 } 501 _ = h.TableHandler(volumeAttachmentColumnDefinitions, printVolumeAttachment) 502 _ = h.TableHandler(volumeAttachmentColumnDefinitions, printVolumeAttachmentList) 503 504 endpointSliceColumnDefinitions := []metav1.TableColumnDefinition{ 505 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 506 {Name: "AddressType", Type: "string", Description: discoveryv1beta1.EndpointSlice{}.SwaggerDoc()["addressType"]}, 507 {Name: "Ports", Type: "string", Description: discoveryv1beta1.EndpointSlice{}.SwaggerDoc()["ports"]}, 508 {Name: "Endpoints", Type: "string", Description: discoveryv1beta1.EndpointSlice{}.SwaggerDoc()["endpoints"]}, 509 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 510 } 511 _ = h.TableHandler(endpointSliceColumnDefinitions, printEndpointSlice) 512 _ = h.TableHandler(endpointSliceColumnDefinitions, printEndpointSliceList) 513 514 csiNodeColumnDefinitions := []metav1.TableColumnDefinition{ 515 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 516 {Name: "Drivers", Type: "integer", Description: "Drivers indicates the number of CSI drivers registered on the node"}, 517 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 518 } 519 _ = h.TableHandler(csiNodeColumnDefinitions, printCSINode) 520 _ = h.TableHandler(csiNodeColumnDefinitions, printCSINodeList) 521 522 csiDriverColumnDefinitions := []metav1.TableColumnDefinition{ 523 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 524 {Name: "AttachRequired", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["attachRequired"]}, 525 {Name: "PodInfoOnMount", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["podInfoOnMount"]}, 526 {Name: "StorageCapacity", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["storageCapacity"]}, 527 } 528 csiDriverColumnDefinitions = append(csiDriverColumnDefinitions, []metav1.TableColumnDefinition{ 529 {Name: "TokenRequests", Type: "string", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["tokenRequests"]}, 530 {Name: "RequiresRepublish", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["requiresRepublish"]}, 531 }...) 532 533 csiDriverColumnDefinitions = append(csiDriverColumnDefinitions, []metav1.TableColumnDefinition{ 534 {Name: "Modes", Type: "string", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["volumeLifecycleModes"]}, 535 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 536 }...) 537 _ = h.TableHandler(csiDriverColumnDefinitions, printCSIDriver) 538 _ = h.TableHandler(csiDriverColumnDefinitions, printCSIDriverList) 539 540 csiStorageCapacityColumnDefinitions := []metav1.TableColumnDefinition{ 541 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 542 {Name: "StorageClassName", Type: "string", Description: storagev1.CSIStorageCapacity{}.SwaggerDoc()["storageClassName"]}, 543 {Name: "Capacity", Type: "string", Description: storagev1.CSIStorageCapacity{}.SwaggerDoc()["capacity"]}, 544 } 545 _ = h.TableHandler(csiStorageCapacityColumnDefinitions, printCSIStorageCapacity) 546 _ = h.TableHandler(csiStorageCapacityColumnDefinitions, printCSIStorageCapacityList) 547 548 mutatingWebhookColumnDefinitions := []metav1.TableColumnDefinition{ 549 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 550 {Name: "Webhooks", Type: "integer", Description: "Webhooks indicates the number of webhooks registered in this configuration"}, 551 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 552 } 553 _ = h.TableHandler(mutatingWebhookColumnDefinitions, printMutatingWebhook) 554 _ = h.TableHandler(mutatingWebhookColumnDefinitions, printMutatingWebhookList) 555 556 validatingWebhookColumnDefinitions := []metav1.TableColumnDefinition{ 557 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 558 {Name: "Webhooks", Type: "integer", Description: "Webhooks indicates the number of webhooks registered in this configuration"}, 559 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 560 } 561 _ = h.TableHandler(validatingWebhookColumnDefinitions, printValidatingWebhook) 562 _ = h.TableHandler(validatingWebhookColumnDefinitions, printValidatingWebhookList) 563 564 validatingAdmissionPolicy := []metav1.TableColumnDefinition{ 565 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 566 {Name: "Validations", Type: "integer", Description: "Validations indicates the number of validation rules defined in this configuration"}, 567 {Name: "ParamKind", Type: "string", Description: "ParamKind specifies the kind of resources used to parameterize this policy"}, 568 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 569 } 570 _ = h.TableHandler(validatingAdmissionPolicy, printValidatingAdmissionPolicy) 571 _ = h.TableHandler(validatingAdmissionPolicy, printValidatingAdmissionPolicyList) 572 573 validatingAdmissionPolicyBinding := []metav1.TableColumnDefinition{ 574 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 575 {Name: "PolicyName", Type: "string", Description: "PolicyName indicates the policy definition which the policy binding binded to"}, 576 {Name: "ParamRef", Type: "string", Description: "ParamRef indicates the param resource which sets the configration param"}, 577 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 578 } 579 _ = h.TableHandler(validatingAdmissionPolicyBinding, printValidatingAdmissionPolicyBinding) 580 _ = h.TableHandler(validatingAdmissionPolicyBinding, printValidatingAdmissionPolicyBindingList) 581 582 flowSchemaColumnDefinitions := []metav1.TableColumnDefinition{ 583 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 584 {Name: "PriorityLevel", Type: "string", Description: flowcontrolv1.PriorityLevelConfigurationReference{}.SwaggerDoc()["name"]}, 585 {Name: "MatchingPrecedence", Type: "string", Description: flowcontrolv1.FlowSchemaSpec{}.SwaggerDoc()["matchingPrecedence"]}, 586 {Name: "DistinguisherMethod", Type: "string", Description: flowcontrolv1.FlowSchemaSpec{}.SwaggerDoc()["distinguisherMethod"]}, 587 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 588 {Name: "MissingPL", Type: "string", Description: "references a broken or non-existent PriorityLevelConfiguration"}, 589 } 590 _ = h.TableHandler(flowSchemaColumnDefinitions, printFlowSchema) 591 _ = h.TableHandler(flowSchemaColumnDefinitions, printFlowSchemaList) 592 593 priorityLevelColumnDefinitions := []metav1.TableColumnDefinition{ 594 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 595 {Name: "Type", Type: "string", Description: flowcontrolv1.PriorityLevelConfigurationSpec{}.SwaggerDoc()["type"]}, 596 {Name: "NominalConcurrencyShares", Type: "string", Description: flowcontrolv1.LimitedPriorityLevelConfiguration{}.SwaggerDoc()["nominalConcurrencyShares"]}, 597 {Name: "Queues", Type: "string", Description: flowcontrolv1.QueuingConfiguration{}.SwaggerDoc()["queues"]}, 598 {Name: "HandSize", Type: "string", Description: flowcontrolv1.QueuingConfiguration{}.SwaggerDoc()["handSize"]}, 599 {Name: "QueueLengthLimit", Type: "string", Description: flowcontrolv1.QueuingConfiguration{}.SwaggerDoc()["queueLengthLimit"]}, 600 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 601 } 602 _ = h.TableHandler(priorityLevelColumnDefinitions, printPriorityLevelConfiguration) 603 _ = h.TableHandler(priorityLevelColumnDefinitions, printPriorityLevelConfigurationList) 604 605 storageVersionColumnDefinitions := []metav1.TableColumnDefinition{ 606 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 607 {Name: "CommonEncodingVersion", Type: "string", Description: apiserverinternalv1alpha1.StorageVersionStatus{}.SwaggerDoc()["commonEncodingVersion"]}, 608 {Name: "StorageVersions", Type: "string", Description: apiserverinternalv1alpha1.StorageVersionStatus{}.SwaggerDoc()["storageVersions"]}, 609 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 610 } 611 _ = h.TableHandler(storageVersionColumnDefinitions, printStorageVersion) 612 _ = h.TableHandler(storageVersionColumnDefinitions, printStorageVersionList) 613 614 scaleColumnDefinitions := []metav1.TableColumnDefinition{ 615 {Name: "Name", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 616 {Name: "Desired", Type: "integer", Description: autoscalingv1.ScaleSpec{}.SwaggerDoc()["replicas"]}, 617 {Name: "Available", Type: "integer", Description: autoscalingv1.ScaleStatus{}.SwaggerDoc()["replicas"]}, 618 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 619 } 620 _ = h.TableHandler(scaleColumnDefinitions, printScale) 621 622 resourceClassColumnDefinitions := []metav1.TableColumnDefinition{ 623 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 624 {Name: "DriverName", Type: "string", Description: resourcev1alpha2.ResourceClass{}.SwaggerDoc()["driverName"]}, 625 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 626 } 627 _ = h.TableHandler(resourceClassColumnDefinitions, printResourceClass) 628 _ = h.TableHandler(resourceClassColumnDefinitions, printResourceClassList) 629 630 resourceClaimColumnDefinitions := []metav1.TableColumnDefinition{ 631 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 632 {Name: "ResourceClassName", Type: "string", Description: resourcev1alpha2.ResourceClaimSpec{}.SwaggerDoc()["resourceClassName"]}, 633 {Name: "AllocationMode", Type: "string", Description: resourcev1alpha2.ResourceClaimSpec{}.SwaggerDoc()["allocationMode"]}, 634 {Name: "State", Type: "string", Description: "A summary of the current state (allocated, pending, reserved, etc.)."}, 635 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 636 } 637 _ = h.TableHandler(resourceClaimColumnDefinitions, printResourceClaim) 638 _ = h.TableHandler(resourceClaimColumnDefinitions, printResourceClaimList) 639 640 resourceClaimTemplateColumnDefinitions := []metav1.TableColumnDefinition{ 641 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 642 {Name: "ResourceClassName", Type: "string", Description: resourcev1alpha2.ResourceClaimSpec{}.SwaggerDoc()["resourceClassName"]}, 643 {Name: "AllocationMode", Type: "string", Description: resourcev1alpha2.ResourceClaimSpec{}.SwaggerDoc()["allocationMode"]}, 644 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 645 } 646 _ = h.TableHandler(resourceClaimTemplateColumnDefinitions, printResourceClaimTemplate) 647 _ = h.TableHandler(resourceClaimTemplateColumnDefinitions, printResourceClaimTemplateList) 648 649 podSchedulingCtxColumnDefinitions := []metav1.TableColumnDefinition{ 650 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 651 {Name: "SelectedNode", Type: "string", Description: resourcev1alpha2.PodSchedulingContextSpec{}.SwaggerDoc()["selectedNode"]}, 652 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 653 } 654 _ = h.TableHandler(podSchedulingCtxColumnDefinitions, printPodSchedulingContext) 655 _ = h.TableHandler(podSchedulingCtxColumnDefinitions, printPodSchedulingContextList) 656 657 serviceCIDRColumnDefinitions := []metav1.TableColumnDefinition{ 658 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 659 {Name: "CIDRs", Type: "string", Description: networkingv1alpha1.ServiceCIDRSpec{}.SwaggerDoc()["cidrs"]}, 660 {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, 661 } 662 663 _ = h.TableHandler(serviceCIDRColumnDefinitions, printServiceCIDR) 664 _ = h.TableHandler(serviceCIDRColumnDefinitions, printServiceCIDRList) 665 666 ipAddressColumnDefinitions := []metav1.TableColumnDefinition{ 667 {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, 668 {Name: "ParentRef", Type: "string", Description: networkingv1alpha1.IPAddressSpec{}.SwaggerDoc()["parentRef"]}, 669 } 670 671 _ = h.TableHandler(ipAddressColumnDefinitions, printIPAddress) 672 _ = h.TableHandler(ipAddressColumnDefinitions, printIPAddressList) 673 } 674 675 // Pass ports=nil for all ports. 676 func formatEndpoints(endpoints *api.Endpoints, ports sets.String) string { 677 if len(endpoints.Subsets) == 0 { 678 return "<none>" 679 } 680 list := []string{} 681 max := 3 682 more := false 683 count := 0 684 for i := range endpoints.Subsets { 685 ss := &endpoints.Subsets[i] 686 if len(ss.Ports) == 0 { 687 // It's possible to have headless services with no ports. 688 count += len(ss.Addresses) 689 for i := range ss.Addresses { 690 if len(list) == max { 691 more = true 692 // the next loop is redundant 693 break 694 } 695 list = append(list, ss.Addresses[i].IP) 696 } 697 // avoid nesting code too deeply 698 continue 699 } 700 701 // "Normal" services with ports defined. 702 for i := range ss.Ports { 703 port := &ss.Ports[i] 704 if ports == nil || ports.Has(port.Name) { 705 count += len(ss.Addresses) 706 for i := range ss.Addresses { 707 if len(list) == max { 708 more = true 709 // the next loop is redundant 710 break 711 } 712 addr := &ss.Addresses[i] 713 hostPort := net.JoinHostPort(addr.IP, strconv.Itoa(int(port.Port))) 714 list = append(list, hostPort) 715 } 716 } 717 } 718 } 719 720 ret := strings.Join(list, ",") 721 if more { 722 return fmt.Sprintf("%s + %d more...", ret, count-max) 723 } 724 return ret 725 } 726 727 func formatDiscoveryPorts(ports []discovery.EndpointPort) string { 728 list := []string{} 729 max := 3 730 more := false 731 count := 0 732 for _, port := range ports { 733 if len(list) < max { 734 portNum := "*" 735 if port.Port != nil { 736 portNum = strconv.Itoa(int(*port.Port)) 737 } else if port.Name != nil { 738 portNum = *port.Name 739 } 740 list = append(list, portNum) 741 } else if len(list) == max { 742 more = true 743 } 744 count++ 745 } 746 return listWithMoreString(list, more, count, max) 747 } 748 749 func formatDiscoveryEndpoints(endpoints []discovery.Endpoint) string { 750 list := []string{} 751 max := 3 752 more := false 753 count := 0 754 for _, endpoint := range endpoints { 755 for _, address := range endpoint.Addresses { 756 if len(list) < max { 757 list = append(list, address) 758 } else if len(list) == max { 759 more = true 760 } 761 count++ 762 } 763 } 764 return listWithMoreString(list, more, count, max) 765 } 766 767 func listWithMoreString(list []string, more bool, count, max int) string { 768 ret := strings.Join(list, ",") 769 if more { 770 return fmt.Sprintf("%s + %d more...", ret, count-max) 771 } 772 if ret == "" { 773 ret = "<unset>" 774 } 775 return ret 776 } 777 778 // translateMicroTimestampSince returns the elapsed time since timestamp in 779 // human-readable approximation. 780 func translateMicroTimestampSince(timestamp metav1.MicroTime) string { 781 if timestamp.IsZero() { 782 return "<unknown>" 783 } 784 785 return duration.HumanDuration(time.Since(timestamp.Time)) 786 } 787 788 // translateTimestampSince returns the elapsed time since timestamp in 789 // human-readable approximation. 790 func translateTimestampSince(timestamp metav1.Time) string { 791 if timestamp.IsZero() { 792 return "<unknown>" 793 } 794 795 return duration.HumanDuration(time.Since(timestamp.Time)) 796 } 797 798 // translateTimestampUntil returns the elapsed time until timestamp in 799 // human-readable approximation. 800 func translateTimestampUntil(timestamp metav1.Time) string { 801 if timestamp.IsZero() { 802 return "<unknown>" 803 } 804 805 return duration.HumanDuration(time.Until(timestamp.Time)) 806 } 807 808 var ( 809 podSuccessConditions = []metav1.TableRowCondition{{Type: metav1.RowCompleted, Status: metav1.ConditionTrue, Reason: string(api.PodSucceeded), Message: "The pod has completed successfully."}} 810 podFailedConditions = []metav1.TableRowCondition{{Type: metav1.RowCompleted, Status: metav1.ConditionTrue, Reason: string(api.PodFailed), Message: "The pod failed."}} 811 ) 812 813 func printPodList(podList *api.PodList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 814 rows := make([]metav1.TableRow, 0, len(podList.Items)) 815 for i := range podList.Items { 816 r, err := printPod(&podList.Items[i], options) 817 if err != nil { 818 return nil, err 819 } 820 rows = append(rows, r...) 821 } 822 return rows, nil 823 } 824 825 func printPod(pod *api.Pod, options printers.GenerateOptions) ([]metav1.TableRow, error) { 826 restarts := 0 827 restartableInitContainerRestarts := 0 828 totalContainers := len(pod.Spec.Containers) 829 readyContainers := 0 830 lastRestartDate := metav1.NewTime(time.Time{}) 831 lastRestartableInitContainerRestartDate := metav1.NewTime(time.Time{}) 832 833 reason := string(pod.Status.Phase) 834 if pod.Status.Reason != "" { 835 reason = pod.Status.Reason 836 } 837 838 // If the Pod carries {type:PodScheduled, reason:WaitingForGates}, set reason to 'SchedulingGated'. 839 for _, condition := range pod.Status.Conditions { 840 if condition.Type == api.PodScheduled && condition.Reason == apiv1.PodReasonSchedulingGated { 841 reason = apiv1.PodReasonSchedulingGated 842 } 843 } 844 845 row := metav1.TableRow{ 846 Object: runtime.RawExtension{Object: pod}, 847 } 848 849 switch pod.Status.Phase { 850 case api.PodSucceeded: 851 row.Conditions = podSuccessConditions 852 case api.PodFailed: 853 row.Conditions = podFailedConditions 854 } 855 856 initContainers := make(map[string]*api.Container) 857 for i := range pod.Spec.InitContainers { 858 initContainers[pod.Spec.InitContainers[i].Name] = &pod.Spec.InitContainers[i] 859 if isRestartableInitContainer(&pod.Spec.InitContainers[i]) { 860 totalContainers++ 861 } 862 } 863 864 initializing := false 865 for i := range pod.Status.InitContainerStatuses { 866 container := pod.Status.InitContainerStatuses[i] 867 restarts += int(container.RestartCount) 868 if container.LastTerminationState.Terminated != nil { 869 terminatedDate := container.LastTerminationState.Terminated.FinishedAt 870 if lastRestartDate.Before(&terminatedDate) { 871 lastRestartDate = terminatedDate 872 } 873 } 874 if isRestartableInitContainer(initContainers[container.Name]) { 875 restartableInitContainerRestarts += int(container.RestartCount) 876 if container.LastTerminationState.Terminated != nil { 877 terminatedDate := container.LastTerminationState.Terminated.FinishedAt 878 if lastRestartableInitContainerRestartDate.Before(&terminatedDate) { 879 lastRestartableInitContainerRestartDate = terminatedDate 880 } 881 } 882 } 883 switch { 884 case container.State.Terminated != nil && container.State.Terminated.ExitCode == 0: 885 continue 886 case isRestartableInitContainer(initContainers[container.Name]) && 887 container.Started != nil && *container.Started: 888 if container.Ready { 889 readyContainers++ 890 } 891 continue 892 case container.State.Terminated != nil: 893 // initialization is failed 894 if len(container.State.Terminated.Reason) == 0 { 895 if container.State.Terminated.Signal != 0 { 896 reason = fmt.Sprintf("Init:Signal:%d", container.State.Terminated.Signal) 897 } else { 898 reason = fmt.Sprintf("Init:ExitCode:%d", container.State.Terminated.ExitCode) 899 } 900 } else { 901 reason = "Init:" + container.State.Terminated.Reason 902 } 903 initializing = true 904 case container.State.Waiting != nil && len(container.State.Waiting.Reason) > 0 && container.State.Waiting.Reason != "PodInitializing": 905 reason = "Init:" + container.State.Waiting.Reason 906 initializing = true 907 default: 908 reason = fmt.Sprintf("Init:%d/%d", i, len(pod.Spec.InitContainers)) 909 initializing = true 910 } 911 break 912 } 913 914 if !initializing || isPodInitializedConditionTrue(&pod.Status) { 915 restarts = restartableInitContainerRestarts 916 lastRestartDate = lastRestartableInitContainerRestartDate 917 hasRunning := false 918 for i := len(pod.Status.ContainerStatuses) - 1; i >= 0; i-- { 919 container := pod.Status.ContainerStatuses[i] 920 921 restarts += int(container.RestartCount) 922 if container.LastTerminationState.Terminated != nil { 923 terminatedDate := container.LastTerminationState.Terminated.FinishedAt 924 if lastRestartDate.Before(&terminatedDate) { 925 lastRestartDate = terminatedDate 926 } 927 } 928 if container.State.Waiting != nil && container.State.Waiting.Reason != "" { 929 reason = container.State.Waiting.Reason 930 } else if container.State.Terminated != nil && container.State.Terminated.Reason != "" { 931 reason = container.State.Terminated.Reason 932 } else if container.State.Terminated != nil && container.State.Terminated.Reason == "" { 933 if container.State.Terminated.Signal != 0 { 934 reason = fmt.Sprintf("Signal:%d", container.State.Terminated.Signal) 935 } else { 936 reason = fmt.Sprintf("ExitCode:%d", container.State.Terminated.ExitCode) 937 } 938 } else if container.Ready && container.State.Running != nil { 939 hasRunning = true 940 readyContainers++ 941 } 942 } 943 944 // change pod status back to "Running" if there is at least one container still reporting as "Running" status 945 if reason == "Completed" && hasRunning { 946 if hasPodReadyCondition(pod.Status.Conditions) { 947 reason = "Running" 948 } else { 949 reason = "NotReady" 950 } 951 } 952 } 953 954 if pod.DeletionTimestamp != nil && pod.Status.Reason == node.NodeUnreachablePodReason { 955 reason = "Unknown" 956 } else if pod.DeletionTimestamp != nil { 957 reason = "Terminating" 958 } 959 960 restartsStr := strconv.Itoa(restarts) 961 if restarts != 0 && !lastRestartDate.IsZero() { 962 restartsStr = fmt.Sprintf("%d (%s ago)", restarts, translateTimestampSince(lastRestartDate)) 963 } 964 965 row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, restartsStr, translateTimestampSince(pod.CreationTimestamp)) 966 if options.Wide { 967 nodeName := pod.Spec.NodeName 968 nominatedNodeName := pod.Status.NominatedNodeName 969 podIP := "" 970 if len(pod.Status.PodIPs) > 0 { 971 podIP = pod.Status.PodIPs[0].IP 972 } 973 974 if podIP == "" { 975 podIP = "<none>" 976 } 977 if nodeName == "" { 978 nodeName = "<none>" 979 } 980 if nominatedNodeName == "" { 981 nominatedNodeName = "<none>" 982 } 983 984 readinessGates := "<none>" 985 if len(pod.Spec.ReadinessGates) > 0 { 986 trueConditions := 0 987 for _, readinessGate := range pod.Spec.ReadinessGates { 988 conditionType := readinessGate.ConditionType 989 for _, condition := range pod.Status.Conditions { 990 if condition.Type == conditionType { 991 if condition.Status == api.ConditionTrue { 992 trueConditions++ 993 } 994 break 995 } 996 } 997 } 998 readinessGates = fmt.Sprintf("%d/%d", trueConditions, len(pod.Spec.ReadinessGates)) 999 } 1000 row.Cells = append(row.Cells, podIP, nodeName, nominatedNodeName, readinessGates) 1001 } 1002 1003 return []metav1.TableRow{row}, nil 1004 } 1005 1006 func hasPodReadyCondition(conditions []api.PodCondition) bool { 1007 for _, condition := range conditions { 1008 if condition.Type == api.PodReady && condition.Status == api.ConditionTrue { 1009 return true 1010 } 1011 } 1012 return false 1013 } 1014 1015 func printPodTemplate(obj *api.PodTemplate, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1016 row := metav1.TableRow{ 1017 Object: runtime.RawExtension{Object: obj}, 1018 } 1019 names, images := layoutContainerCells(obj.Template.Spec.Containers) 1020 row.Cells = append(row.Cells, obj.Name, names, images, labels.FormatLabels(obj.Template.Labels)) 1021 return []metav1.TableRow{row}, nil 1022 } 1023 1024 func printPodTemplateList(list *api.PodTemplateList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1025 rows := make([]metav1.TableRow, 0, len(list.Items)) 1026 for i := range list.Items { 1027 r, err := printPodTemplate(&list.Items[i], options) 1028 if err != nil { 1029 return nil, err 1030 } 1031 rows = append(rows, r...) 1032 } 1033 return rows, nil 1034 } 1035 1036 func printPodDisruptionBudget(obj *policy.PodDisruptionBudget, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1037 row := metav1.TableRow{ 1038 Object: runtime.RawExtension{Object: obj}, 1039 } 1040 1041 var minAvailable string 1042 var maxUnavailable string 1043 if obj.Spec.MinAvailable != nil { 1044 minAvailable = obj.Spec.MinAvailable.String() 1045 } else { 1046 minAvailable = "N/A" 1047 } 1048 1049 if obj.Spec.MaxUnavailable != nil { 1050 maxUnavailable = obj.Spec.MaxUnavailable.String() 1051 } else { 1052 maxUnavailable = "N/A" 1053 } 1054 1055 row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, int64(obj.Status.DisruptionsAllowed), translateTimestampSince(obj.CreationTimestamp)) 1056 return []metav1.TableRow{row}, nil 1057 } 1058 1059 func printPodDisruptionBudgetList(list *policy.PodDisruptionBudgetList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1060 rows := make([]metav1.TableRow, 0, len(list.Items)) 1061 for i := range list.Items { 1062 r, err := printPodDisruptionBudget(&list.Items[i], options) 1063 if err != nil { 1064 return nil, err 1065 } 1066 rows = append(rows, r...) 1067 } 1068 return rows, nil 1069 } 1070 1071 // TODO(AdoHe): try to put wide output in a single method 1072 func printReplicationController(obj *api.ReplicationController, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1073 row := metav1.TableRow{ 1074 Object: runtime.RawExtension{Object: obj}, 1075 } 1076 1077 desiredReplicas := obj.Spec.Replicas 1078 currentReplicas := obj.Status.Replicas 1079 readyReplicas := obj.Status.ReadyReplicas 1080 1081 row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestampSince(obj.CreationTimestamp)) 1082 if options.Wide { 1083 names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) 1084 row.Cells = append(row.Cells, names, images, labels.FormatLabels(obj.Spec.Selector)) 1085 } 1086 return []metav1.TableRow{row}, nil 1087 } 1088 1089 func printReplicationControllerList(list *api.ReplicationControllerList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1090 rows := make([]metav1.TableRow, 0, len(list.Items)) 1091 for i := range list.Items { 1092 r, err := printReplicationController(&list.Items[i], options) 1093 if err != nil { 1094 return nil, err 1095 } 1096 rows = append(rows, r...) 1097 } 1098 return rows, nil 1099 } 1100 1101 func printReplicaSet(obj *apps.ReplicaSet, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1102 row := metav1.TableRow{ 1103 Object: runtime.RawExtension{Object: obj}, 1104 } 1105 1106 desiredReplicas := obj.Spec.Replicas 1107 currentReplicas := obj.Status.Replicas 1108 readyReplicas := obj.Status.ReadyReplicas 1109 1110 row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestampSince(obj.CreationTimestamp)) 1111 if options.Wide { 1112 names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) 1113 row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) 1114 } 1115 return []metav1.TableRow{row}, nil 1116 } 1117 1118 func printReplicaSetList(list *apps.ReplicaSetList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1119 rows := make([]metav1.TableRow, 0, len(list.Items)) 1120 for i := range list.Items { 1121 r, err := printReplicaSet(&list.Items[i], options) 1122 if err != nil { 1123 return nil, err 1124 } 1125 rows = append(rows, r...) 1126 } 1127 return rows, nil 1128 } 1129 1130 func printJob(obj *batch.Job, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1131 row := metav1.TableRow{ 1132 Object: runtime.RawExtension{Object: obj}, 1133 } 1134 1135 var completions string 1136 if obj.Spec.Completions != nil { 1137 completions = fmt.Sprintf("%d/%d", obj.Status.Succeeded, *obj.Spec.Completions) 1138 } else { 1139 parallelism := int32(0) 1140 if obj.Spec.Parallelism != nil { 1141 parallelism = *obj.Spec.Parallelism 1142 } 1143 if parallelism > 1 { 1144 completions = fmt.Sprintf("%d/1 of %d", obj.Status.Succeeded, parallelism) 1145 } else { 1146 completions = fmt.Sprintf("%d/1", obj.Status.Succeeded) 1147 } 1148 } 1149 var jobDuration string 1150 switch { 1151 case obj.Status.StartTime == nil: 1152 case obj.Status.CompletionTime == nil: 1153 jobDuration = duration.HumanDuration(time.Since(obj.Status.StartTime.Time)) 1154 default: 1155 jobDuration = duration.HumanDuration(obj.Status.CompletionTime.Sub(obj.Status.StartTime.Time)) 1156 } 1157 1158 row.Cells = append(row.Cells, obj.Name, completions, jobDuration, translateTimestampSince(obj.CreationTimestamp)) 1159 if options.Wide { 1160 names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) 1161 row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) 1162 } 1163 return []metav1.TableRow{row}, nil 1164 } 1165 1166 func printJobList(list *batch.JobList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1167 rows := make([]metav1.TableRow, 0, len(list.Items)) 1168 for i := range list.Items { 1169 r, err := printJob(&list.Items[i], options) 1170 if err != nil { 1171 return nil, err 1172 } 1173 rows = append(rows, r...) 1174 } 1175 return rows, nil 1176 } 1177 1178 func printCronJob(obj *batch.CronJob, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1179 row := metav1.TableRow{ 1180 Object: runtime.RawExtension{Object: obj}, 1181 } 1182 1183 lastScheduleTime := "<none>" 1184 if obj.Status.LastScheduleTime != nil { 1185 lastScheduleTime = translateTimestampSince(*obj.Status.LastScheduleTime) 1186 } 1187 1188 row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), int64(len(obj.Status.Active)), lastScheduleTime, translateTimestampSince(obj.CreationTimestamp)) 1189 if options.Wide { 1190 names, images := layoutContainerCells(obj.Spec.JobTemplate.Spec.Template.Spec.Containers) 1191 row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.JobTemplate.Spec.Selector)) 1192 } 1193 return []metav1.TableRow{row}, nil 1194 } 1195 1196 func printCronJobList(list *batch.CronJobList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1197 rows := make([]metav1.TableRow, 0, len(list.Items)) 1198 for i := range list.Items { 1199 r, err := printCronJob(&list.Items[i], options) 1200 if err != nil { 1201 return nil, err 1202 } 1203 rows = append(rows, r...) 1204 } 1205 return rows, nil 1206 } 1207 1208 // loadBalancerStatusStringer behaves mostly like a string interface and converts the given status to a string. 1209 // `wide` indicates whether the returned value is meant for --o=wide output. If not, it's clipped to 16 bytes. 1210 func loadBalancerStatusStringer(s api.LoadBalancerStatus, wide bool) string { 1211 ingress := s.Ingress 1212 result := sets.NewString() 1213 for i := range ingress { 1214 if ingress[i].IP != "" { 1215 result.Insert(ingress[i].IP) 1216 } else if ingress[i].Hostname != "" { 1217 result.Insert(ingress[i].Hostname) 1218 } 1219 } 1220 1221 r := strings.Join(result.List(), ",") 1222 if !wide && len(r) > loadBalancerWidth { 1223 r = r[0:(loadBalancerWidth-3)] + "..." 1224 } 1225 return r 1226 } 1227 1228 func getServiceExternalIP(svc *api.Service, wide bool) string { 1229 switch svc.Spec.Type { 1230 case api.ServiceTypeClusterIP: 1231 if len(svc.Spec.ExternalIPs) > 0 { 1232 return strings.Join(svc.Spec.ExternalIPs, ",") 1233 } 1234 return "<none>" 1235 case api.ServiceTypeNodePort: 1236 if len(svc.Spec.ExternalIPs) > 0 { 1237 return strings.Join(svc.Spec.ExternalIPs, ",") 1238 } 1239 return "<none>" 1240 case api.ServiceTypeLoadBalancer: 1241 lbIps := loadBalancerStatusStringer(svc.Status.LoadBalancer, wide) 1242 if len(svc.Spec.ExternalIPs) > 0 { 1243 results := []string{} 1244 if len(lbIps) > 0 { 1245 results = append(results, strings.Split(lbIps, ",")...) 1246 } 1247 results = append(results, svc.Spec.ExternalIPs...) 1248 return strings.Join(results, ",") 1249 } 1250 if len(lbIps) > 0 { 1251 return lbIps 1252 } 1253 return "<pending>" 1254 case api.ServiceTypeExternalName: 1255 return svc.Spec.ExternalName 1256 } 1257 return "<unknown>" 1258 } 1259 1260 func makePortString(ports []api.ServicePort) string { 1261 pieces := make([]string, len(ports)) 1262 for ix := range ports { 1263 port := &ports[ix] 1264 pieces[ix] = fmt.Sprintf("%d/%s", port.Port, port.Protocol) 1265 if port.NodePort > 0 { 1266 pieces[ix] = fmt.Sprintf("%d:%d/%s", port.Port, port.NodePort, port.Protocol) 1267 } 1268 } 1269 return strings.Join(pieces, ",") 1270 } 1271 1272 func printService(obj *api.Service, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1273 row := metav1.TableRow{ 1274 Object: runtime.RawExtension{Object: obj}, 1275 } 1276 svcType := obj.Spec.Type 1277 internalIP := "<none>" 1278 if len(obj.Spec.ClusterIPs) > 0 { 1279 internalIP = obj.Spec.ClusterIPs[0] 1280 } 1281 1282 externalIP := getServiceExternalIP(obj, options.Wide) 1283 svcPorts := makePortString(obj.Spec.Ports) 1284 if len(svcPorts) == 0 { 1285 svcPorts = "<none>" 1286 } 1287 1288 row.Cells = append(row.Cells, obj.Name, string(svcType), internalIP, externalIP, svcPorts, translateTimestampSince(obj.CreationTimestamp)) 1289 if options.Wide { 1290 row.Cells = append(row.Cells, labels.FormatLabels(obj.Spec.Selector)) 1291 } 1292 1293 return []metav1.TableRow{row}, nil 1294 } 1295 1296 func printServiceList(list *api.ServiceList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1297 rows := make([]metav1.TableRow, 0, len(list.Items)) 1298 for i := range list.Items { 1299 r, err := printService(&list.Items[i], options) 1300 if err != nil { 1301 return nil, err 1302 } 1303 rows = append(rows, r...) 1304 } 1305 return rows, nil 1306 } 1307 1308 func formatHosts(rules []networking.IngressRule) string { 1309 list := []string{} 1310 max := 3 1311 more := false 1312 for _, rule := range rules { 1313 if len(list) == max { 1314 more = true 1315 } 1316 if !more && len(rule.Host) != 0 { 1317 list = append(list, rule.Host) 1318 } 1319 } 1320 if len(list) == 0 { 1321 return "*" 1322 } 1323 ret := strings.Join(list, ",") 1324 if more { 1325 return fmt.Sprintf("%s + %d more...", ret, len(rules)-max) 1326 } 1327 return ret 1328 } 1329 1330 func formatPorts(tls []networking.IngressTLS) string { 1331 if len(tls) != 0 { 1332 return "80, 443" 1333 } 1334 return "80" 1335 } 1336 1337 func printIngress(obj *networking.Ingress, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1338 row := metav1.TableRow{ 1339 Object: runtime.RawExtension{Object: obj}, 1340 } 1341 className := "<none>" 1342 if obj.Spec.IngressClassName != nil { 1343 className = *obj.Spec.IngressClassName 1344 } 1345 hosts := formatHosts(obj.Spec.Rules) 1346 address := ingressLoadBalancerStatusStringer(obj.Status.LoadBalancer, options.Wide) 1347 ports := formatPorts(obj.Spec.TLS) 1348 createTime := translateTimestampSince(obj.CreationTimestamp) 1349 row.Cells = append(row.Cells, obj.Name, className, hosts, address, ports, createTime) 1350 return []metav1.TableRow{row}, nil 1351 } 1352 1353 // ingressLoadBalancerStatusStringer behaves mostly like a string interface and converts the given status to a string. 1354 // `wide` indicates whether the returned value is meant for --o=wide output. If not, it's clipped to 16 bytes. 1355 func ingressLoadBalancerStatusStringer(s networking.IngressLoadBalancerStatus, wide bool) string { 1356 ingress := s.Ingress 1357 result := sets.NewString() 1358 for i := range ingress { 1359 if ingress[i].IP != "" { 1360 result.Insert(ingress[i].IP) 1361 } else if ingress[i].Hostname != "" { 1362 result.Insert(ingress[i].Hostname) 1363 } 1364 } 1365 1366 r := strings.Join(result.List(), ",") 1367 if !wide && len(r) > loadBalancerWidth { 1368 r = r[0:(loadBalancerWidth-3)] + "..." 1369 } 1370 return r 1371 } 1372 1373 func printIngressList(list *networking.IngressList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1374 rows := make([]metav1.TableRow, 0, len(list.Items)) 1375 for i := range list.Items { 1376 r, err := printIngress(&list.Items[i], options) 1377 if err != nil { 1378 return nil, err 1379 } 1380 rows = append(rows, r...) 1381 } 1382 return rows, nil 1383 } 1384 1385 func printIngressClass(obj *networking.IngressClass, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1386 row := metav1.TableRow{ 1387 Object: runtime.RawExtension{Object: obj}, 1388 } 1389 parameters := "<none>" 1390 if obj.Spec.Parameters != nil { 1391 parameters = obj.Spec.Parameters.Kind 1392 if obj.Spec.Parameters.APIGroup != nil { 1393 parameters = parameters + "." + *obj.Spec.Parameters.APIGroup 1394 } 1395 parameters = parameters + "/" + obj.Spec.Parameters.Name 1396 } 1397 createTime := translateTimestampSince(obj.CreationTimestamp) 1398 row.Cells = append(row.Cells, obj.Name, obj.Spec.Controller, parameters, createTime) 1399 return []metav1.TableRow{row}, nil 1400 } 1401 1402 func printIngressClassList(list *networking.IngressClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1403 rows := make([]metav1.TableRow, 0, len(list.Items)) 1404 for i := range list.Items { 1405 r, err := printIngressClass(&list.Items[i], options) 1406 if err != nil { 1407 return nil, err 1408 } 1409 rows = append(rows, r...) 1410 } 1411 return rows, nil 1412 } 1413 1414 func printStatefulSet(obj *apps.StatefulSet, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1415 row := metav1.TableRow{ 1416 Object: runtime.RawExtension{Object: obj}, 1417 } 1418 desiredReplicas := obj.Spec.Replicas 1419 readyReplicas := obj.Status.ReadyReplicas 1420 createTime := translateTimestampSince(obj.CreationTimestamp) 1421 row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%d/%d", int64(readyReplicas), int64(desiredReplicas)), createTime) 1422 if options.Wide { 1423 names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) 1424 row.Cells = append(row.Cells, names, images) 1425 } 1426 return []metav1.TableRow{row}, nil 1427 } 1428 1429 func printStatefulSetList(list *apps.StatefulSetList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1430 rows := make([]metav1.TableRow, 0, len(list.Items)) 1431 for i := range list.Items { 1432 r, err := printStatefulSet(&list.Items[i], options) 1433 if err != nil { 1434 return nil, err 1435 } 1436 rows = append(rows, r...) 1437 } 1438 return rows, nil 1439 } 1440 1441 func printDaemonSet(obj *apps.DaemonSet, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1442 row := metav1.TableRow{ 1443 Object: runtime.RawExtension{Object: obj}, 1444 } 1445 1446 desiredScheduled := obj.Status.DesiredNumberScheduled 1447 currentScheduled := obj.Status.CurrentNumberScheduled 1448 numberReady := obj.Status.NumberReady 1449 numberUpdated := obj.Status.UpdatedNumberScheduled 1450 numberAvailable := obj.Status.NumberAvailable 1451 1452 row.Cells = append(row.Cells, obj.Name, int64(desiredScheduled), int64(currentScheduled), int64(numberReady), int64(numberUpdated), int64(numberAvailable), labels.FormatLabels(obj.Spec.Template.Spec.NodeSelector), translateTimestampSince(obj.CreationTimestamp)) 1453 if options.Wide { 1454 names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) 1455 row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) 1456 } 1457 return []metav1.TableRow{row}, nil 1458 } 1459 1460 func printDaemonSetList(list *apps.DaemonSetList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1461 rows := make([]metav1.TableRow, 0, len(list.Items)) 1462 for i := range list.Items { 1463 r, err := printDaemonSet(&list.Items[i], options) 1464 if err != nil { 1465 return nil, err 1466 } 1467 rows = append(rows, r...) 1468 } 1469 return rows, nil 1470 } 1471 1472 func printEndpoints(obj *api.Endpoints, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1473 row := metav1.TableRow{ 1474 Object: runtime.RawExtension{Object: obj}, 1475 } 1476 row.Cells = append(row.Cells, obj.Name, formatEndpoints(obj, nil), translateTimestampSince(obj.CreationTimestamp)) 1477 return []metav1.TableRow{row}, nil 1478 } 1479 1480 func printEndpointsList(list *api.EndpointsList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1481 rows := make([]metav1.TableRow, 0, len(list.Items)) 1482 for i := range list.Items { 1483 r, err := printEndpoints(&list.Items[i], options) 1484 if err != nil { 1485 return nil, err 1486 } 1487 rows = append(rows, r...) 1488 } 1489 return rows, nil 1490 } 1491 1492 func printEndpointSlice(obj *discovery.EndpointSlice, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1493 row := metav1.TableRow{ 1494 Object: runtime.RawExtension{Object: obj}, 1495 } 1496 row.Cells = append(row.Cells, obj.Name, string(obj.AddressType), formatDiscoveryPorts(obj.Ports), formatDiscoveryEndpoints(obj.Endpoints), translateTimestampSince(obj.CreationTimestamp)) 1497 return []metav1.TableRow{row}, nil 1498 } 1499 1500 func printEndpointSliceList(list *discovery.EndpointSliceList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1501 rows := make([]metav1.TableRow, 0, len(list.Items)) 1502 for i := range list.Items { 1503 r, err := printEndpointSlice(&list.Items[i], options) 1504 if err != nil { 1505 return nil, err 1506 } 1507 rows = append(rows, r...) 1508 } 1509 return rows, nil 1510 } 1511 1512 func printCSINode(obj *storage.CSINode, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1513 row := metav1.TableRow{ 1514 Object: runtime.RawExtension{Object: obj}, 1515 } 1516 row.Cells = append(row.Cells, obj.Name, int64(len(obj.Spec.Drivers)), translateTimestampSince(obj.CreationTimestamp)) 1517 return []metav1.TableRow{row}, nil 1518 } 1519 1520 func printCSINodeList(list *storage.CSINodeList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1521 rows := make([]metav1.TableRow, 0, len(list.Items)) 1522 for i := range list.Items { 1523 r, err := printCSINode(&list.Items[i], options) 1524 if err != nil { 1525 return nil, err 1526 } 1527 rows = append(rows, r...) 1528 } 1529 return rows, nil 1530 } 1531 1532 func printCSIDriver(obj *storage.CSIDriver, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1533 row := metav1.TableRow{ 1534 Object: runtime.RawExtension{Object: obj}, 1535 } 1536 attachRequired := true 1537 if obj.Spec.AttachRequired != nil { 1538 attachRequired = *obj.Spec.AttachRequired 1539 } 1540 podInfoOnMount := false 1541 if obj.Spec.PodInfoOnMount != nil { 1542 podInfoOnMount = *obj.Spec.PodInfoOnMount 1543 } 1544 allModes := []string{} 1545 for _, mode := range obj.Spec.VolumeLifecycleModes { 1546 allModes = append(allModes, string(mode)) 1547 } 1548 modes := strings.Join(allModes, ",") 1549 if len(modes) == 0 { 1550 modes = "<none>" 1551 } 1552 1553 row.Cells = append(row.Cells, obj.Name, attachRequired, podInfoOnMount) 1554 storageCapacity := false 1555 if obj.Spec.StorageCapacity != nil { 1556 storageCapacity = *obj.Spec.StorageCapacity 1557 } 1558 row.Cells = append(row.Cells, storageCapacity) 1559 1560 tokenRequests := "<unset>" 1561 if obj.Spec.TokenRequests != nil { 1562 audiences := []string{} 1563 for _, t := range obj.Spec.TokenRequests { 1564 audiences = append(audiences, t.Audience) 1565 } 1566 tokenRequests = strings.Join(audiences, ",") 1567 } 1568 requiresRepublish := false 1569 if obj.Spec.RequiresRepublish != nil { 1570 requiresRepublish = *obj.Spec.RequiresRepublish 1571 } 1572 row.Cells = append(row.Cells, tokenRequests, requiresRepublish) 1573 1574 row.Cells = append(row.Cells, modes, translateTimestampSince(obj.CreationTimestamp)) 1575 return []metav1.TableRow{row}, nil 1576 } 1577 1578 func printCSIDriverList(list *storage.CSIDriverList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1579 rows := make([]metav1.TableRow, 0, len(list.Items)) 1580 for i := range list.Items { 1581 r, err := printCSIDriver(&list.Items[i], options) 1582 if err != nil { 1583 return nil, err 1584 } 1585 rows = append(rows, r...) 1586 } 1587 return rows, nil 1588 } 1589 1590 func printCSIStorageCapacity(obj *storage.CSIStorageCapacity, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1591 row := metav1.TableRow{ 1592 Object: runtime.RawExtension{Object: obj}, 1593 } 1594 1595 capacity := "<unset>" 1596 if obj.Capacity != nil { 1597 capacity = obj.Capacity.String() 1598 } 1599 1600 row.Cells = append(row.Cells, obj.Name, obj.StorageClassName, capacity) 1601 return []metav1.TableRow{row}, nil 1602 } 1603 1604 func printCSIStorageCapacityList(list *storage.CSIStorageCapacityList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1605 rows := make([]metav1.TableRow, 0, len(list.Items)) 1606 for i := range list.Items { 1607 r, err := printCSIStorageCapacity(&list.Items[i], options) 1608 if err != nil { 1609 return nil, err 1610 } 1611 rows = append(rows, r...) 1612 } 1613 return rows, nil 1614 } 1615 1616 func printMutatingWebhook(obj *admissionregistration.MutatingWebhookConfiguration, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1617 row := metav1.TableRow{ 1618 Object: runtime.RawExtension{Object: obj}, 1619 } 1620 row.Cells = append(row.Cells, obj.Name, int64(len(obj.Webhooks)), translateTimestampSince(obj.CreationTimestamp)) 1621 return []metav1.TableRow{row}, nil 1622 } 1623 1624 func printMutatingWebhookList(list *admissionregistration.MutatingWebhookConfigurationList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1625 rows := make([]metav1.TableRow, 0, len(list.Items)) 1626 for i := range list.Items { 1627 r, err := printMutatingWebhook(&list.Items[i], options) 1628 if err != nil { 1629 return nil, err 1630 } 1631 rows = append(rows, r...) 1632 } 1633 return rows, nil 1634 } 1635 1636 func printValidatingWebhook(obj *admissionregistration.ValidatingWebhookConfiguration, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1637 row := metav1.TableRow{ 1638 Object: runtime.RawExtension{Object: obj}, 1639 } 1640 row.Cells = append(row.Cells, obj.Name, int64(len(obj.Webhooks)), translateTimestampSince(obj.CreationTimestamp)) 1641 return []metav1.TableRow{row}, nil 1642 } 1643 1644 func printValidatingWebhookList(list *admissionregistration.ValidatingWebhookConfigurationList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1645 rows := make([]metav1.TableRow, 0, len(list.Items)) 1646 for i := range list.Items { 1647 r, err := printValidatingWebhook(&list.Items[i], options) 1648 if err != nil { 1649 return nil, err 1650 } 1651 rows = append(rows, r...) 1652 } 1653 return rows, nil 1654 } 1655 1656 func printValidatingAdmissionPolicy(obj *admissionregistration.ValidatingAdmissionPolicy, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1657 row := metav1.TableRow{ 1658 Object: runtime.RawExtension{Object: obj}, 1659 } 1660 paramKind := "<unset>" 1661 if obj.Spec.ParamKind != nil { 1662 paramKind = obj.Spec.ParamKind.APIVersion + "/" + obj.Spec.ParamKind.Kind 1663 } 1664 row.Cells = append(row.Cells, obj.Name, int64(len(obj.Spec.Validations)), paramKind, translateTimestampSince(obj.CreationTimestamp)) 1665 return []metav1.TableRow{row}, nil 1666 } 1667 1668 func printValidatingAdmissionPolicyList(list *admissionregistration.ValidatingAdmissionPolicyList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1669 rows := make([]metav1.TableRow, 0, len(list.Items)) 1670 for i := range list.Items { 1671 r, err := printValidatingAdmissionPolicy(&list.Items[i], options) 1672 if err != nil { 1673 return nil, err 1674 } 1675 rows = append(rows, r...) 1676 } 1677 return rows, nil 1678 } 1679 1680 func printValidatingAdmissionPolicyBinding(obj *admissionregistration.ValidatingAdmissionPolicyBinding, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1681 row := metav1.TableRow{ 1682 Object: runtime.RawExtension{Object: obj}, 1683 } 1684 paramName := "<unset>" 1685 if pr := obj.Spec.ParamRef; pr != nil { 1686 if len(pr.Name) > 0 { 1687 if pr.Namespace != "" { 1688 paramName = pr.Namespace + "/" + pr.Name 1689 } else { 1690 // Can't tell from here if param is cluster-scoped, so all 1691 // params without names get * namespace 1692 paramName = "*/" + pr.Name 1693 } 1694 } else if pr.Selector != nil { 1695 paramName = pr.Selector.String() 1696 } 1697 } 1698 row.Cells = append(row.Cells, obj.Name, obj.Spec.PolicyName, paramName, translateTimestampSince(obj.CreationTimestamp)) 1699 return []metav1.TableRow{row}, nil 1700 } 1701 1702 func printValidatingAdmissionPolicyBindingList(list *admissionregistration.ValidatingAdmissionPolicyBindingList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1703 rows := make([]metav1.TableRow, 0, len(list.Items)) 1704 for i := range list.Items { 1705 r, err := printValidatingAdmissionPolicyBinding(&list.Items[i], options) 1706 if err != nil { 1707 return nil, err 1708 } 1709 rows = append(rows, r...) 1710 } 1711 return rows, nil 1712 } 1713 1714 func printNamespace(obj *api.Namespace, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1715 row := metav1.TableRow{ 1716 Object: runtime.RawExtension{Object: obj}, 1717 } 1718 row.Cells = append(row.Cells, obj.Name, string(obj.Status.Phase), translateTimestampSince(obj.CreationTimestamp)) 1719 return []metav1.TableRow{row}, nil 1720 } 1721 1722 func printNamespaceList(list *api.NamespaceList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1723 rows := make([]metav1.TableRow, 0, len(list.Items)) 1724 for i := range list.Items { 1725 r, err := printNamespace(&list.Items[i], options) 1726 if err != nil { 1727 return nil, err 1728 } 1729 rows = append(rows, r...) 1730 } 1731 return rows, nil 1732 } 1733 1734 func printSecret(obj *api.Secret, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1735 row := metav1.TableRow{ 1736 Object: runtime.RawExtension{Object: obj}, 1737 } 1738 row.Cells = append(row.Cells, obj.Name, string(obj.Type), int64(len(obj.Data)), translateTimestampSince(obj.CreationTimestamp)) 1739 return []metav1.TableRow{row}, nil 1740 } 1741 1742 func printSecretList(list *api.SecretList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1743 rows := make([]metav1.TableRow, 0, len(list.Items)) 1744 for i := range list.Items { 1745 r, err := printSecret(&list.Items[i], options) 1746 if err != nil { 1747 return nil, err 1748 } 1749 rows = append(rows, r...) 1750 } 1751 return rows, nil 1752 } 1753 1754 func printServiceAccount(obj *api.ServiceAccount, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1755 row := metav1.TableRow{ 1756 Object: runtime.RawExtension{Object: obj}, 1757 } 1758 row.Cells = append(row.Cells, obj.Name, int64(len(obj.Secrets)), translateTimestampSince(obj.CreationTimestamp)) 1759 return []metav1.TableRow{row}, nil 1760 } 1761 1762 func printServiceAccountList(list *api.ServiceAccountList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1763 rows := make([]metav1.TableRow, 0, len(list.Items)) 1764 for i := range list.Items { 1765 r, err := printServiceAccount(&list.Items[i], options) 1766 if err != nil { 1767 return nil, err 1768 } 1769 rows = append(rows, r...) 1770 } 1771 return rows, nil 1772 } 1773 1774 func printNode(obj *api.Node, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1775 row := metav1.TableRow{ 1776 Object: runtime.RawExtension{Object: obj}, 1777 } 1778 1779 conditionMap := make(map[api.NodeConditionType]*api.NodeCondition) 1780 NodeAllConditions := []api.NodeConditionType{api.NodeReady} 1781 for i := range obj.Status.Conditions { 1782 cond := obj.Status.Conditions[i] 1783 conditionMap[cond.Type] = &cond 1784 } 1785 var status []string 1786 for _, validCondition := range NodeAllConditions { 1787 if condition, ok := conditionMap[validCondition]; ok { 1788 if condition.Status == api.ConditionTrue { 1789 status = append(status, string(condition.Type)) 1790 } else { 1791 status = append(status, "Not"+string(condition.Type)) 1792 } 1793 } 1794 } 1795 if len(status) == 0 { 1796 status = append(status, "Unknown") 1797 } 1798 if obj.Spec.Unschedulable { 1799 status = append(status, "SchedulingDisabled") 1800 } 1801 1802 roles := strings.Join(findNodeRoles(obj), ",") 1803 if len(roles) == 0 { 1804 roles = "<none>" 1805 } 1806 1807 row.Cells = append(row.Cells, obj.Name, strings.Join(status, ","), roles, translateTimestampSince(obj.CreationTimestamp), obj.Status.NodeInfo.KubeletVersion) 1808 if options.Wide { 1809 osImage, kernelVersion, crVersion := obj.Status.NodeInfo.OSImage, obj.Status.NodeInfo.KernelVersion, obj.Status.NodeInfo.ContainerRuntimeVersion 1810 if osImage == "" { 1811 osImage = "<unknown>" 1812 } 1813 if kernelVersion == "" { 1814 kernelVersion = "<unknown>" 1815 } 1816 if crVersion == "" { 1817 crVersion = "<unknown>" 1818 } 1819 row.Cells = append(row.Cells, getNodeInternalIP(obj), getNodeExternalIP(obj), osImage, kernelVersion, crVersion) 1820 } 1821 1822 return []metav1.TableRow{row}, nil 1823 } 1824 1825 // Returns first external ip of the node or "<none>" if none is found. 1826 func getNodeExternalIP(node *api.Node) string { 1827 for _, address := range node.Status.Addresses { 1828 if address.Type == api.NodeExternalIP { 1829 return address.Address 1830 } 1831 } 1832 1833 return "<none>" 1834 } 1835 1836 // Returns the internal IP of the node or "<none>" if none is found. 1837 func getNodeInternalIP(node *api.Node) string { 1838 for _, address := range node.Status.Addresses { 1839 if address.Type == api.NodeInternalIP { 1840 return address.Address 1841 } 1842 } 1843 1844 return "<none>" 1845 } 1846 1847 // findNodeRoles returns the roles of a given node. 1848 // The roles are determined by looking for: 1849 // * a node-role.kubernetes.io/<role>="" label 1850 // * a kubernetes.io/role="<role>" label 1851 func findNodeRoles(node *api.Node) []string { 1852 roles := sets.NewString() 1853 for k, v := range node.Labels { 1854 switch { 1855 case strings.HasPrefix(k, labelNodeRolePrefix): 1856 if role := strings.TrimPrefix(k, labelNodeRolePrefix); len(role) > 0 { 1857 roles.Insert(role) 1858 } 1859 1860 case k == nodeLabelRole && v != "": 1861 roles.Insert(v) 1862 } 1863 } 1864 return roles.List() 1865 } 1866 1867 func printNodeList(list *api.NodeList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1868 rows := make([]metav1.TableRow, 0, len(list.Items)) 1869 for i := range list.Items { 1870 r, err := printNode(&list.Items[i], options) 1871 if err != nil { 1872 return nil, err 1873 } 1874 rows = append(rows, r...) 1875 } 1876 return rows, nil 1877 } 1878 1879 func printPersistentVolume(obj *api.PersistentVolume, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1880 row := metav1.TableRow{ 1881 Object: runtime.RawExtension{Object: obj}, 1882 } 1883 1884 claimRefUID := "" 1885 if obj.Spec.ClaimRef != nil { 1886 claimRefUID += obj.Spec.ClaimRef.Namespace 1887 claimRefUID += "/" 1888 claimRefUID += obj.Spec.ClaimRef.Name 1889 } 1890 1891 modesStr := helper.GetAccessModesAsString(obj.Spec.AccessModes) 1892 reclaimPolicyStr := string(obj.Spec.PersistentVolumeReclaimPolicy) 1893 1894 aQty := obj.Spec.Capacity[api.ResourceStorage] 1895 aSize := aQty.String() 1896 1897 phase := obj.Status.Phase 1898 if obj.ObjectMeta.DeletionTimestamp != nil { 1899 phase = "Terminating" 1900 } 1901 volumeMode := "<unset>" 1902 if obj.Spec.VolumeMode != nil { 1903 volumeMode = string(*obj.Spec.VolumeMode) 1904 } 1905 1906 volumeAttributeClass := "<unset>" 1907 if obj.Spec.VolumeAttributesClassName != nil { 1908 volumeAttributeClass = *obj.Spec.VolumeAttributesClassName 1909 } 1910 1911 row.Cells = append(row.Cells, obj.Name, aSize, modesStr, reclaimPolicyStr, 1912 string(phase), claimRefUID, helper.GetPersistentVolumeClass(obj), volumeAttributeClass, 1913 obj.Status.Reason, translateTimestampSince(obj.CreationTimestamp), volumeMode) 1914 return []metav1.TableRow{row}, nil 1915 } 1916 1917 func printPersistentVolumeList(list *api.PersistentVolumeList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1918 rows := make([]metav1.TableRow, 0, len(list.Items)) 1919 for i := range list.Items { 1920 r, err := printPersistentVolume(&list.Items[i], options) 1921 if err != nil { 1922 return nil, err 1923 } 1924 rows = append(rows, r...) 1925 } 1926 return rows, nil 1927 } 1928 1929 func printPersistentVolumeClaim(obj *api.PersistentVolumeClaim, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1930 row := metav1.TableRow{ 1931 Object: runtime.RawExtension{Object: obj}, 1932 } 1933 1934 phase := obj.Status.Phase 1935 if obj.ObjectMeta.DeletionTimestamp != nil { 1936 phase = "Terminating" 1937 } 1938 1939 volumeAttributeClass := "<unset>" 1940 storage := obj.Spec.Resources.Requests[api.ResourceStorage] 1941 capacity := "" 1942 accessModes := "" 1943 volumeMode := "<unset>" 1944 1945 if obj.Spec.VolumeAttributesClassName != nil { 1946 volumeAttributeClass = *obj.Spec.VolumeAttributesClassName 1947 } 1948 1949 if obj.Spec.VolumeName != "" { 1950 accessModes = helper.GetAccessModesAsString(obj.Status.AccessModes) 1951 storage = obj.Status.Capacity[api.ResourceStorage] 1952 capacity = storage.String() 1953 } 1954 1955 if obj.Spec.VolumeMode != nil { 1956 volumeMode = string(*obj.Spec.VolumeMode) 1957 } 1958 1959 row.Cells = append(row.Cells, obj.Name, string(phase), obj.Spec.VolumeName, capacity, accessModes, 1960 helper.GetPersistentVolumeClaimClass(obj), volumeAttributeClass, translateTimestampSince(obj.CreationTimestamp), volumeMode) 1961 return []metav1.TableRow{row}, nil 1962 } 1963 1964 func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1965 rows := make([]metav1.TableRow, 0, len(list.Items)) 1966 for i := range list.Items { 1967 r, err := printPersistentVolumeClaim(&list.Items[i], options) 1968 if err != nil { 1969 return nil, err 1970 } 1971 rows = append(rows, r...) 1972 } 1973 return rows, nil 1974 } 1975 1976 func printEvent(obj *api.Event, options printers.GenerateOptions) ([]metav1.TableRow, error) { 1977 row := metav1.TableRow{ 1978 Object: runtime.RawExtension{Object: obj}, 1979 } 1980 1981 firstTimestamp := translateTimestampSince(obj.FirstTimestamp) 1982 if obj.FirstTimestamp.IsZero() { 1983 firstTimestamp = translateMicroTimestampSince(obj.EventTime) 1984 } 1985 1986 lastTimestamp := translateTimestampSince(obj.LastTimestamp) 1987 if obj.LastTimestamp.IsZero() { 1988 lastTimestamp = firstTimestamp 1989 } 1990 1991 count := obj.Count 1992 if obj.Series != nil { 1993 lastTimestamp = translateMicroTimestampSince(obj.Series.LastObservedTime) 1994 count = obj.Series.Count 1995 } else if count == 0 { 1996 // Singleton events don't have a count set in the new API. 1997 count = 1 1998 } 1999 2000 var target string 2001 if len(obj.InvolvedObject.Name) > 0 { 2002 target = fmt.Sprintf("%s/%s", strings.ToLower(obj.InvolvedObject.Kind), obj.InvolvedObject.Name) 2003 } else { 2004 target = strings.ToLower(obj.InvolvedObject.Kind) 2005 } 2006 if options.Wide { 2007 row.Cells = append(row.Cells, 2008 lastTimestamp, 2009 obj.Type, 2010 obj.Reason, 2011 target, 2012 obj.InvolvedObject.FieldPath, 2013 formatEventSource(obj.Source, obj.ReportingController, obj.ReportingInstance), 2014 strings.TrimSpace(obj.Message), 2015 firstTimestamp, 2016 int64(count), 2017 obj.Name, 2018 ) 2019 } else { 2020 row.Cells = append(row.Cells, 2021 lastTimestamp, 2022 obj.Type, 2023 obj.Reason, 2024 target, 2025 strings.TrimSpace(obj.Message), 2026 ) 2027 } 2028 2029 return []metav1.TableRow{row}, nil 2030 } 2031 2032 // Sorts and prints the EventList in a human-friendly format. 2033 func printEventList(list *api.EventList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2034 rows := make([]metav1.TableRow, 0, len(list.Items)) 2035 for i := range list.Items { 2036 r, err := printEvent(&list.Items[i], options) 2037 if err != nil { 2038 return nil, err 2039 } 2040 rows = append(rows, r...) 2041 } 2042 return rows, nil 2043 } 2044 2045 func printRoleBinding(obj *rbac.RoleBinding, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2046 row := metav1.TableRow{ 2047 Object: runtime.RawExtension{Object: obj}, 2048 } 2049 2050 roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name) 2051 row.Cells = append(row.Cells, obj.Name, roleRef, translateTimestampSince(obj.CreationTimestamp)) 2052 if options.Wide { 2053 users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects) 2054 row.Cells = append(row.Cells, strings.Join(users, ", "), strings.Join(groups, ", "), strings.Join(sas, ", ")) 2055 } 2056 return []metav1.TableRow{row}, nil 2057 } 2058 2059 // Prints the RoleBinding in a human-friendly format. 2060 func printRoleBindingList(list *rbac.RoleBindingList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2061 rows := make([]metav1.TableRow, 0, len(list.Items)) 2062 for i := range list.Items { 2063 r, err := printRoleBinding(&list.Items[i], options) 2064 if err != nil { 2065 return nil, err 2066 } 2067 rows = append(rows, r...) 2068 } 2069 return rows, nil 2070 } 2071 2072 func printClusterRoleBinding(obj *rbac.ClusterRoleBinding, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2073 row := metav1.TableRow{ 2074 Object: runtime.RawExtension{Object: obj}, 2075 } 2076 2077 roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name) 2078 row.Cells = append(row.Cells, obj.Name, roleRef, translateTimestampSince(obj.CreationTimestamp)) 2079 if options.Wide { 2080 users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects) 2081 row.Cells = append(row.Cells, strings.Join(users, ", "), strings.Join(groups, ", "), strings.Join(sas, ", ")) 2082 } 2083 return []metav1.TableRow{row}, nil 2084 } 2085 2086 // Prints the ClusterRoleBinding in a human-friendly format. 2087 func printClusterRoleBindingList(list *rbac.ClusterRoleBindingList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2088 rows := make([]metav1.TableRow, 0, len(list.Items)) 2089 for i := range list.Items { 2090 r, err := printClusterRoleBinding(&list.Items[i], options) 2091 if err != nil { 2092 return nil, err 2093 } 2094 rows = append(rows, r...) 2095 } 2096 return rows, nil 2097 } 2098 2099 func printCertificateSigningRequest(obj *certificates.CertificateSigningRequest, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2100 row := metav1.TableRow{ 2101 Object: runtime.RawExtension{Object: obj}, 2102 } 2103 status := extractCSRStatus(obj) 2104 signerName := "<none>" 2105 if obj.Spec.SignerName != "" { 2106 signerName = obj.Spec.SignerName 2107 } 2108 requestedDuration := "<none>" 2109 if obj.Spec.ExpirationSeconds != nil { 2110 requestedDuration = duration.HumanDuration(csr.ExpirationSecondsToDuration(*obj.Spec.ExpirationSeconds)) 2111 } 2112 row.Cells = append(row.Cells, obj.Name, translateTimestampSince(obj.CreationTimestamp), signerName, obj.Spec.Username, requestedDuration, status) 2113 return []metav1.TableRow{row}, nil 2114 } 2115 2116 func extractCSRStatus(csr *certificates.CertificateSigningRequest) string { 2117 var approved, denied, failed bool 2118 for _, c := range csr.Status.Conditions { 2119 switch c.Type { 2120 case certificates.CertificateApproved: 2121 approved = true 2122 case certificates.CertificateDenied: 2123 denied = true 2124 case certificates.CertificateFailed: 2125 failed = true 2126 } 2127 } 2128 var status string 2129 // must be in order of presidence 2130 if denied { 2131 status += "Denied" 2132 } else if approved { 2133 status += "Approved" 2134 } else { 2135 status += "Pending" 2136 } 2137 if failed { 2138 status += ",Failed" 2139 } 2140 if len(csr.Status.Certificate) > 0 { 2141 status += ",Issued" 2142 } 2143 return status 2144 } 2145 2146 func printCertificateSigningRequestList(list *certificates.CertificateSigningRequestList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2147 rows := make([]metav1.TableRow, 0, len(list.Items)) 2148 for i := range list.Items { 2149 r, err := printCertificateSigningRequest(&list.Items[i], options) 2150 if err != nil { 2151 return nil, err 2152 } 2153 rows = append(rows, r...) 2154 } 2155 return rows, nil 2156 } 2157 2158 func printClusterTrustBundle(obj *certificates.ClusterTrustBundle, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2159 row := metav1.TableRow{ 2160 Object: runtime.RawExtension{Object: obj}, 2161 } 2162 signerName := "<none>" 2163 if obj.Spec.SignerName != "" { 2164 signerName = obj.Spec.SignerName 2165 } 2166 row.Cells = append(row.Cells, obj.Name, signerName) 2167 return []metav1.TableRow{row}, nil 2168 } 2169 2170 func printClusterTrustBundleList(list *certificates.ClusterTrustBundleList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2171 rows := make([]metav1.TableRow, 0, len(list.Items)) 2172 for i := range list.Items { 2173 r, err := printClusterTrustBundle(&list.Items[i], options) 2174 if err != nil { 2175 return nil, err 2176 } 2177 rows = append(rows, r...) 2178 } 2179 return rows, nil 2180 } 2181 2182 func printComponentStatus(obj *api.ComponentStatus, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2183 row := metav1.TableRow{ 2184 Object: runtime.RawExtension{Object: obj}, 2185 } 2186 status := "Unknown" 2187 message := "" 2188 error := "" 2189 for _, condition := range obj.Conditions { 2190 if condition.Type == api.ComponentHealthy { 2191 if condition.Status == api.ConditionTrue { 2192 status = "Healthy" 2193 } else { 2194 status = "Unhealthy" 2195 } 2196 message = condition.Message 2197 error = condition.Error 2198 break 2199 } 2200 } 2201 row.Cells = append(row.Cells, obj.Name, status, message, error) 2202 return []metav1.TableRow{row}, nil 2203 } 2204 2205 func printComponentStatusList(list *api.ComponentStatusList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2206 rows := make([]metav1.TableRow, 0, len(list.Items)) 2207 for i := range list.Items { 2208 r, err := printComponentStatus(&list.Items[i], options) 2209 if err != nil { 2210 return nil, err 2211 } 2212 rows = append(rows, r...) 2213 } 2214 return rows, nil 2215 } 2216 2217 func printDeployment(obj *apps.Deployment, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2218 row := metav1.TableRow{ 2219 Object: runtime.RawExtension{Object: obj}, 2220 } 2221 desiredReplicas := obj.Spec.Replicas 2222 updatedReplicas := obj.Status.UpdatedReplicas 2223 readyReplicas := obj.Status.ReadyReplicas 2224 availableReplicas := obj.Status.AvailableReplicas 2225 age := translateTimestampSince(obj.CreationTimestamp) 2226 containers := obj.Spec.Template.Spec.Containers 2227 selector, err := metav1.LabelSelectorAsSelector(obj.Spec.Selector) 2228 selectorString := "" 2229 if err != nil { 2230 selectorString = "<invalid>" 2231 } else { 2232 selectorString = selector.String() 2233 } 2234 row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%d/%d", int64(readyReplicas), int64(desiredReplicas)), int64(updatedReplicas), int64(availableReplicas), age) 2235 if options.Wide { 2236 containers, images := layoutContainerCells(containers) 2237 row.Cells = append(row.Cells, containers, images, selectorString) 2238 } 2239 return []metav1.TableRow{row}, nil 2240 } 2241 2242 func printDeploymentList(list *apps.DeploymentList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2243 rows := make([]metav1.TableRow, 0, len(list.Items)) 2244 for i := range list.Items { 2245 r, err := printDeployment(&list.Items[i], options) 2246 if err != nil { 2247 return nil, err 2248 } 2249 rows = append(rows, r...) 2250 } 2251 return rows, nil 2252 } 2253 2254 func formatHPAMetrics(specs []autoscaling.MetricSpec, statuses []autoscaling.MetricStatus) string { 2255 if len(specs) == 0 { 2256 return "<none>" 2257 } 2258 list := []string{} 2259 max := 2 2260 more := false 2261 count := 0 2262 for i, spec := range specs { 2263 switch spec.Type { 2264 case autoscaling.ExternalMetricSourceType: 2265 if spec.External.Target.AverageValue != nil { 2266 current := "<unknown>" 2267 if len(statuses) > i && statuses[i].External != nil && statuses[i].External.Current.AverageValue != nil { 2268 current = statuses[i].External.Current.AverageValue.String() 2269 } 2270 list = append(list, fmt.Sprintf("%s/%s (avg)", current, spec.External.Target.AverageValue.String())) 2271 } else { 2272 current := "<unknown>" 2273 if len(statuses) > i && statuses[i].External != nil { 2274 current = statuses[i].External.Current.Value.String() 2275 } 2276 list = append(list, fmt.Sprintf("%s/%s", current, spec.External.Target.Value.String())) 2277 } 2278 case autoscaling.PodsMetricSourceType: 2279 current := "<unknown>" 2280 if len(statuses) > i && statuses[i].Pods != nil { 2281 current = statuses[i].Pods.Current.AverageValue.String() 2282 } 2283 list = append(list, fmt.Sprintf("%s/%s", current, spec.Pods.Target.AverageValue.String())) 2284 case autoscaling.ObjectMetricSourceType: 2285 if spec.Object.Target.AverageValue != nil { 2286 current := "<unknown>" 2287 if len(statuses) > i && statuses[i].Object != nil && statuses[i].Object.Current.AverageValue != nil { 2288 current = statuses[i].Object.Current.AverageValue.String() 2289 } 2290 list = append(list, fmt.Sprintf("%s/%s (avg)", current, spec.Object.Target.AverageValue.String())) 2291 } else { 2292 current := "<unknown>" 2293 if len(statuses) > i && statuses[i].Object != nil { 2294 current = statuses[i].Object.Current.Value.String() 2295 } 2296 list = append(list, fmt.Sprintf("%s/%s", current, spec.Object.Target.Value.String())) 2297 } 2298 case autoscaling.ResourceMetricSourceType: 2299 if spec.Resource.Target.AverageValue != nil { 2300 current := "<unknown>" 2301 if len(statuses) > i && statuses[i].Resource != nil { 2302 current = statuses[i].Resource.Current.AverageValue.String() 2303 } 2304 list = append(list, fmt.Sprintf("%s/%s", current, spec.Resource.Target.AverageValue.String())) 2305 } else { 2306 current := "<unknown>" 2307 if len(statuses) > i && statuses[i].Resource != nil && statuses[i].Resource.Current.AverageUtilization != nil { 2308 current = fmt.Sprintf("%d%%", *statuses[i].Resource.Current.AverageUtilization) 2309 } 2310 2311 target := "<auto>" 2312 if spec.Resource.Target.AverageUtilization != nil { 2313 target = fmt.Sprintf("%d%%", *spec.Resource.Target.AverageUtilization) 2314 } 2315 list = append(list, fmt.Sprintf("%s/%s", current, target)) 2316 } 2317 case autoscaling.ContainerResourceMetricSourceType: 2318 if spec.ContainerResource.Target.AverageValue != nil { 2319 current := "<unknown>" 2320 if len(statuses) > i && statuses[i].ContainerResource != nil { 2321 current = statuses[i].ContainerResource.Current.AverageValue.String() 2322 } 2323 list = append(list, fmt.Sprintf("%s/%s", current, spec.ContainerResource.Target.AverageValue.String())) 2324 } else { 2325 current := "<unknown>" 2326 if len(statuses) > i && statuses[i].ContainerResource != nil && statuses[i].ContainerResource.Current.AverageUtilization != nil { 2327 current = fmt.Sprintf("%d%%", *statuses[i].ContainerResource.Current.AverageUtilization) 2328 } 2329 2330 target := "<auto>" 2331 if spec.ContainerResource.Target.AverageUtilization != nil { 2332 target = fmt.Sprintf("%d%%", *spec.ContainerResource.Target.AverageUtilization) 2333 } 2334 list = append(list, fmt.Sprintf("%s/%s", current, target)) 2335 } 2336 default: 2337 list = append(list, "<unknown type>") 2338 } 2339 2340 count++ 2341 } 2342 2343 if count > max { 2344 list = list[:max] 2345 more = true 2346 } 2347 2348 ret := strings.Join(list, ", ") 2349 if more { 2350 return fmt.Sprintf("%s + %d more...", ret, count-max) 2351 } 2352 return ret 2353 } 2354 2355 func printHorizontalPodAutoscaler(obj *autoscaling.HorizontalPodAutoscaler, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2356 row := metav1.TableRow{ 2357 Object: runtime.RawExtension{Object: obj}, 2358 } 2359 2360 reference := fmt.Sprintf("%s/%s", 2361 obj.Spec.ScaleTargetRef.Kind, 2362 obj.Spec.ScaleTargetRef.Name) 2363 minPods := "<unset>" 2364 metrics := formatHPAMetrics(obj.Spec.Metrics, obj.Status.CurrentMetrics) 2365 if obj.Spec.MinReplicas != nil { 2366 minPods = fmt.Sprintf("%d", *obj.Spec.MinReplicas) 2367 } 2368 maxPods := obj.Spec.MaxReplicas 2369 currentReplicas := obj.Status.CurrentReplicas 2370 row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestampSince(obj.CreationTimestamp)) 2371 return []metav1.TableRow{row}, nil 2372 } 2373 2374 func printHorizontalPodAutoscalerList(list *autoscaling.HorizontalPodAutoscalerList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2375 rows := make([]metav1.TableRow, 0, len(list.Items)) 2376 for i := range list.Items { 2377 r, err := printHorizontalPodAutoscaler(&list.Items[i], options) 2378 if err != nil { 2379 return nil, err 2380 } 2381 rows = append(rows, r...) 2382 } 2383 return rows, nil 2384 } 2385 2386 func printConfigMap(obj *api.ConfigMap, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2387 row := metav1.TableRow{ 2388 Object: runtime.RawExtension{Object: obj}, 2389 } 2390 row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)+len(obj.BinaryData)), translateTimestampSince(obj.CreationTimestamp)) 2391 return []metav1.TableRow{row}, nil 2392 } 2393 2394 func printConfigMapList(list *api.ConfigMapList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2395 rows := make([]metav1.TableRow, 0, len(list.Items)) 2396 for i := range list.Items { 2397 r, err := printConfigMap(&list.Items[i], options) 2398 if err != nil { 2399 return nil, err 2400 } 2401 rows = append(rows, r...) 2402 } 2403 return rows, nil 2404 } 2405 2406 func printNetworkPolicy(obj *networking.NetworkPolicy, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2407 row := metav1.TableRow{ 2408 Object: runtime.RawExtension{Object: obj}, 2409 } 2410 row.Cells = append(row.Cells, obj.Name, metav1.FormatLabelSelector(&obj.Spec.PodSelector), translateTimestampSince(obj.CreationTimestamp)) 2411 return []metav1.TableRow{row}, nil 2412 } 2413 2414 func printNetworkPolicyList(list *networking.NetworkPolicyList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2415 rows := make([]metav1.TableRow, 0, len(list.Items)) 2416 for i := range list.Items { 2417 r, err := printNetworkPolicy(&list.Items[i], options) 2418 if err != nil { 2419 return nil, err 2420 } 2421 rows = append(rows, r...) 2422 } 2423 return rows, nil 2424 } 2425 2426 func printStorageClass(obj *storage.StorageClass, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2427 row := metav1.TableRow{ 2428 Object: runtime.RawExtension{Object: obj}, 2429 } 2430 2431 name := obj.Name 2432 if storageutil.IsDefaultAnnotation(obj.ObjectMeta) { 2433 name += " (default)" 2434 } 2435 provtype := obj.Provisioner 2436 reclaimPolicy := string(api.PersistentVolumeReclaimDelete) 2437 if obj.ReclaimPolicy != nil { 2438 reclaimPolicy = string(*obj.ReclaimPolicy) 2439 } 2440 2441 volumeBindingMode := string(storage.VolumeBindingImmediate) 2442 if obj.VolumeBindingMode != nil { 2443 volumeBindingMode = string(*obj.VolumeBindingMode) 2444 } 2445 2446 allowVolumeExpansion := false 2447 if obj.AllowVolumeExpansion != nil { 2448 allowVolumeExpansion = *obj.AllowVolumeExpansion 2449 } 2450 2451 row.Cells = append(row.Cells, name, provtype, reclaimPolicy, volumeBindingMode, allowVolumeExpansion, 2452 translateTimestampSince(obj.CreationTimestamp)) 2453 2454 return []metav1.TableRow{row}, nil 2455 } 2456 2457 func printStorageClassList(list *storage.StorageClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2458 rows := make([]metav1.TableRow, 0, len(list.Items)) 2459 for i := range list.Items { 2460 r, err := printStorageClass(&list.Items[i], options) 2461 if err != nil { 2462 return nil, err 2463 } 2464 rows = append(rows, r...) 2465 } 2466 return rows, nil 2467 } 2468 2469 func printVolumeAttributesClass(obj *storage.VolumeAttributesClass, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2470 row := metav1.TableRow{ 2471 Object: runtime.RawExtension{Object: obj}, 2472 } 2473 2474 name := obj.Name 2475 if storageutil.IsDefaultAnnotationForVolumeAttributesClass(obj.ObjectMeta) { 2476 name += " (default)" 2477 } 2478 2479 row.Cells = append(row.Cells, name, obj.DriverName, translateTimestampSince(obj.CreationTimestamp)) 2480 2481 return []metav1.TableRow{row}, nil 2482 } 2483 2484 func printVolumeAttributesClassList(list *storage.VolumeAttributesClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2485 rows := make([]metav1.TableRow, 0, len(list.Items)) 2486 for i := range list.Items { 2487 r, err := printVolumeAttributesClass(&list.Items[i], options) 2488 if err != nil { 2489 return nil, err 2490 } 2491 rows = append(rows, r...) 2492 } 2493 return rows, nil 2494 } 2495 2496 func printLease(obj *coordination.Lease, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2497 row := metav1.TableRow{ 2498 Object: runtime.RawExtension{Object: obj}, 2499 } 2500 2501 var holderIdentity string 2502 if obj.Spec.HolderIdentity != nil { 2503 holderIdentity = *obj.Spec.HolderIdentity 2504 } 2505 row.Cells = append(row.Cells, obj.Name, holderIdentity, translateTimestampSince(obj.CreationTimestamp)) 2506 return []metav1.TableRow{row}, nil 2507 } 2508 2509 func printLeaseList(list *coordination.LeaseList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2510 rows := make([]metav1.TableRow, 0, len(list.Items)) 2511 for i := range list.Items { 2512 r, err := printLease(&list.Items[i], options) 2513 if err != nil { 2514 return nil, err 2515 } 2516 rows = append(rows, r...) 2517 } 2518 return rows, nil 2519 } 2520 2521 func printStatus(obj *metav1.Status, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2522 row := metav1.TableRow{ 2523 Object: runtime.RawExtension{Object: obj}, 2524 } 2525 row.Cells = append(row.Cells, obj.Status, string(obj.Reason), obj.Message) 2526 2527 return []metav1.TableRow{row}, nil 2528 } 2529 2530 // Lay out all the containers on one line if use wide output. 2531 func layoutContainerCells(containers []api.Container) (names string, images string) { 2532 var namesBuffer bytes.Buffer 2533 var imagesBuffer bytes.Buffer 2534 2535 for i, container := range containers { 2536 namesBuffer.WriteString(container.Name) 2537 imagesBuffer.WriteString(container.Image) 2538 if i != len(containers)-1 { 2539 namesBuffer.WriteString(",") 2540 imagesBuffer.WriteString(",") 2541 } 2542 } 2543 return namesBuffer.String(), imagesBuffer.String() 2544 } 2545 2546 // formatEventSource formats EventSource as a comma separated string excluding Host when empty. 2547 // It uses reportingController when Source.Component is empty and reportingInstance when Source.Host is empty 2548 func formatEventSource(es api.EventSource, reportingController, reportingInstance string) string { 2549 return formatEventSourceComponentInstance( 2550 firstNonEmpty(es.Component, reportingController), 2551 firstNonEmpty(es.Host, reportingInstance), 2552 ) 2553 } 2554 2555 func firstNonEmpty(ss ...string) string { 2556 for _, s := range ss { 2557 if len(s) > 0 { 2558 return s 2559 } 2560 } 2561 return "" 2562 } 2563 2564 func formatEventSourceComponentInstance(component, instance string) string { 2565 if len(instance) == 0 { 2566 return component 2567 } 2568 return component + ", " + instance 2569 } 2570 2571 func printControllerRevision(obj *apps.ControllerRevision, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2572 row := metav1.TableRow{ 2573 Object: runtime.RawExtension{Object: obj}, 2574 } 2575 2576 controllerRef := metav1.GetControllerOf(obj) 2577 controllerName := "<none>" 2578 if controllerRef != nil { 2579 withKind := true 2580 gv, err := schema.ParseGroupVersion(controllerRef.APIVersion) 2581 if err != nil { 2582 return nil, err 2583 } 2584 gvk := gv.WithKind(controllerRef.Kind) 2585 controllerName = formatResourceName(gvk.GroupKind(), controllerRef.Name, withKind) 2586 } 2587 revision := obj.Revision 2588 age := translateTimestampSince(obj.CreationTimestamp) 2589 row.Cells = append(row.Cells, obj.Name, controllerName, revision, age) 2590 return []metav1.TableRow{row}, nil 2591 } 2592 2593 func printControllerRevisionList(list *apps.ControllerRevisionList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2594 rows := make([]metav1.TableRow, 0, len(list.Items)) 2595 for i := range list.Items { 2596 r, err := printControllerRevision(&list.Items[i], options) 2597 if err != nil { 2598 return nil, err 2599 } 2600 rows = append(rows, r...) 2601 } 2602 return rows, nil 2603 } 2604 2605 // formatResourceName receives a resource kind, name, and boolean specifying 2606 // whether or not to update the current name to "kind/name" 2607 func formatResourceName(kind schema.GroupKind, name string, withKind bool) string { 2608 if !withKind || kind.Empty() { 2609 return name 2610 } 2611 2612 return strings.ToLower(kind.String()) + "/" + name 2613 } 2614 2615 func printResourceQuota(resourceQuota *api.ResourceQuota, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2616 row := metav1.TableRow{ 2617 Object: runtime.RawExtension{Object: resourceQuota}, 2618 } 2619 2620 resources := make([]api.ResourceName, 0, len(resourceQuota.Status.Hard)) 2621 for resource := range resourceQuota.Status.Hard { 2622 resources = append(resources, resource) 2623 } 2624 sort.Sort(SortableResourceNames(resources)) 2625 2626 requestColumn := bytes.NewBuffer([]byte{}) 2627 limitColumn := bytes.NewBuffer([]byte{}) 2628 for i := range resources { 2629 w := requestColumn 2630 resource := resources[i] 2631 usedQuantity := resourceQuota.Status.Used[resource] 2632 hardQuantity := resourceQuota.Status.Hard[resource] 2633 2634 // use limitColumn writer if a resource name prefixed with "limits" is found 2635 if pieces := strings.Split(resource.String(), "."); len(pieces) > 1 && pieces[0] == "limits" { 2636 w = limitColumn 2637 } 2638 2639 fmt.Fprintf(w, "%s: %s/%s, ", resource, usedQuantity.String(), hardQuantity.String()) 2640 } 2641 2642 age := translateTimestampSince(resourceQuota.CreationTimestamp) 2643 row.Cells = append(row.Cells, resourceQuota.Name, age, strings.TrimSuffix(requestColumn.String(), ", "), strings.TrimSuffix(limitColumn.String(), ", ")) 2644 return []metav1.TableRow{row}, nil 2645 } 2646 2647 func printResourceQuotaList(list *api.ResourceQuotaList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2648 rows := make([]metav1.TableRow, 0, len(list.Items)) 2649 for i := range list.Items { 2650 r, err := printResourceQuota(&list.Items[i], options) 2651 if err != nil { 2652 return nil, err 2653 } 2654 rows = append(rows, r...) 2655 } 2656 return rows, nil 2657 } 2658 2659 func printPriorityClass(obj *scheduling.PriorityClass, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2660 row := metav1.TableRow{ 2661 Object: runtime.RawExtension{Object: obj}, 2662 } 2663 2664 name := obj.Name 2665 value := obj.Value 2666 globalDefault := obj.GlobalDefault 2667 row.Cells = append(row.Cells, name, int64(value), globalDefault, translateTimestampSince(obj.CreationTimestamp)) 2668 2669 return []metav1.TableRow{row}, nil 2670 } 2671 2672 func printPriorityClassList(list *scheduling.PriorityClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2673 rows := make([]metav1.TableRow, 0, len(list.Items)) 2674 for i := range list.Items { 2675 r, err := printPriorityClass(&list.Items[i], options) 2676 if err != nil { 2677 return nil, err 2678 } 2679 rows = append(rows, r...) 2680 } 2681 return rows, nil 2682 } 2683 2684 func printRuntimeClass(obj *nodeapi.RuntimeClass, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2685 row := metav1.TableRow{ 2686 Object: runtime.RawExtension{Object: obj}, 2687 } 2688 2689 name := obj.Name 2690 handler := obj.Handler 2691 row.Cells = append(row.Cells, name, handler, translateTimestampSince(obj.CreationTimestamp)) 2692 2693 return []metav1.TableRow{row}, nil 2694 } 2695 2696 func printRuntimeClassList(list *nodeapi.RuntimeClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2697 rows := make([]metav1.TableRow, 0, len(list.Items)) 2698 for i := range list.Items { 2699 r, err := printRuntimeClass(&list.Items[i], options) 2700 2701 if err != nil { 2702 return nil, err 2703 } 2704 rows = append(rows, r...) 2705 } 2706 return rows, nil 2707 } 2708 2709 func printVolumeAttachment(obj *storage.VolumeAttachment, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2710 row := metav1.TableRow{ 2711 Object: runtime.RawExtension{Object: obj}, 2712 } 2713 2714 name := obj.Name 2715 pvName := "" 2716 if obj.Spec.Source.PersistentVolumeName != nil { 2717 pvName = *obj.Spec.Source.PersistentVolumeName 2718 } 2719 row.Cells = append(row.Cells, name, obj.Spec.Attacher, pvName, obj.Spec.NodeName, obj.Status.Attached, translateTimestampSince(obj.CreationTimestamp)) 2720 2721 return []metav1.TableRow{row}, nil 2722 } 2723 2724 func printVolumeAttachmentList(list *storage.VolumeAttachmentList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2725 rows := make([]metav1.TableRow, 0, len(list.Items)) 2726 for i := range list.Items { 2727 r, err := printVolumeAttachment(&list.Items[i], options) 2728 if err != nil { 2729 return nil, err 2730 } 2731 rows = append(rows, r...) 2732 } 2733 return rows, nil 2734 } 2735 2736 func printFlowSchema(obj *flowcontrol.FlowSchema, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2737 row := metav1.TableRow{ 2738 Object: runtime.RawExtension{Object: obj}, 2739 } 2740 2741 name := obj.Name 2742 plName := obj.Spec.PriorityLevelConfiguration.Name 2743 distinguisherMethod := "<none>" 2744 if obj.Spec.DistinguisherMethod != nil { 2745 distinguisherMethod = string(obj.Spec.DistinguisherMethod.Type) 2746 } 2747 badPLRef := "?" 2748 for _, cond := range obj.Status.Conditions { 2749 if cond.Type == flowcontrol.FlowSchemaConditionDangling { 2750 badPLRef = string(cond.Status) 2751 break 2752 } 2753 } 2754 row.Cells = append(row.Cells, name, plName, int64(obj.Spec.MatchingPrecedence), distinguisherMethod, translateTimestampSince(obj.CreationTimestamp), badPLRef) 2755 2756 return []metav1.TableRow{row}, nil 2757 } 2758 2759 func printFlowSchemaList(list *flowcontrol.FlowSchemaList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2760 rows := make([]metav1.TableRow, 0, len(list.Items)) 2761 fsSeq := make(apihelpers.FlowSchemaSequence, len(list.Items)) 2762 for i := range list.Items { 2763 fsSeq[i] = &list.Items[i] 2764 } 2765 sort.Sort(fsSeq) 2766 for i := range fsSeq { 2767 r, err := printFlowSchema(fsSeq[i], options) 2768 if err != nil { 2769 return nil, err 2770 } 2771 rows = append(rows, r...) 2772 } 2773 return rows, nil 2774 } 2775 2776 func printStorageVersion(obj *apiserverinternal.StorageVersion, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2777 row := metav1.TableRow{ 2778 Object: runtime.RawExtension{Object: obj}, 2779 } 2780 commonEncodingVersion := "<unset>" 2781 if obj.Status.CommonEncodingVersion != nil { 2782 commonEncodingVersion = *obj.Status.CommonEncodingVersion 2783 } 2784 row.Cells = append(row.Cells, obj.Name, commonEncodingVersion, formatStorageVersions(obj.Status.StorageVersions), translateTimestampSince(obj.CreationTimestamp)) 2785 return []metav1.TableRow{row}, nil 2786 } 2787 2788 func formatStorageVersions(storageVersions []apiserverinternal.ServerStorageVersion) string { 2789 list := []string{} 2790 max := 3 2791 more := false 2792 count := 0 2793 for _, sv := range storageVersions { 2794 if len(list) < max { 2795 list = append(list, fmt.Sprintf("%s=%s", sv.APIServerID, sv.EncodingVersion)) 2796 } else if len(list) == max { 2797 more = true 2798 } 2799 count++ 2800 } 2801 return listWithMoreString(list, more, count, max) 2802 } 2803 2804 func printStorageVersionList(list *apiserverinternal.StorageVersionList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2805 rows := make([]metav1.TableRow, 0, len(list.Items)) 2806 for i := range list.Items { 2807 r, err := printStorageVersion(&list.Items[i], options) 2808 if err != nil { 2809 return nil, err 2810 } 2811 rows = append(rows, r...) 2812 } 2813 return rows, nil 2814 } 2815 2816 func printPriorityLevelConfiguration(obj *flowcontrol.PriorityLevelConfiguration, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2817 row := metav1.TableRow{ 2818 Object: runtime.RawExtension{Object: obj}, 2819 } 2820 name := obj.Name 2821 ncs := interface{}("<none>") 2822 queues := interface{}("<none>") 2823 handSize := interface{}("<none>") 2824 queueLengthLimit := interface{}("<none>") 2825 if obj.Spec.Limited != nil { 2826 ncs = obj.Spec.Limited.NominalConcurrencyShares 2827 if qc := obj.Spec.Limited.LimitResponse.Queuing; qc != nil { 2828 queues = qc.Queues 2829 handSize = qc.HandSize 2830 queueLengthLimit = qc.QueueLengthLimit 2831 } 2832 } 2833 row.Cells = append(row.Cells, name, string(obj.Spec.Type), ncs, queues, handSize, queueLengthLimit, translateTimestampSince(obj.CreationTimestamp)) 2834 2835 return []metav1.TableRow{row}, nil 2836 } 2837 2838 func printPriorityLevelConfigurationList(list *flowcontrol.PriorityLevelConfigurationList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2839 rows := make([]metav1.TableRow, 0, len(list.Items)) 2840 for i := range list.Items { 2841 r, err := printPriorityLevelConfiguration(&list.Items[i], options) 2842 if err != nil { 2843 return nil, err 2844 } 2845 rows = append(rows, r...) 2846 } 2847 return rows, nil 2848 } 2849 2850 func printServiceCIDR(obj *networking.ServiceCIDR, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2851 row := metav1.TableRow{ 2852 Object: runtime.RawExtension{Object: obj}, 2853 } 2854 2855 cidrs := strings.Join(obj.Spec.CIDRs, ",") 2856 row.Cells = append(row.Cells, obj.Name, cidrs, translateTimestampSince(obj.CreationTimestamp)) 2857 return []metav1.TableRow{row}, nil 2858 } 2859 2860 func printServiceCIDRList(list *networking.ServiceCIDRList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2861 rows := make([]metav1.TableRow, 0, len(list.Items)) 2862 for i := range list.Items { 2863 r, err := printServiceCIDR(&list.Items[i], options) 2864 if err != nil { 2865 return nil, err 2866 } 2867 rows = append(rows, r...) 2868 } 2869 return rows, nil 2870 } 2871 2872 func printIPAddress(obj *networking.IPAddress, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2873 row := metav1.TableRow{ 2874 Object: runtime.RawExtension{Object: obj}, 2875 } 2876 2877 parentRefName := "<none>" 2878 if obj.Spec.ParentRef != nil { 2879 gr := schema.GroupResource{ 2880 Group: obj.Spec.ParentRef.Group, 2881 Resource: obj.Spec.ParentRef.Resource, 2882 } 2883 parentRefName = strings.ToLower(gr.String()) 2884 if obj.Spec.ParentRef.Namespace != "" { 2885 parentRefName += "/" + obj.Spec.ParentRef.Namespace 2886 } 2887 parentRefName += "/" + obj.Spec.ParentRef.Name 2888 } 2889 age := translateTimestampSince(obj.CreationTimestamp) 2890 row.Cells = append(row.Cells, obj.Name, parentRefName, age) 2891 2892 return []metav1.TableRow{row}, nil 2893 } 2894 2895 func printIPAddressList(list *networking.IPAddressList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2896 rows := make([]metav1.TableRow, 0, len(list.Items)) 2897 for i := range list.Items { 2898 r, err := printIPAddress(&list.Items[i], options) 2899 if err != nil { 2900 return nil, err 2901 } 2902 rows = append(rows, r...) 2903 } 2904 return rows, nil 2905 } 2906 2907 func printScale(obj *autoscaling.Scale, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2908 row := metav1.TableRow{ 2909 Object: runtime.RawExtension{Object: obj}, 2910 } 2911 row.Cells = append(row.Cells, obj.Name, int64(obj.Spec.Replicas), int64(obj.Status.Replicas), translateTimestampSince(obj.CreationTimestamp)) 2912 return []metav1.TableRow{row}, nil 2913 } 2914 2915 func printResourceClass(obj *resource.ResourceClass, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2916 row := metav1.TableRow{ 2917 Object: runtime.RawExtension{Object: obj}, 2918 } 2919 row.Cells = append(row.Cells, obj.Name, obj.DriverName, translateTimestampSince(obj.CreationTimestamp)) 2920 2921 return []metav1.TableRow{row}, nil 2922 } 2923 2924 func printResourceClassList(list *resource.ResourceClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2925 rows := make([]metav1.TableRow, 0, len(list.Items)) 2926 for i := range list.Items { 2927 r, err := printResourceClass(&list.Items[i], options) 2928 if err != nil { 2929 return nil, err 2930 } 2931 rows = append(rows, r...) 2932 } 2933 return rows, nil 2934 } 2935 2936 func printResourceClaim(obj *resource.ResourceClaim, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2937 row := metav1.TableRow{ 2938 Object: runtime.RawExtension{Object: obj}, 2939 } 2940 row.Cells = append(row.Cells, obj.Name, obj.Spec.ResourceClassName, string(obj.Spec.AllocationMode), resourceClaimState(obj), translateTimestampSince(obj.CreationTimestamp)) 2941 2942 return []metav1.TableRow{row}, nil 2943 } 2944 2945 func resourceClaimState(obj *resource.ResourceClaim) string { 2946 var states []string 2947 if obj.DeletionTimestamp != nil { 2948 states = append(states, "deleted") 2949 } 2950 if obj.Status.Allocation == nil { 2951 if obj.DeletionTimestamp == nil { 2952 states = append(states, "pending") 2953 } 2954 } else { 2955 states = append(states, "allocated") 2956 if len(obj.Status.ReservedFor) > 0 { 2957 states = append(states, "reserved") 2958 } else if obj.DeletionTimestamp != nil || obj.Status.DeallocationRequested { 2959 states = append(states, "deallocating") 2960 } 2961 } 2962 return strings.Join(states, ",") 2963 } 2964 2965 func printResourceClaimList(list *resource.ResourceClaimList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2966 rows := make([]metav1.TableRow, 0, len(list.Items)) 2967 for i := range list.Items { 2968 r, err := printResourceClaim(&list.Items[i], options) 2969 if err != nil { 2970 return nil, err 2971 } 2972 rows = append(rows, r...) 2973 } 2974 return rows, nil 2975 } 2976 2977 func printResourceClaimTemplate(obj *resource.ResourceClaimTemplate, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2978 row := metav1.TableRow{ 2979 Object: runtime.RawExtension{Object: obj}, 2980 } 2981 row.Cells = append(row.Cells, obj.Name, obj.Spec.Spec.ResourceClassName, string(obj.Spec.Spec.AllocationMode), translateTimestampSince(obj.CreationTimestamp)) 2982 2983 return []metav1.TableRow{row}, nil 2984 } 2985 2986 func printResourceClaimTemplateList(list *resource.ResourceClaimTemplateList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2987 rows := make([]metav1.TableRow, 0, len(list.Items)) 2988 for i := range list.Items { 2989 r, err := printResourceClaimTemplate(&list.Items[i], options) 2990 if err != nil { 2991 return nil, err 2992 } 2993 rows = append(rows, r...) 2994 } 2995 return rows, nil 2996 } 2997 2998 func printPodSchedulingContext(obj *resource.PodSchedulingContext, options printers.GenerateOptions) ([]metav1.TableRow, error) { 2999 row := metav1.TableRow{ 3000 Object: runtime.RawExtension{Object: obj}, 3001 } 3002 row.Cells = append(row.Cells, obj.Name, obj.Spec.SelectedNode, translateTimestampSince(obj.CreationTimestamp)) 3003 3004 return []metav1.TableRow{row}, nil 3005 } 3006 3007 func printPodSchedulingContextList(list *resource.PodSchedulingContextList, options printers.GenerateOptions) ([]metav1.TableRow, error) { 3008 rows := make([]metav1.TableRow, 0, len(list.Items)) 3009 for i := range list.Items { 3010 r, err := printPodSchedulingContext(&list.Items[i], options) 3011 if err != nil { 3012 return nil, err 3013 } 3014 rows = append(rows, r...) 3015 } 3016 return rows, nil 3017 } 3018 3019 func printBoolPtr(value *bool) string { 3020 if value != nil { 3021 return printBool(*value) 3022 } 3023 3024 return "<unset>" 3025 } 3026 3027 func printBool(value bool) string { 3028 if value { 3029 return "True" 3030 } 3031 3032 return "False" 3033 } 3034 3035 // SortableResourceNames - An array of sortable resource names 3036 type SortableResourceNames []api.ResourceName 3037 3038 func (list SortableResourceNames) Len() int { 3039 return len(list) 3040 } 3041 3042 func (list SortableResourceNames) Swap(i, j int) { 3043 list[i], list[j] = list[j], list[i] 3044 } 3045 3046 func (list SortableResourceNames) Less(i, j int) bool { 3047 return list[i] < list[j] 3048 } 3049 3050 func isRestartableInitContainer(initContainer *api.Container) bool { 3051 if initContainer.RestartPolicy == nil { 3052 return false 3053 } 3054 3055 return *initContainer.RestartPolicy == api.ContainerRestartPolicyAlways 3056 } 3057 3058 func isPodInitializedConditionTrue(status *api.PodStatus) bool { 3059 for _, condition := range status.Conditions { 3060 if condition.Type != api.PodInitialized { 3061 continue 3062 } 3063 3064 return condition.Status == api.ConditionTrue 3065 } 3066 return false 3067 }