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