printers.go 94 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package internalversion
  14. import (
  15. "bytes"
  16. "fmt"
  17. "net"
  18. "sort"
  19. "strconv"
  20. "strings"
  21. "time"
  22. appsv1beta1 "k8s.io/api/apps/v1beta1"
  23. autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
  24. batchv1 "k8s.io/api/batch/v1"
  25. batchv1beta1 "k8s.io/api/batch/v1beta1"
  26. certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
  27. coordinationv1 "k8s.io/api/coordination/v1"
  28. apiv1 "k8s.io/api/core/v1"
  29. discoveryv1beta1 "k8s.io/api/discovery/v1beta1"
  30. extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
  31. flowcontrolv1alpha1 "k8s.io/api/flowcontrol/v1alpha1"
  32. policyv1beta1 "k8s.io/api/policy/v1beta1"
  33. rbacv1beta1 "k8s.io/api/rbac/v1beta1"
  34. schedulingv1 "k8s.io/api/scheduling/v1"
  35. storagev1 "k8s.io/api/storage/v1"
  36. storagev1beta1 "k8s.io/api/storage/v1beta1"
  37. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  38. "k8s.io/apimachinery/pkg/labels"
  39. "k8s.io/apimachinery/pkg/runtime"
  40. "k8s.io/apimachinery/pkg/runtime/schema"
  41. "k8s.io/apimachinery/pkg/util/duration"
  42. "k8s.io/apimachinery/pkg/util/sets"
  43. "k8s.io/kubernetes/pkg/apis/admissionregistration"
  44. "k8s.io/kubernetes/pkg/apis/apps"
  45. "k8s.io/kubernetes/pkg/apis/autoscaling"
  46. "k8s.io/kubernetes/pkg/apis/batch"
  47. "k8s.io/kubernetes/pkg/apis/certificates"
  48. "k8s.io/kubernetes/pkg/apis/coordination"
  49. api "k8s.io/kubernetes/pkg/apis/core"
  50. "k8s.io/kubernetes/pkg/apis/core/helper"
  51. "k8s.io/kubernetes/pkg/apis/discovery"
  52. "k8s.io/kubernetes/pkg/apis/flowcontrol"
  53. apihelpers "k8s.io/kubernetes/pkg/apis/flowcontrol/util"
  54. "k8s.io/kubernetes/pkg/apis/networking"
  55. nodeapi "k8s.io/kubernetes/pkg/apis/node"
  56. "k8s.io/kubernetes/pkg/apis/policy"
  57. "k8s.io/kubernetes/pkg/apis/rbac"
  58. "k8s.io/kubernetes/pkg/apis/scheduling"
  59. "k8s.io/kubernetes/pkg/apis/storage"
  60. storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
  61. "k8s.io/kubernetes/pkg/printers"
  62. "k8s.io/kubernetes/pkg/util/node"
  63. )
  64. const (
  65. loadBalancerWidth = 16
  66. // labelNodeRolePrefix is a label prefix for node roles
  67. // It's copied over to here until it's merged in core: https://github.com/kubernetes/kubernetes/pull/39112
  68. labelNodeRolePrefix = "node-role.kubernetes.io/"
  69. // nodeLabelRole specifies the role of a node
  70. nodeLabelRole = "kubernetes.io/role"
  71. )
  72. // AddHandlers adds print handlers for default Kubernetes types dealing with internal versions.
  73. // TODO: handle errors from Handler
  74. func AddHandlers(h printers.PrintHandler) {
  75. podColumnDefinitions := []metav1.TableColumnDefinition{
  76. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  77. {Name: "Ready", Type: "string", Description: "The aggregate readiness state of this pod for accepting traffic."},
  78. {Name: "Status", Type: "string", Description: "The aggregate status of the containers in this pod."},
  79. {Name: "Restarts", Type: "integer", Description: "The number of times the containers in this pod have been restarted."},
  80. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  81. {Name: "IP", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["podIP"]},
  82. {Name: "Node", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["nodeName"]},
  83. {Name: "Nominated Node", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["nominatedNodeName"]},
  84. {Name: "Readiness Gates", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["readinessGates"]},
  85. }
  86. h.TableHandler(podColumnDefinitions, printPodList)
  87. h.TableHandler(podColumnDefinitions, printPod)
  88. podTemplateColumnDefinitions := []metav1.TableColumnDefinition{
  89. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  90. {Name: "Containers", Type: "string", Description: "Names of each container in the template."},
  91. {Name: "Images", Type: "string", Description: "Images referenced by each container in the template."},
  92. {Name: "Pod Labels", Type: "string", Description: "The labels for the pod template."},
  93. }
  94. h.TableHandler(podTemplateColumnDefinitions, printPodTemplate)
  95. h.TableHandler(podTemplateColumnDefinitions, printPodTemplateList)
  96. podDisruptionBudgetColumnDefinitions := []metav1.TableColumnDefinition{
  97. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  98. {Name: "Min Available", Type: "string", Description: "The minimum number of pods that must be available."},
  99. {Name: "Max Unavailable", Type: "string", Description: "The maximum number of pods that may be unavailable."},
  100. {Name: "Allowed Disruptions", Type: "integer", Description: "Calculated number of pods that may be disrupted at this time."},
  101. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  102. }
  103. h.TableHandler(podDisruptionBudgetColumnDefinitions, printPodDisruptionBudget)
  104. h.TableHandler(podDisruptionBudgetColumnDefinitions, printPodDisruptionBudgetList)
  105. replicationControllerColumnDefinitions := []metav1.TableColumnDefinition{
  106. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  107. {Name: "Desired", Type: "integer", Description: apiv1.ReplicationControllerSpec{}.SwaggerDoc()["replicas"]},
  108. {Name: "Current", Type: "integer", Description: apiv1.ReplicationControllerStatus{}.SwaggerDoc()["replicas"]},
  109. {Name: "Ready", Type: "integer", Description: apiv1.ReplicationControllerStatus{}.SwaggerDoc()["readyReplicas"]},
  110. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  111. {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."},
  112. {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."},
  113. {Name: "Selector", Type: "string", Priority: 1, Description: apiv1.ReplicationControllerSpec{}.SwaggerDoc()["selector"]},
  114. }
  115. h.TableHandler(replicationControllerColumnDefinitions, printReplicationController)
  116. h.TableHandler(replicationControllerColumnDefinitions, printReplicationControllerList)
  117. replicaSetColumnDefinitions := []metav1.TableColumnDefinition{
  118. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  119. {Name: "Desired", Type: "integer", Description: extensionsv1beta1.ReplicaSetSpec{}.SwaggerDoc()["replicas"]},
  120. {Name: "Current", Type: "integer", Description: extensionsv1beta1.ReplicaSetStatus{}.SwaggerDoc()["replicas"]},
  121. {Name: "Ready", Type: "integer", Description: extensionsv1beta1.ReplicaSetStatus{}.SwaggerDoc()["readyReplicas"]},
  122. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  123. {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."},
  124. {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."},
  125. {Name: "Selector", Type: "string", Priority: 1, Description: extensionsv1beta1.ReplicaSetSpec{}.SwaggerDoc()["selector"]},
  126. }
  127. h.TableHandler(replicaSetColumnDefinitions, printReplicaSet)
  128. h.TableHandler(replicaSetColumnDefinitions, printReplicaSetList)
  129. daemonSetColumnDefinitions := []metav1.TableColumnDefinition{
  130. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  131. {Name: "Desired", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["desiredNumberScheduled"]},
  132. {Name: "Current", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["currentNumberScheduled"]},
  133. {Name: "Ready", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["numberReady"]},
  134. {Name: "Up-to-date", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["updatedNumberScheduled"]},
  135. {Name: "Available", Type: "integer", Description: extensionsv1beta1.DaemonSetStatus{}.SwaggerDoc()["numberAvailable"]},
  136. {Name: "Node Selector", Type: "string", Description: apiv1.PodSpec{}.SwaggerDoc()["nodeSelector"]},
  137. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  138. {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."},
  139. {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."},
  140. {Name: "Selector", Type: "string", Priority: 1, Description: extensionsv1beta1.DaemonSetSpec{}.SwaggerDoc()["selector"]},
  141. }
  142. h.TableHandler(daemonSetColumnDefinitions, printDaemonSet)
  143. h.TableHandler(daemonSetColumnDefinitions, printDaemonSetList)
  144. jobColumnDefinitions := []metav1.TableColumnDefinition{
  145. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  146. {Name: "Completions", Type: "string", Description: batchv1.JobStatus{}.SwaggerDoc()["succeeded"]},
  147. {Name: "Duration", Type: "string", Description: "Time required to complete the job."},
  148. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  149. {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."},
  150. {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."},
  151. {Name: "Selector", Type: "string", Priority: 1, Description: batchv1.JobSpec{}.SwaggerDoc()["selector"]},
  152. }
  153. h.TableHandler(jobColumnDefinitions, printJob)
  154. h.TableHandler(jobColumnDefinitions, printJobList)
  155. cronJobColumnDefinitions := []metav1.TableColumnDefinition{
  156. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  157. {Name: "Schedule", Type: "string", Description: batchv1beta1.CronJobSpec{}.SwaggerDoc()["schedule"]},
  158. {Name: "Suspend", Type: "boolean", Description: batchv1beta1.CronJobSpec{}.SwaggerDoc()["suspend"]},
  159. {Name: "Active", Type: "integer", Description: batchv1beta1.CronJobStatus{}.SwaggerDoc()["active"]},
  160. {Name: "Last Schedule", Type: "string", Description: batchv1beta1.CronJobStatus{}.SwaggerDoc()["lastScheduleTime"]},
  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: batchv1.JobSpec{}.SwaggerDoc()["selector"]},
  165. }
  166. h.TableHandler(cronJobColumnDefinitions, printCronJob)
  167. h.TableHandler(cronJobColumnDefinitions, printCronJobList)
  168. serviceColumnDefinitions := []metav1.TableColumnDefinition{
  169. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  170. {Name: "Type", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["type"]},
  171. {Name: "Cluster-IP", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["clusterIP"]},
  172. {Name: "External-IP", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["externalIPs"]},
  173. {Name: "Port(s)", Type: "string", Description: apiv1.ServiceSpec{}.SwaggerDoc()["ports"]},
  174. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  175. {Name: "Selector", Type: "string", Priority: 1, Description: apiv1.ServiceSpec{}.SwaggerDoc()["selector"]},
  176. }
  177. h.TableHandler(serviceColumnDefinitions, printService)
  178. h.TableHandler(serviceColumnDefinitions, printServiceList)
  179. ingressColumnDefinitions := []metav1.TableColumnDefinition{
  180. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  181. {Name: "Hosts", Type: "string", Description: "Hosts that incoming requests are matched against before the ingress rule"},
  182. {Name: "Address", Type: "string", Description: "Address is a list containing ingress points for the load-balancer"},
  183. {Name: "Ports", Type: "string", Description: "Ports of TLS configurations that open"},
  184. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  185. }
  186. h.TableHandler(ingressColumnDefinitions, printIngress)
  187. h.TableHandler(ingressColumnDefinitions, printIngressList)
  188. statefulSetColumnDefinitions := []metav1.TableColumnDefinition{
  189. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  190. {Name: "Ready", Type: "string", Description: "Number of the pod with ready state"},
  191. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  192. {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."},
  193. {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."},
  194. }
  195. h.TableHandler(statefulSetColumnDefinitions, printStatefulSet)
  196. h.TableHandler(statefulSetColumnDefinitions, printStatefulSetList)
  197. endpointColumnDefinitions := []metav1.TableColumnDefinition{
  198. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  199. {Name: "Endpoints", Type: "string", Description: apiv1.Endpoints{}.SwaggerDoc()["subsets"]},
  200. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  201. }
  202. h.TableHandler(endpointColumnDefinitions, printEndpoints)
  203. h.TableHandler(endpointColumnDefinitions, printEndpointsList)
  204. nodeColumnDefinitions := []metav1.TableColumnDefinition{
  205. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  206. {Name: "Status", Type: "string", Description: "The status of the node"},
  207. {Name: "Roles", Type: "string", Description: "The roles of the node"},
  208. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  209. {Name: "Version", Type: "string", Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kubeletVersion"]},
  210. {Name: "Internal-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]},
  211. {Name: "External-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]},
  212. {Name: "OS-Image", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["osImage"]},
  213. {Name: "Kernel-Version", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kernelVersion"]},
  214. {Name: "Container-Runtime", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["containerRuntimeVersion"]},
  215. }
  216. h.TableHandler(nodeColumnDefinitions, printNode)
  217. h.TableHandler(nodeColumnDefinitions, printNodeList)
  218. eventColumnDefinitions := []metav1.TableColumnDefinition{
  219. {Name: "Last Seen", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["lastTimestamp"]},
  220. {Name: "Type", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["type"]},
  221. {Name: "Reason", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["reason"]},
  222. {Name: "Object", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["involvedObject"]},
  223. {Name: "Subobject", Type: "string", Priority: 1, Description: apiv1.Event{}.InvolvedObject.SwaggerDoc()["fieldPath"]},
  224. {Name: "Source", Type: "string", Priority: 1, Description: apiv1.Event{}.SwaggerDoc()["source"]},
  225. {Name: "Message", Type: "string", Description: apiv1.Event{}.SwaggerDoc()["message"]},
  226. {Name: "First Seen", Type: "string", Priority: 1, Description: apiv1.Event{}.SwaggerDoc()["firstTimestamp"]},
  227. {Name: "Count", Type: "string", Priority: 1, Description: apiv1.Event{}.SwaggerDoc()["count"]},
  228. {Name: "Name", Type: "string", Priority: 1, Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  229. }
  230. h.TableHandler(eventColumnDefinitions, printEvent)
  231. h.TableHandler(eventColumnDefinitions, printEventList)
  232. namespaceColumnDefinitions := []metav1.TableColumnDefinition{
  233. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  234. {Name: "Status", Type: "string", Description: "The status of the namespace"},
  235. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  236. }
  237. h.TableHandler(namespaceColumnDefinitions, printNamespace)
  238. h.TableHandler(namespaceColumnDefinitions, printNamespaceList)
  239. secretColumnDefinitions := []metav1.TableColumnDefinition{
  240. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  241. {Name: "Type", Type: "string", Description: apiv1.Secret{}.SwaggerDoc()["type"]},
  242. {Name: "Data", Type: "string", Description: apiv1.Secret{}.SwaggerDoc()["data"]},
  243. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  244. }
  245. h.TableHandler(secretColumnDefinitions, printSecret)
  246. h.TableHandler(secretColumnDefinitions, printSecretList)
  247. serviceAccountColumnDefinitions := []metav1.TableColumnDefinition{
  248. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  249. {Name: "Secrets", Type: "string", Description: apiv1.ServiceAccount{}.SwaggerDoc()["secrets"]},
  250. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  251. }
  252. h.TableHandler(serviceAccountColumnDefinitions, printServiceAccount)
  253. h.TableHandler(serviceAccountColumnDefinitions, printServiceAccountList)
  254. persistentVolumeColumnDefinitions := []metav1.TableColumnDefinition{
  255. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  256. {Name: "Capacity", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["capacity"]},
  257. {Name: "Access Modes", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["accessModes"]},
  258. {Name: "Reclaim Policy", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["persistentVolumeReclaimPolicy"]},
  259. {Name: "Status", Type: "string", Description: apiv1.PersistentVolumeStatus{}.SwaggerDoc()["phase"]},
  260. {Name: "Claim", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["claimRef"]},
  261. {Name: "StorageClass", Type: "string", Description: "StorageClass of the pv"},
  262. {Name: "Reason", Type: "string", Description: apiv1.PersistentVolumeStatus{}.SwaggerDoc()["reason"]},
  263. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  264. {Name: "VolumeMode", Type: "string", Priority: 1, Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["volumeMode"]},
  265. }
  266. h.TableHandler(persistentVolumeColumnDefinitions, printPersistentVolume)
  267. h.TableHandler(persistentVolumeColumnDefinitions, printPersistentVolumeList)
  268. persistentVolumeClaimColumnDefinitions := []metav1.TableColumnDefinition{
  269. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  270. {Name: "Status", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["phase"]},
  271. {Name: "Volume", Type: "string", Description: apiv1.PersistentVolumeClaimSpec{}.SwaggerDoc()["volumeName"]},
  272. {Name: "Capacity", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["capacity"]},
  273. {Name: "Access Modes", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["accessModes"]},
  274. {Name: "StorageClass", Type: "string", Description: "StorageClass of the pvc"},
  275. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  276. {Name: "VolumeMode", Type: "string", Priority: 1, Description: apiv1.PersistentVolumeClaimSpec{}.SwaggerDoc()["volumeMode"]},
  277. }
  278. h.TableHandler(persistentVolumeClaimColumnDefinitions, printPersistentVolumeClaim)
  279. h.TableHandler(persistentVolumeClaimColumnDefinitions, printPersistentVolumeClaimList)
  280. componentStatusColumnDefinitions := []metav1.TableColumnDefinition{
  281. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  282. {Name: "Status", Type: "string", Description: "Status of the component conditions"},
  283. {Name: "Message", Type: "string", Description: "Message of the component conditions"},
  284. {Name: "Error", Type: "string", Description: "Error of the component conditions"},
  285. }
  286. h.TableHandler(componentStatusColumnDefinitions, printComponentStatus)
  287. h.TableHandler(componentStatusColumnDefinitions, printComponentStatusList)
  288. deploymentColumnDefinitions := []metav1.TableColumnDefinition{
  289. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  290. {Name: "Ready", Type: "string", Description: "Number of the pod with ready state"},
  291. {Name: "Up-to-date", Type: "string", Description: extensionsv1beta1.DeploymentStatus{}.SwaggerDoc()["updatedReplicas"]},
  292. {Name: "Available", Type: "string", Description: extensionsv1beta1.DeploymentStatus{}.SwaggerDoc()["availableReplicas"]},
  293. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  294. {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."},
  295. {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."},
  296. {Name: "Selector", Type: "string", Priority: 1, Description: extensionsv1beta1.DeploymentSpec{}.SwaggerDoc()["selector"]},
  297. }
  298. h.TableHandler(deploymentColumnDefinitions, printDeployment)
  299. h.TableHandler(deploymentColumnDefinitions, printDeploymentList)
  300. horizontalPodAutoscalerColumnDefinitions := []metav1.TableColumnDefinition{
  301. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  302. {Name: "Reference", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["scaleTargetRef"]},
  303. {Name: "Targets", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["metrics"]},
  304. {Name: "MinPods", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["minReplicas"]},
  305. {Name: "MaxPods", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerSpec{}.SwaggerDoc()["maxReplicas"]},
  306. {Name: "Replicas", Type: "string", Description: autoscalingv2beta1.HorizontalPodAutoscalerStatus{}.SwaggerDoc()["currentReplicas"]},
  307. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  308. }
  309. h.TableHandler(horizontalPodAutoscalerColumnDefinitions, printHorizontalPodAutoscaler)
  310. h.TableHandler(horizontalPodAutoscalerColumnDefinitions, printHorizontalPodAutoscalerList)
  311. configMapColumnDefinitions := []metav1.TableColumnDefinition{
  312. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  313. {Name: "Data", Type: "string", Description: apiv1.ConfigMap{}.SwaggerDoc()["data"]},
  314. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  315. }
  316. h.TableHandler(configMapColumnDefinitions, printConfigMap)
  317. h.TableHandler(configMapColumnDefinitions, printConfigMapList)
  318. podSecurityPolicyColumnDefinitions := []metav1.TableColumnDefinition{
  319. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  320. {Name: "Priv", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["privileged"]},
  321. {Name: "Caps", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["allowedCapabilities"]},
  322. {Name: "SELinux", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["seLinux"]},
  323. {Name: "RunAsUser", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["runAsUser"]},
  324. {Name: "FsGroup", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["fsGroup"]},
  325. {Name: "SupGroup", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["supplementalGroups"]},
  326. {Name: "ReadOnlyRootFs", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["readOnlyRootFilesystem"]},
  327. {Name: "Volumes", Type: "string", Description: policyv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["volumes"]},
  328. }
  329. h.TableHandler(podSecurityPolicyColumnDefinitions, printPodSecurityPolicy)
  330. h.TableHandler(podSecurityPolicyColumnDefinitions, printPodSecurityPolicyList)
  331. networkPolicyColumnDefinitioins := []metav1.TableColumnDefinition{
  332. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  333. {Name: "Pod-Selector", Type: "string", Description: extensionsv1beta1.NetworkPolicySpec{}.SwaggerDoc()["podSelector"]},
  334. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  335. }
  336. h.TableHandler(networkPolicyColumnDefinitioins, printNetworkPolicy)
  337. h.TableHandler(networkPolicyColumnDefinitioins, printNetworkPolicyList)
  338. roleBindingsColumnDefinitions := []metav1.TableColumnDefinition{
  339. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  340. {Name: "Role", Type: "string", Description: rbacv1beta1.RoleBinding{}.SwaggerDoc()["roleRef"]},
  341. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  342. {Name: "Users", Type: "string", Priority: 1, Description: "Users in the roleBinding"},
  343. {Name: "Groups", Type: "string", Priority: 1, Description: "Groups in the roleBinding"},
  344. {Name: "ServiceAccounts", Type: "string", Priority: 1, Description: "ServiceAccounts in the roleBinding"},
  345. }
  346. h.TableHandler(roleBindingsColumnDefinitions, printRoleBinding)
  347. h.TableHandler(roleBindingsColumnDefinitions, printRoleBindingList)
  348. clusterRoleBindingsColumnDefinitions := []metav1.TableColumnDefinition{
  349. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  350. {Name: "Role", Type: "string", Description: rbacv1beta1.ClusterRoleBinding{}.SwaggerDoc()["roleRef"]},
  351. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  352. {Name: "Users", Type: "string", Priority: 1, Description: "Users in the clusterRoleBinding"},
  353. {Name: "Groups", Type: "string", Priority: 1, Description: "Groups in the clusterRoleBinding"},
  354. {Name: "ServiceAccounts", Type: "string", Priority: 1, Description: "ServiceAccounts in the clusterRoleBinding"},
  355. }
  356. h.TableHandler(clusterRoleBindingsColumnDefinitions, printClusterRoleBinding)
  357. h.TableHandler(clusterRoleBindingsColumnDefinitions, printClusterRoleBindingList)
  358. certificateSigningRequestColumnDefinitions := []metav1.TableColumnDefinition{
  359. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  360. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  361. {Name: "Requestor", Type: "string", Description: certificatesv1beta1.CertificateSigningRequestSpec{}.SwaggerDoc()["request"]},
  362. {Name: "Condition", Type: "string", Description: certificatesv1beta1.CertificateSigningRequestStatus{}.SwaggerDoc()["conditions"]},
  363. }
  364. h.TableHandler(certificateSigningRequestColumnDefinitions, printCertificateSigningRequest)
  365. h.TableHandler(certificateSigningRequestColumnDefinitions, printCertificateSigningRequestList)
  366. leaseColumnDefinitions := []metav1.TableColumnDefinition{
  367. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  368. {Name: "Holder", Type: "string", Description: coordinationv1.LeaseSpec{}.SwaggerDoc()["holderIdentity"]},
  369. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  370. }
  371. h.TableHandler(leaseColumnDefinitions, printLease)
  372. h.TableHandler(leaseColumnDefinitions, printLeaseList)
  373. storageClassColumnDefinitions := []metav1.TableColumnDefinition{
  374. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  375. {Name: "Provisioner", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["provisioner"]},
  376. {Name: "ReclaimPolicy", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["reclaimPolicy"]},
  377. {Name: "VolumeBindingMode", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["volumeBindingMode"]},
  378. {Name: "AllowVolumeExpansion", Type: "string", Description: storagev1.StorageClass{}.SwaggerDoc()["allowVolumeExpansion"]},
  379. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  380. }
  381. h.TableHandler(storageClassColumnDefinitions, printStorageClass)
  382. h.TableHandler(storageClassColumnDefinitions, printStorageClassList)
  383. statusColumnDefinitions := []metav1.TableColumnDefinition{
  384. {Name: "Status", Type: "string", Description: metav1.Status{}.SwaggerDoc()["status"]},
  385. {Name: "Reason", Type: "string", Description: metav1.Status{}.SwaggerDoc()["reason"]},
  386. {Name: "Message", Type: "string", Description: metav1.Status{}.SwaggerDoc()["Message"]},
  387. }
  388. h.TableHandler(statusColumnDefinitions, printStatus)
  389. controllerRevisionColumnDefinition := []metav1.TableColumnDefinition{
  390. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  391. {Name: "Controller", Type: "string", Description: "Controller of the object"},
  392. {Name: "Revision", Type: "string", Description: appsv1beta1.ControllerRevision{}.SwaggerDoc()["revision"]},
  393. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  394. }
  395. h.TableHandler(controllerRevisionColumnDefinition, printControllerRevision)
  396. h.TableHandler(controllerRevisionColumnDefinition, printControllerRevisionList)
  397. resourceQuotaColumnDefinitions := []metav1.TableColumnDefinition{
  398. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  399. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  400. {Name: "Request", Type: "string", Description: "Request represents a minimum amount of cpu/memory that a container may consume."},
  401. {Name: "Limit", Type: "string", Description: "Limits control the maximum amount of cpu/memory that a container may use independent of contention on the node."},
  402. }
  403. h.TableHandler(resourceQuotaColumnDefinitions, printResourceQuota)
  404. h.TableHandler(resourceQuotaColumnDefinitions, printResourceQuotaList)
  405. priorityClassColumnDefinitions := []metav1.TableColumnDefinition{
  406. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  407. {Name: "Value", Type: "integer", Description: schedulingv1.PriorityClass{}.SwaggerDoc()["value"]},
  408. {Name: "Global-Default", Type: "boolean", Description: schedulingv1.PriorityClass{}.SwaggerDoc()["globalDefault"]},
  409. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  410. }
  411. h.TableHandler(priorityClassColumnDefinitions, printPriorityClass)
  412. h.TableHandler(priorityClassColumnDefinitions, printPriorityClassList)
  413. runtimeClassColumnDefinitions := []metav1.TableColumnDefinition{
  414. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  415. {Name: "Handler", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["handler"]},
  416. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  417. }
  418. h.TableHandler(runtimeClassColumnDefinitions, printRuntimeClass)
  419. h.TableHandler(runtimeClassColumnDefinitions, printRuntimeClassList)
  420. volumeAttachmentColumnDefinitions := []metav1.TableColumnDefinition{
  421. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  422. {Name: "Attacher", Type: "string", Format: "name", Description: storagev1.VolumeAttachmentSpec{}.SwaggerDoc()["attacher"]},
  423. {Name: "PV", Type: "string", Description: storagev1.VolumeAttachmentSource{}.SwaggerDoc()["persistentVolumeName"]},
  424. {Name: "Node", Type: "string", Description: storagev1.VolumeAttachmentSpec{}.SwaggerDoc()["nodeName"]},
  425. {Name: "Attached", Type: "boolean", Description: storagev1.VolumeAttachmentStatus{}.SwaggerDoc()["attached"]},
  426. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  427. }
  428. h.TableHandler(volumeAttachmentColumnDefinitions, printVolumeAttachment)
  429. h.TableHandler(volumeAttachmentColumnDefinitions, printVolumeAttachmentList)
  430. endpointSliceColumnDefinitions := []metav1.TableColumnDefinition{
  431. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  432. {Name: "AddressType", Type: "string", Description: discoveryv1beta1.EndpointSlice{}.SwaggerDoc()["addressType"]},
  433. {Name: "Ports", Type: "string", Description: discoveryv1beta1.EndpointSlice{}.SwaggerDoc()["ports"]},
  434. {Name: "Endpoints", Type: "string", Description: discoveryv1beta1.EndpointSlice{}.SwaggerDoc()["endpoints"]},
  435. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  436. }
  437. h.TableHandler(endpointSliceColumnDefinitions, printEndpointSlice)
  438. h.TableHandler(endpointSliceColumnDefinitions, printEndpointSliceList)
  439. csiNodeColumnDefinitions := []metav1.TableColumnDefinition{
  440. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  441. {Name: "Drivers", Type: "integer", Description: "Drivers indicates the number of CSI drivers registered on the node"},
  442. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  443. }
  444. h.TableHandler(csiNodeColumnDefinitions, printCSINode)
  445. h.TableHandler(csiNodeColumnDefinitions, printCSINodeList)
  446. csiDriverColumnDefinitions := []metav1.TableColumnDefinition{
  447. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  448. {Name: "AttachRequired", Type: "boolean", Description: storagev1beta1.CSIDriverSpec{}.SwaggerDoc()["attachRequired"]},
  449. {Name: "PodInfoOnMount", Type: "boolean", Description: storagev1beta1.CSIDriverSpec{}.SwaggerDoc()["podInfoOnMount"]},
  450. {Name: "Modes", Type: "string", Description: storagev1beta1.CSIDriverSpec{}.SwaggerDoc()["volumeLifecycleModes"]},
  451. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  452. }
  453. h.TableHandler(csiDriverColumnDefinitions, printCSIDriver)
  454. h.TableHandler(csiDriverColumnDefinitions, printCSIDriverList)
  455. mutatingWebhookColumnDefinitions := []metav1.TableColumnDefinition{
  456. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  457. {Name: "Webhooks", Type: "integer", Description: "Webhooks indicates the number of webhooks registered in this configuration"},
  458. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  459. }
  460. h.TableHandler(mutatingWebhookColumnDefinitions, printMutatingWebhook)
  461. h.TableHandler(mutatingWebhookColumnDefinitions, printMutatingWebhookList)
  462. validatingWebhookColumnDefinitions := []metav1.TableColumnDefinition{
  463. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  464. {Name: "Webhooks", Type: "integer", Description: "Webhooks indicates the number of webhooks registered in this configuration"},
  465. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  466. }
  467. h.TableHandler(validatingWebhookColumnDefinitions, printValidatingWebhook)
  468. h.TableHandler(validatingWebhookColumnDefinitions, printValidatingWebhookList)
  469. flowSchemaColumnDefinitions := []metav1.TableColumnDefinition{
  470. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  471. {Name: "PriorityLevel", Type: "string", Description: flowcontrolv1alpha1.PriorityLevelConfigurationReference{}.SwaggerDoc()["name"]},
  472. {Name: "MatchingPrecedence", Type: "string", Description: flowcontrolv1alpha1.FlowSchemaSpec{}.SwaggerDoc()["matchingPrecedence"]},
  473. {Name: "DistinguisherMethod", Type: "string", Description: flowcontrolv1alpha1.FlowSchemaSpec{}.SwaggerDoc()["distinguisherMethod"]},
  474. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  475. {Name: "MissingPL", Type: "string", Description: "references a broken or non-existent PriorityLevelConfiguration"},
  476. }
  477. h.TableHandler(flowSchemaColumnDefinitions, printFlowSchema)
  478. h.TableHandler(flowSchemaColumnDefinitions, printFlowSchemaList)
  479. priorityLevelColumnDefinitions := []metav1.TableColumnDefinition{
  480. {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
  481. {Name: "Type", Type: "string", Description: flowcontrolv1alpha1.PriorityLevelConfigurationSpec{}.SwaggerDoc()["type"]},
  482. {Name: "AssuredConcurrencyShares", Type: "string", Description: flowcontrolv1alpha1.LimitedPriorityLevelConfiguration{}.SwaggerDoc()["assuredConcurrencyShares"]},
  483. {Name: "Queues", Type: "string", Description: flowcontrolv1alpha1.QueuingConfiguration{}.SwaggerDoc()["queues"]},
  484. {Name: "HandSize", Type: "string", Description: flowcontrolv1alpha1.QueuingConfiguration{}.SwaggerDoc()["handSize"]},
  485. {Name: "QueueLengthLimit", Type: "string", Description: flowcontrolv1alpha1.QueuingConfiguration{}.SwaggerDoc()["queueLengthLimit"]},
  486. {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
  487. }
  488. h.TableHandler(priorityLevelColumnDefinitions, printPriorityLevelConfiguration)
  489. h.TableHandler(priorityLevelColumnDefinitions, printPriorityLevelConfigurationList)
  490. }
  491. // Pass ports=nil for all ports.
  492. func formatEndpoints(endpoints *api.Endpoints, ports sets.String) string {
  493. if len(endpoints.Subsets) == 0 {
  494. return "<none>"
  495. }
  496. list := []string{}
  497. max := 3
  498. more := false
  499. count := 0
  500. for i := range endpoints.Subsets {
  501. ss := &endpoints.Subsets[i]
  502. if len(ss.Ports) == 0 {
  503. // It's possible to have headless services with no ports.
  504. for i := range ss.Addresses {
  505. if len(list) == max {
  506. more = true
  507. }
  508. if !more {
  509. list = append(list, ss.Addresses[i].IP)
  510. }
  511. count++
  512. }
  513. } else {
  514. // "Normal" services with ports defined.
  515. for i := range ss.Ports {
  516. port := &ss.Ports[i]
  517. if ports == nil || ports.Has(port.Name) {
  518. for i := range ss.Addresses {
  519. if len(list) == max {
  520. more = true
  521. }
  522. addr := &ss.Addresses[i]
  523. if !more {
  524. hostPort := net.JoinHostPort(addr.IP, strconv.Itoa(int(port.Port)))
  525. list = append(list, hostPort)
  526. }
  527. count++
  528. }
  529. }
  530. }
  531. }
  532. }
  533. ret := strings.Join(list, ",")
  534. if more {
  535. return fmt.Sprintf("%s + %d more...", ret, count-max)
  536. }
  537. return ret
  538. }
  539. func formatDiscoveryPorts(ports []discovery.EndpointPort) string {
  540. list := []string{}
  541. max := 3
  542. more := false
  543. count := 0
  544. for _, port := range ports {
  545. if len(list) < max {
  546. portNum := "*"
  547. if port.Port != nil {
  548. portNum = strconv.Itoa(int(*port.Port))
  549. } else if port.Name != nil {
  550. portNum = *port.Name
  551. }
  552. list = append(list, portNum)
  553. } else if len(list) == max {
  554. more = true
  555. }
  556. count++
  557. }
  558. return listWithMoreString(list, more, count, max)
  559. }
  560. func formatDiscoveryEndpoints(endpoints []discovery.Endpoint) string {
  561. list := []string{}
  562. max := 3
  563. more := false
  564. count := 0
  565. for _, endpoint := range endpoints {
  566. for _, address := range endpoint.Addresses {
  567. if len(list) < max {
  568. list = append(list, address)
  569. } else if len(list) == max {
  570. more = true
  571. }
  572. count++
  573. }
  574. }
  575. return listWithMoreString(list, more, count, max)
  576. }
  577. func listWithMoreString(list []string, more bool, count, max int) string {
  578. ret := strings.Join(list, ",")
  579. if more {
  580. return fmt.Sprintf("%s + %d more...", ret, count-max)
  581. }
  582. if ret == "" {
  583. ret = "<unset>"
  584. }
  585. return ret
  586. }
  587. // translateTimestampSince returns the elapsed time since timestamp in
  588. // human-readable approximation.
  589. func translateTimestampSince(timestamp metav1.Time) string {
  590. if timestamp.IsZero() {
  591. return "<unknown>"
  592. }
  593. return duration.HumanDuration(time.Since(timestamp.Time))
  594. }
  595. // translateTimestampUntil returns the elapsed time until timestamp in
  596. // human-readable approximation.
  597. func translateTimestampUntil(timestamp metav1.Time) string {
  598. if timestamp.IsZero() {
  599. return "<unknown>"
  600. }
  601. return duration.HumanDuration(time.Until(timestamp.Time))
  602. }
  603. var (
  604. podSuccessConditions = []metav1.TableRowCondition{{Type: metav1.RowCompleted, Status: metav1.ConditionTrue, Reason: string(api.PodSucceeded), Message: "The pod has completed successfully."}}
  605. podFailedConditions = []metav1.TableRowCondition{{Type: metav1.RowCompleted, Status: metav1.ConditionTrue, Reason: string(api.PodFailed), Message: "The pod failed."}}
  606. )
  607. func printPodList(podList *api.PodList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  608. rows := make([]metav1.TableRow, 0, len(podList.Items))
  609. for i := range podList.Items {
  610. r, err := printPod(&podList.Items[i], options)
  611. if err != nil {
  612. return nil, err
  613. }
  614. rows = append(rows, r...)
  615. }
  616. return rows, nil
  617. }
  618. func printPod(pod *api.Pod, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  619. restarts := 0
  620. totalContainers := len(pod.Spec.Containers)
  621. readyContainers := 0
  622. reason := string(pod.Status.Phase)
  623. if pod.Status.Reason != "" {
  624. reason = pod.Status.Reason
  625. }
  626. row := metav1.TableRow{
  627. Object: runtime.RawExtension{Object: pod},
  628. }
  629. switch pod.Status.Phase {
  630. case api.PodSucceeded:
  631. row.Conditions = podSuccessConditions
  632. case api.PodFailed:
  633. row.Conditions = podFailedConditions
  634. }
  635. initializing := false
  636. for i := range pod.Status.InitContainerStatuses {
  637. container := pod.Status.InitContainerStatuses[i]
  638. restarts += int(container.RestartCount)
  639. switch {
  640. case container.State.Terminated != nil && container.State.Terminated.ExitCode == 0:
  641. continue
  642. case container.State.Terminated != nil:
  643. // initialization is failed
  644. if len(container.State.Terminated.Reason) == 0 {
  645. if container.State.Terminated.Signal != 0 {
  646. reason = fmt.Sprintf("Init:Signal:%d", container.State.Terminated.Signal)
  647. } else {
  648. reason = fmt.Sprintf("Init:ExitCode:%d", container.State.Terminated.ExitCode)
  649. }
  650. } else {
  651. reason = "Init:" + container.State.Terminated.Reason
  652. }
  653. initializing = true
  654. case container.State.Waiting != nil && len(container.State.Waiting.Reason) > 0 && container.State.Waiting.Reason != "PodInitializing":
  655. reason = "Init:" + container.State.Waiting.Reason
  656. initializing = true
  657. default:
  658. reason = fmt.Sprintf("Init:%d/%d", i, len(pod.Spec.InitContainers))
  659. initializing = true
  660. }
  661. break
  662. }
  663. if !initializing {
  664. restarts = 0
  665. hasRunning := false
  666. for i := len(pod.Status.ContainerStatuses) - 1; i >= 0; i-- {
  667. container := pod.Status.ContainerStatuses[i]
  668. restarts += int(container.RestartCount)
  669. if container.State.Waiting != nil && container.State.Waiting.Reason != "" {
  670. reason = container.State.Waiting.Reason
  671. } else if container.State.Terminated != nil && container.State.Terminated.Reason != "" {
  672. reason = container.State.Terminated.Reason
  673. } else if container.State.Terminated != nil && container.State.Terminated.Reason == "" {
  674. if container.State.Terminated.Signal != 0 {
  675. reason = fmt.Sprintf("Signal:%d", container.State.Terminated.Signal)
  676. } else {
  677. reason = fmt.Sprintf("ExitCode:%d", container.State.Terminated.ExitCode)
  678. }
  679. } else if container.Ready && container.State.Running != nil {
  680. hasRunning = true
  681. readyContainers++
  682. }
  683. }
  684. // change pod status back to "Running" if there is at least one container still reporting as "Running" status
  685. if reason == "Completed" && hasRunning {
  686. reason = "Running"
  687. }
  688. }
  689. if pod.DeletionTimestamp != nil && pod.Status.Reason == node.NodeUnreachablePodReason {
  690. reason = "Unknown"
  691. } else if pod.DeletionTimestamp != nil {
  692. reason = "Terminating"
  693. }
  694. row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, int64(restarts), translateTimestampSince(pod.CreationTimestamp))
  695. if options.Wide {
  696. nodeName := pod.Spec.NodeName
  697. nominatedNodeName := pod.Status.NominatedNodeName
  698. podIP := ""
  699. if len(pod.Status.PodIPs) > 0 {
  700. podIP = pod.Status.PodIPs[0].IP
  701. }
  702. if podIP == "" {
  703. podIP = "<none>"
  704. }
  705. if nodeName == "" {
  706. nodeName = "<none>"
  707. }
  708. if nominatedNodeName == "" {
  709. nominatedNodeName = "<none>"
  710. }
  711. readinessGates := "<none>"
  712. if len(pod.Spec.ReadinessGates) > 0 {
  713. trueConditions := 0
  714. for _, readinessGate := range pod.Spec.ReadinessGates {
  715. conditionType := readinessGate.ConditionType
  716. for _, condition := range pod.Status.Conditions {
  717. if condition.Type == conditionType {
  718. if condition.Status == api.ConditionTrue {
  719. trueConditions++
  720. }
  721. break
  722. }
  723. }
  724. }
  725. readinessGates = fmt.Sprintf("%d/%d", trueConditions, len(pod.Spec.ReadinessGates))
  726. }
  727. row.Cells = append(row.Cells, podIP, nodeName, nominatedNodeName, readinessGates)
  728. }
  729. return []metav1.TableRow{row}, nil
  730. }
  731. func printPodTemplate(obj *api.PodTemplate, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  732. row := metav1.TableRow{
  733. Object: runtime.RawExtension{Object: obj},
  734. }
  735. names, images := layoutContainerCells(obj.Template.Spec.Containers)
  736. row.Cells = append(row.Cells, obj.Name, names, images, labels.FormatLabels(obj.Template.Labels))
  737. return []metav1.TableRow{row}, nil
  738. }
  739. func printPodTemplateList(list *api.PodTemplateList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  740. rows := make([]metav1.TableRow, 0, len(list.Items))
  741. for i := range list.Items {
  742. r, err := printPodTemplate(&list.Items[i], options)
  743. if err != nil {
  744. return nil, err
  745. }
  746. rows = append(rows, r...)
  747. }
  748. return rows, nil
  749. }
  750. func printPodDisruptionBudget(obj *policy.PodDisruptionBudget, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  751. row := metav1.TableRow{
  752. Object: runtime.RawExtension{Object: obj},
  753. }
  754. var minAvailable string
  755. var maxUnavailable string
  756. if obj.Spec.MinAvailable != nil {
  757. minAvailable = obj.Spec.MinAvailable.String()
  758. } else {
  759. minAvailable = "N/A"
  760. }
  761. if obj.Spec.MaxUnavailable != nil {
  762. maxUnavailable = obj.Spec.MaxUnavailable.String()
  763. } else {
  764. maxUnavailable = "N/A"
  765. }
  766. row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, int64(obj.Status.DisruptionsAllowed), translateTimestampSince(obj.CreationTimestamp))
  767. return []metav1.TableRow{row}, nil
  768. }
  769. func printPodDisruptionBudgetList(list *policy.PodDisruptionBudgetList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  770. rows := make([]metav1.TableRow, 0, len(list.Items))
  771. for i := range list.Items {
  772. r, err := printPodDisruptionBudget(&list.Items[i], options)
  773. if err != nil {
  774. return nil, err
  775. }
  776. rows = append(rows, r...)
  777. }
  778. return rows, nil
  779. }
  780. // TODO(AdoHe): try to put wide output in a single method
  781. func printReplicationController(obj *api.ReplicationController, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  782. row := metav1.TableRow{
  783. Object: runtime.RawExtension{Object: obj},
  784. }
  785. desiredReplicas := obj.Spec.Replicas
  786. currentReplicas := obj.Status.Replicas
  787. readyReplicas := obj.Status.ReadyReplicas
  788. row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestampSince(obj.CreationTimestamp))
  789. if options.Wide {
  790. names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
  791. row.Cells = append(row.Cells, names, images, labels.FormatLabels(obj.Spec.Selector))
  792. }
  793. return []metav1.TableRow{row}, nil
  794. }
  795. func printReplicationControllerList(list *api.ReplicationControllerList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  796. rows := make([]metav1.TableRow, 0, len(list.Items))
  797. for i := range list.Items {
  798. r, err := printReplicationController(&list.Items[i], options)
  799. if err != nil {
  800. return nil, err
  801. }
  802. rows = append(rows, r...)
  803. }
  804. return rows, nil
  805. }
  806. func printReplicaSet(obj *apps.ReplicaSet, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  807. row := metav1.TableRow{
  808. Object: runtime.RawExtension{Object: obj},
  809. }
  810. desiredReplicas := obj.Spec.Replicas
  811. currentReplicas := obj.Status.Replicas
  812. readyReplicas := obj.Status.ReadyReplicas
  813. row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestampSince(obj.CreationTimestamp))
  814. if options.Wide {
  815. names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
  816. row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector))
  817. }
  818. return []metav1.TableRow{row}, nil
  819. }
  820. func printReplicaSetList(list *apps.ReplicaSetList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  821. rows := make([]metav1.TableRow, 0, len(list.Items))
  822. for i := range list.Items {
  823. r, err := printReplicaSet(&list.Items[i], options)
  824. if err != nil {
  825. return nil, err
  826. }
  827. rows = append(rows, r...)
  828. }
  829. return rows, nil
  830. }
  831. func printJob(obj *batch.Job, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  832. row := metav1.TableRow{
  833. Object: runtime.RawExtension{Object: obj},
  834. }
  835. var completions string
  836. if obj.Spec.Completions != nil {
  837. completions = fmt.Sprintf("%d/%d", obj.Status.Succeeded, *obj.Spec.Completions)
  838. } else {
  839. parallelism := int32(0)
  840. if obj.Spec.Parallelism != nil {
  841. parallelism = *obj.Spec.Parallelism
  842. }
  843. if parallelism > 1 {
  844. completions = fmt.Sprintf("%d/1 of %d", obj.Status.Succeeded, parallelism)
  845. } else {
  846. completions = fmt.Sprintf("%d/1", obj.Status.Succeeded)
  847. }
  848. }
  849. var jobDuration string
  850. switch {
  851. case obj.Status.StartTime == nil:
  852. case obj.Status.CompletionTime == nil:
  853. jobDuration = duration.HumanDuration(time.Since(obj.Status.StartTime.Time))
  854. default:
  855. jobDuration = duration.HumanDuration(obj.Status.CompletionTime.Sub(obj.Status.StartTime.Time))
  856. }
  857. row.Cells = append(row.Cells, obj.Name, completions, jobDuration, translateTimestampSince(obj.CreationTimestamp))
  858. if options.Wide {
  859. names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
  860. row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector))
  861. }
  862. return []metav1.TableRow{row}, nil
  863. }
  864. func printJobList(list *batch.JobList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  865. rows := make([]metav1.TableRow, 0, len(list.Items))
  866. for i := range list.Items {
  867. r, err := printJob(&list.Items[i], options)
  868. if err != nil {
  869. return nil, err
  870. }
  871. rows = append(rows, r...)
  872. }
  873. return rows, nil
  874. }
  875. func printCronJob(obj *batch.CronJob, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  876. row := metav1.TableRow{
  877. Object: runtime.RawExtension{Object: obj},
  878. }
  879. lastScheduleTime := "<none>"
  880. if obj.Status.LastScheduleTime != nil {
  881. lastScheduleTime = translateTimestampSince(*obj.Status.LastScheduleTime)
  882. }
  883. row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), int64(len(obj.Status.Active)), lastScheduleTime, translateTimestampSince(obj.CreationTimestamp))
  884. if options.Wide {
  885. names, images := layoutContainerCells(obj.Spec.JobTemplate.Spec.Template.Spec.Containers)
  886. row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.JobTemplate.Spec.Selector))
  887. }
  888. return []metav1.TableRow{row}, nil
  889. }
  890. func printCronJobList(list *batch.CronJobList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  891. rows := make([]metav1.TableRow, 0, len(list.Items))
  892. for i := range list.Items {
  893. r, err := printCronJob(&list.Items[i], options)
  894. if err != nil {
  895. return nil, err
  896. }
  897. rows = append(rows, r...)
  898. }
  899. return rows, nil
  900. }
  901. // loadBalancerStatusStringer behaves mostly like a string interface and converts the given status to a string.
  902. // `wide` indicates whether the returned value is meant for --o=wide output. If not, it's clipped to 16 bytes.
  903. func loadBalancerStatusStringer(s api.LoadBalancerStatus, wide bool) string {
  904. ingress := s.Ingress
  905. result := sets.NewString()
  906. for i := range ingress {
  907. if ingress[i].IP != "" {
  908. result.Insert(ingress[i].IP)
  909. } else if ingress[i].Hostname != "" {
  910. result.Insert(ingress[i].Hostname)
  911. }
  912. }
  913. r := strings.Join(result.List(), ",")
  914. if !wide && len(r) > loadBalancerWidth {
  915. r = r[0:(loadBalancerWidth-3)] + "..."
  916. }
  917. return r
  918. }
  919. func getServiceExternalIP(svc *api.Service, wide bool) string {
  920. switch svc.Spec.Type {
  921. case api.ServiceTypeClusterIP:
  922. if len(svc.Spec.ExternalIPs) > 0 {
  923. return strings.Join(svc.Spec.ExternalIPs, ",")
  924. }
  925. return "<none>"
  926. case api.ServiceTypeNodePort:
  927. if len(svc.Spec.ExternalIPs) > 0 {
  928. return strings.Join(svc.Spec.ExternalIPs, ",")
  929. }
  930. return "<none>"
  931. case api.ServiceTypeLoadBalancer:
  932. lbIps := loadBalancerStatusStringer(svc.Status.LoadBalancer, wide)
  933. if len(svc.Spec.ExternalIPs) > 0 {
  934. results := []string{}
  935. if len(lbIps) > 0 {
  936. results = append(results, strings.Split(lbIps, ",")...)
  937. }
  938. results = append(results, svc.Spec.ExternalIPs...)
  939. return strings.Join(results, ",")
  940. }
  941. if len(lbIps) > 0 {
  942. return lbIps
  943. }
  944. return "<pending>"
  945. case api.ServiceTypeExternalName:
  946. return svc.Spec.ExternalName
  947. }
  948. return "<unknown>"
  949. }
  950. func makePortString(ports []api.ServicePort) string {
  951. pieces := make([]string, len(ports))
  952. for ix := range ports {
  953. port := &ports[ix]
  954. pieces[ix] = fmt.Sprintf("%d/%s", port.Port, port.Protocol)
  955. if port.NodePort > 0 {
  956. pieces[ix] = fmt.Sprintf("%d:%d/%s", port.Port, port.NodePort, port.Protocol)
  957. }
  958. }
  959. return strings.Join(pieces, ",")
  960. }
  961. func printService(obj *api.Service, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  962. row := metav1.TableRow{
  963. Object: runtime.RawExtension{Object: obj},
  964. }
  965. svcType := obj.Spec.Type
  966. internalIP := obj.Spec.ClusterIP
  967. if len(internalIP) == 0 {
  968. internalIP = "<none>"
  969. }
  970. externalIP := getServiceExternalIP(obj, options.Wide)
  971. svcPorts := makePortString(obj.Spec.Ports)
  972. if len(svcPorts) == 0 {
  973. svcPorts = "<none>"
  974. }
  975. row.Cells = append(row.Cells, obj.Name, string(svcType), internalIP, externalIP, svcPorts, translateTimestampSince(obj.CreationTimestamp))
  976. if options.Wide {
  977. row.Cells = append(row.Cells, labels.FormatLabels(obj.Spec.Selector))
  978. }
  979. return []metav1.TableRow{row}, nil
  980. }
  981. func printServiceList(list *api.ServiceList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  982. rows := make([]metav1.TableRow, 0, len(list.Items))
  983. for i := range list.Items {
  984. r, err := printService(&list.Items[i], options)
  985. if err != nil {
  986. return nil, err
  987. }
  988. rows = append(rows, r...)
  989. }
  990. return rows, nil
  991. }
  992. func formatHosts(rules []networking.IngressRule) string {
  993. list := []string{}
  994. max := 3
  995. more := false
  996. for _, rule := range rules {
  997. if len(list) == max {
  998. more = true
  999. }
  1000. if !more && len(rule.Host) != 0 {
  1001. list = append(list, rule.Host)
  1002. }
  1003. }
  1004. if len(list) == 0 {
  1005. return "*"
  1006. }
  1007. ret := strings.Join(list, ",")
  1008. if more {
  1009. return fmt.Sprintf("%s + %d more...", ret, len(rules)-max)
  1010. }
  1011. return ret
  1012. }
  1013. func formatPorts(tls []networking.IngressTLS) string {
  1014. if len(tls) != 0 {
  1015. return "80, 443"
  1016. }
  1017. return "80"
  1018. }
  1019. func printIngress(obj *networking.Ingress, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1020. row := metav1.TableRow{
  1021. Object: runtime.RawExtension{Object: obj},
  1022. }
  1023. hosts := formatHosts(obj.Spec.Rules)
  1024. address := loadBalancerStatusStringer(obj.Status.LoadBalancer, options.Wide)
  1025. ports := formatPorts(obj.Spec.TLS)
  1026. createTime := translateTimestampSince(obj.CreationTimestamp)
  1027. row.Cells = append(row.Cells, obj.Name, hosts, address, ports, createTime)
  1028. return []metav1.TableRow{row}, nil
  1029. }
  1030. func printIngressList(list *networking.IngressList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1031. rows := make([]metav1.TableRow, 0, len(list.Items))
  1032. for i := range list.Items {
  1033. r, err := printIngress(&list.Items[i], options)
  1034. if err != nil {
  1035. return nil, err
  1036. }
  1037. rows = append(rows, r...)
  1038. }
  1039. return rows, nil
  1040. }
  1041. func printStatefulSet(obj *apps.StatefulSet, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1042. row := metav1.TableRow{
  1043. Object: runtime.RawExtension{Object: obj},
  1044. }
  1045. desiredReplicas := obj.Spec.Replicas
  1046. readyReplicas := obj.Status.ReadyReplicas
  1047. createTime := translateTimestampSince(obj.CreationTimestamp)
  1048. row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%d/%d", int64(readyReplicas), int64(desiredReplicas)), createTime)
  1049. if options.Wide {
  1050. names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
  1051. row.Cells = append(row.Cells, names, images)
  1052. }
  1053. return []metav1.TableRow{row}, nil
  1054. }
  1055. func printStatefulSetList(list *apps.StatefulSetList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1056. rows := make([]metav1.TableRow, 0, len(list.Items))
  1057. for i := range list.Items {
  1058. r, err := printStatefulSet(&list.Items[i], options)
  1059. if err != nil {
  1060. return nil, err
  1061. }
  1062. rows = append(rows, r...)
  1063. }
  1064. return rows, nil
  1065. }
  1066. func printDaemonSet(obj *apps.DaemonSet, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1067. row := metav1.TableRow{
  1068. Object: runtime.RawExtension{Object: obj},
  1069. }
  1070. desiredScheduled := obj.Status.DesiredNumberScheduled
  1071. currentScheduled := obj.Status.CurrentNumberScheduled
  1072. numberReady := obj.Status.NumberReady
  1073. numberUpdated := obj.Status.UpdatedNumberScheduled
  1074. numberAvailable := obj.Status.NumberAvailable
  1075. 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))
  1076. if options.Wide {
  1077. names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
  1078. row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector))
  1079. }
  1080. return []metav1.TableRow{row}, nil
  1081. }
  1082. func printDaemonSetList(list *apps.DaemonSetList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1083. rows := make([]metav1.TableRow, 0, len(list.Items))
  1084. for i := range list.Items {
  1085. r, err := printDaemonSet(&list.Items[i], options)
  1086. if err != nil {
  1087. return nil, err
  1088. }
  1089. rows = append(rows, r...)
  1090. }
  1091. return rows, nil
  1092. }
  1093. func printEndpoints(obj *api.Endpoints, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1094. row := metav1.TableRow{
  1095. Object: runtime.RawExtension{Object: obj},
  1096. }
  1097. row.Cells = append(row.Cells, obj.Name, formatEndpoints(obj, nil), translateTimestampSince(obj.CreationTimestamp))
  1098. return []metav1.TableRow{row}, nil
  1099. }
  1100. func printEndpointsList(list *api.EndpointsList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1101. rows := make([]metav1.TableRow, 0, len(list.Items))
  1102. for i := range list.Items {
  1103. r, err := printEndpoints(&list.Items[i], options)
  1104. if err != nil {
  1105. return nil, err
  1106. }
  1107. rows = append(rows, r...)
  1108. }
  1109. return rows, nil
  1110. }
  1111. func printEndpointSlice(obj *discovery.EndpointSlice, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1112. row := metav1.TableRow{
  1113. Object: runtime.RawExtension{Object: obj},
  1114. }
  1115. row.Cells = append(row.Cells, obj.Name, string(obj.AddressType), formatDiscoveryPorts(obj.Ports), formatDiscoveryEndpoints(obj.Endpoints), translateTimestampSince(obj.CreationTimestamp))
  1116. return []metav1.TableRow{row}, nil
  1117. }
  1118. func printEndpointSliceList(list *discovery.EndpointSliceList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1119. rows := make([]metav1.TableRow, 0, len(list.Items))
  1120. for i := range list.Items {
  1121. r, err := printEndpointSlice(&list.Items[i], options)
  1122. if err != nil {
  1123. return nil, err
  1124. }
  1125. rows = append(rows, r...)
  1126. }
  1127. return rows, nil
  1128. }
  1129. func printCSINode(obj *storage.CSINode, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1130. row := metav1.TableRow{
  1131. Object: runtime.RawExtension{Object: obj},
  1132. }
  1133. row.Cells = append(row.Cells, obj.Name, len(obj.Spec.Drivers), translateTimestampSince(obj.CreationTimestamp))
  1134. return []metav1.TableRow{row}, nil
  1135. }
  1136. func printCSINodeList(list *storage.CSINodeList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1137. rows := make([]metav1.TableRow, 0, len(list.Items))
  1138. for i := range list.Items {
  1139. r, err := printCSINode(&list.Items[i], options)
  1140. if err != nil {
  1141. return nil, err
  1142. }
  1143. rows = append(rows, r...)
  1144. }
  1145. return rows, nil
  1146. }
  1147. func printCSIDriver(obj *storage.CSIDriver, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1148. row := metav1.TableRow{
  1149. Object: runtime.RawExtension{Object: obj},
  1150. }
  1151. attachRequired := true
  1152. if obj.Spec.AttachRequired != nil {
  1153. attachRequired = *obj.Spec.AttachRequired
  1154. }
  1155. podInfoOnMount := false
  1156. if obj.Spec.PodInfoOnMount != nil {
  1157. podInfoOnMount = *obj.Spec.PodInfoOnMount
  1158. }
  1159. allModes := []string{}
  1160. for _, mode := range obj.Spec.VolumeLifecycleModes {
  1161. allModes = append(allModes, string(mode))
  1162. }
  1163. modes := strings.Join(allModes, ",")
  1164. if len(modes) == 0 {
  1165. modes = "<none>"
  1166. }
  1167. row.Cells = append(row.Cells, obj.Name, attachRequired, podInfoOnMount, modes, translateTimestampSince(obj.CreationTimestamp))
  1168. return []metav1.TableRow{row}, nil
  1169. }
  1170. func printCSIDriverList(list *storage.CSIDriverList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1171. rows := make([]metav1.TableRow, 0, len(list.Items))
  1172. for i := range list.Items {
  1173. r, err := printCSIDriver(&list.Items[i], options)
  1174. if err != nil {
  1175. return nil, err
  1176. }
  1177. rows = append(rows, r...)
  1178. }
  1179. return rows, nil
  1180. }
  1181. func printMutatingWebhook(obj *admissionregistration.MutatingWebhookConfiguration, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1182. row := metav1.TableRow{
  1183. Object: runtime.RawExtension{Object: obj},
  1184. }
  1185. row.Cells = append(row.Cells, obj.Name, len(obj.Webhooks), translateTimestampSince(obj.CreationTimestamp))
  1186. return []metav1.TableRow{row}, nil
  1187. }
  1188. func printMutatingWebhookList(list *admissionregistration.MutatingWebhookConfigurationList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1189. rows := make([]metav1.TableRow, 0, len(list.Items))
  1190. for i := range list.Items {
  1191. r, err := printMutatingWebhook(&list.Items[i], options)
  1192. if err != nil {
  1193. return nil, err
  1194. }
  1195. rows = append(rows, r...)
  1196. }
  1197. return rows, nil
  1198. }
  1199. func printValidatingWebhook(obj *admissionregistration.ValidatingWebhookConfiguration, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1200. row := metav1.TableRow{
  1201. Object: runtime.RawExtension{Object: obj},
  1202. }
  1203. row.Cells = append(row.Cells, obj.Name, len(obj.Webhooks), translateTimestampSince(obj.CreationTimestamp))
  1204. return []metav1.TableRow{row}, nil
  1205. }
  1206. func printValidatingWebhookList(list *admissionregistration.ValidatingWebhookConfigurationList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1207. rows := make([]metav1.TableRow, 0, len(list.Items))
  1208. for i := range list.Items {
  1209. r, err := printValidatingWebhook(&list.Items[i], options)
  1210. if err != nil {
  1211. return nil, err
  1212. }
  1213. rows = append(rows, r...)
  1214. }
  1215. return rows, nil
  1216. }
  1217. func printNamespace(obj *api.Namespace, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1218. row := metav1.TableRow{
  1219. Object: runtime.RawExtension{Object: obj},
  1220. }
  1221. row.Cells = append(row.Cells, obj.Name, string(obj.Status.Phase), translateTimestampSince(obj.CreationTimestamp))
  1222. return []metav1.TableRow{row}, nil
  1223. }
  1224. func printNamespaceList(list *api.NamespaceList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1225. rows := make([]metav1.TableRow, 0, len(list.Items))
  1226. for i := range list.Items {
  1227. r, err := printNamespace(&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. func printSecret(obj *api.Secret, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1236. row := metav1.TableRow{
  1237. Object: runtime.RawExtension{Object: obj},
  1238. }
  1239. row.Cells = append(row.Cells, obj.Name, string(obj.Type), int64(len(obj.Data)), translateTimestampSince(obj.CreationTimestamp))
  1240. return []metav1.TableRow{row}, nil
  1241. }
  1242. func printSecretList(list *api.SecretList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1243. rows := make([]metav1.TableRow, 0, len(list.Items))
  1244. for i := range list.Items {
  1245. r, err := printSecret(&list.Items[i], options)
  1246. if err != nil {
  1247. return nil, err
  1248. }
  1249. rows = append(rows, r...)
  1250. }
  1251. return rows, nil
  1252. }
  1253. func printServiceAccount(obj *api.ServiceAccount, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1254. row := metav1.TableRow{
  1255. Object: runtime.RawExtension{Object: obj},
  1256. }
  1257. row.Cells = append(row.Cells, obj.Name, int64(len(obj.Secrets)), translateTimestampSince(obj.CreationTimestamp))
  1258. return []metav1.TableRow{row}, nil
  1259. }
  1260. func printServiceAccountList(list *api.ServiceAccountList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1261. rows := make([]metav1.TableRow, 0, len(list.Items))
  1262. for i := range list.Items {
  1263. r, err := printServiceAccount(&list.Items[i], options)
  1264. if err != nil {
  1265. return nil, err
  1266. }
  1267. rows = append(rows, r...)
  1268. }
  1269. return rows, nil
  1270. }
  1271. func printNode(obj *api.Node, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1272. row := metav1.TableRow{
  1273. Object: runtime.RawExtension{Object: obj},
  1274. }
  1275. conditionMap := make(map[api.NodeConditionType]*api.NodeCondition)
  1276. NodeAllConditions := []api.NodeConditionType{api.NodeReady}
  1277. for i := range obj.Status.Conditions {
  1278. cond := obj.Status.Conditions[i]
  1279. conditionMap[cond.Type] = &cond
  1280. }
  1281. var status []string
  1282. for _, validCondition := range NodeAllConditions {
  1283. if condition, ok := conditionMap[validCondition]; ok {
  1284. if condition.Status == api.ConditionTrue {
  1285. status = append(status, string(condition.Type))
  1286. } else {
  1287. status = append(status, "Not"+string(condition.Type))
  1288. }
  1289. }
  1290. }
  1291. if len(status) == 0 {
  1292. status = append(status, "Unknown")
  1293. }
  1294. if obj.Spec.Unschedulable {
  1295. status = append(status, "SchedulingDisabled")
  1296. }
  1297. roles := strings.Join(findNodeRoles(obj), ",")
  1298. if len(roles) == 0 {
  1299. roles = "<none>"
  1300. }
  1301. row.Cells = append(row.Cells, obj.Name, strings.Join(status, ","), roles, translateTimestampSince(obj.CreationTimestamp), obj.Status.NodeInfo.KubeletVersion)
  1302. if options.Wide {
  1303. osImage, kernelVersion, crVersion := obj.Status.NodeInfo.OSImage, obj.Status.NodeInfo.KernelVersion, obj.Status.NodeInfo.ContainerRuntimeVersion
  1304. if osImage == "" {
  1305. osImage = "<unknown>"
  1306. }
  1307. if kernelVersion == "" {
  1308. kernelVersion = "<unknown>"
  1309. }
  1310. if crVersion == "" {
  1311. crVersion = "<unknown>"
  1312. }
  1313. row.Cells = append(row.Cells, getNodeInternalIP(obj), getNodeExternalIP(obj), osImage, kernelVersion, crVersion)
  1314. }
  1315. return []metav1.TableRow{row}, nil
  1316. }
  1317. // Returns first external ip of the node or "<none>" if none is found.
  1318. func getNodeExternalIP(node *api.Node) string {
  1319. for _, address := range node.Status.Addresses {
  1320. if address.Type == api.NodeExternalIP {
  1321. return address.Address
  1322. }
  1323. }
  1324. return "<none>"
  1325. }
  1326. // Returns the internal IP of the node or "<none>" if none is found.
  1327. func getNodeInternalIP(node *api.Node) string {
  1328. for _, address := range node.Status.Addresses {
  1329. if address.Type == api.NodeInternalIP {
  1330. return address.Address
  1331. }
  1332. }
  1333. return "<none>"
  1334. }
  1335. // findNodeRoles returns the roles of a given node.
  1336. // The roles are determined by looking for:
  1337. // * a node-role.kubernetes.io/<role>="" label
  1338. // * a kubernetes.io/role="<role>" label
  1339. func findNodeRoles(node *api.Node) []string {
  1340. roles := sets.NewString()
  1341. for k, v := range node.Labels {
  1342. switch {
  1343. case strings.HasPrefix(k, labelNodeRolePrefix):
  1344. if role := strings.TrimPrefix(k, labelNodeRolePrefix); len(role) > 0 {
  1345. roles.Insert(role)
  1346. }
  1347. case k == nodeLabelRole && v != "":
  1348. roles.Insert(v)
  1349. }
  1350. }
  1351. return roles.List()
  1352. }
  1353. func printNodeList(list *api.NodeList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1354. rows := make([]metav1.TableRow, 0, len(list.Items))
  1355. for i := range list.Items {
  1356. r, err := printNode(&list.Items[i], options)
  1357. if err != nil {
  1358. return nil, err
  1359. }
  1360. rows = append(rows, r...)
  1361. }
  1362. return rows, nil
  1363. }
  1364. func printPersistentVolume(obj *api.PersistentVolume, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1365. row := metav1.TableRow{
  1366. Object: runtime.RawExtension{Object: obj},
  1367. }
  1368. claimRefUID := ""
  1369. if obj.Spec.ClaimRef != nil {
  1370. claimRefUID += obj.Spec.ClaimRef.Namespace
  1371. claimRefUID += "/"
  1372. claimRefUID += obj.Spec.ClaimRef.Name
  1373. }
  1374. modesStr := helper.GetAccessModesAsString(obj.Spec.AccessModes)
  1375. reclaimPolicyStr := string(obj.Spec.PersistentVolumeReclaimPolicy)
  1376. aQty := obj.Spec.Capacity[api.ResourceStorage]
  1377. aSize := aQty.String()
  1378. phase := obj.Status.Phase
  1379. if obj.ObjectMeta.DeletionTimestamp != nil {
  1380. phase = "Terminating"
  1381. }
  1382. volumeMode := "<unset>"
  1383. if obj.Spec.VolumeMode != nil {
  1384. volumeMode = string(*obj.Spec.VolumeMode)
  1385. }
  1386. row.Cells = append(row.Cells, obj.Name, aSize, modesStr, reclaimPolicyStr,
  1387. string(phase), claimRefUID, helper.GetPersistentVolumeClass(obj),
  1388. obj.Status.Reason, translateTimestampSince(obj.CreationTimestamp), volumeMode)
  1389. return []metav1.TableRow{row}, nil
  1390. }
  1391. func printPersistentVolumeList(list *api.PersistentVolumeList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1392. rows := make([]metav1.TableRow, 0, len(list.Items))
  1393. for i := range list.Items {
  1394. r, err := printPersistentVolume(&list.Items[i], options)
  1395. if err != nil {
  1396. return nil, err
  1397. }
  1398. rows = append(rows, r...)
  1399. }
  1400. return rows, nil
  1401. }
  1402. func printPersistentVolumeClaim(obj *api.PersistentVolumeClaim, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1403. row := metav1.TableRow{
  1404. Object: runtime.RawExtension{Object: obj},
  1405. }
  1406. phase := obj.Status.Phase
  1407. if obj.ObjectMeta.DeletionTimestamp != nil {
  1408. phase = "Terminating"
  1409. }
  1410. storage := obj.Spec.Resources.Requests[api.ResourceStorage]
  1411. capacity := ""
  1412. accessModes := ""
  1413. volumeMode := "<unset>"
  1414. if obj.Spec.VolumeName != "" {
  1415. accessModes = helper.GetAccessModesAsString(obj.Status.AccessModes)
  1416. storage = obj.Status.Capacity[api.ResourceStorage]
  1417. capacity = storage.String()
  1418. }
  1419. if obj.Spec.VolumeMode != nil {
  1420. volumeMode = string(*obj.Spec.VolumeMode)
  1421. }
  1422. row.Cells = append(row.Cells, obj.Name, string(phase), obj.Spec.VolumeName, capacity, accessModes,
  1423. helper.GetPersistentVolumeClaimClass(obj), translateTimestampSince(obj.CreationTimestamp), volumeMode)
  1424. return []metav1.TableRow{row}, nil
  1425. }
  1426. func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1427. rows := make([]metav1.TableRow, 0, len(list.Items))
  1428. for i := range list.Items {
  1429. r, err := printPersistentVolumeClaim(&list.Items[i], options)
  1430. if err != nil {
  1431. return nil, err
  1432. }
  1433. rows = append(rows, r...)
  1434. }
  1435. return rows, nil
  1436. }
  1437. func printEvent(obj *api.Event, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1438. row := metav1.TableRow{
  1439. Object: runtime.RawExtension{Object: obj},
  1440. }
  1441. firstTimestamp := translateTimestampSince(obj.FirstTimestamp)
  1442. lastTimestamp := translateTimestampSince(obj.LastTimestamp)
  1443. if obj.LastTimestamp.IsZero() {
  1444. lastTimestamp = firstTimestamp
  1445. }
  1446. var target string
  1447. if len(obj.InvolvedObject.Name) > 0 {
  1448. target = fmt.Sprintf("%s/%s", strings.ToLower(obj.InvolvedObject.Kind), obj.InvolvedObject.Name)
  1449. } else {
  1450. target = strings.ToLower(obj.InvolvedObject.Kind)
  1451. }
  1452. if options.Wide {
  1453. row.Cells = append(row.Cells,
  1454. lastTimestamp,
  1455. obj.Type,
  1456. obj.Reason,
  1457. target,
  1458. obj.InvolvedObject.FieldPath,
  1459. formatEventSource(obj.Source),
  1460. strings.TrimSpace(obj.Message),
  1461. firstTimestamp,
  1462. int64(obj.Count),
  1463. obj.Name,
  1464. )
  1465. } else {
  1466. row.Cells = append(row.Cells,
  1467. lastTimestamp,
  1468. obj.Type,
  1469. obj.Reason,
  1470. target,
  1471. strings.TrimSpace(obj.Message),
  1472. )
  1473. }
  1474. return []metav1.TableRow{row}, nil
  1475. }
  1476. // Sorts and prints the EventList in a human-friendly format.
  1477. func printEventList(list *api.EventList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1478. rows := make([]metav1.TableRow, 0, len(list.Items))
  1479. for i := range list.Items {
  1480. r, err := printEvent(&list.Items[i], options)
  1481. if err != nil {
  1482. return nil, err
  1483. }
  1484. rows = append(rows, r...)
  1485. }
  1486. return rows, nil
  1487. }
  1488. func printRoleBinding(obj *rbac.RoleBinding, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1489. row := metav1.TableRow{
  1490. Object: runtime.RawExtension{Object: obj},
  1491. }
  1492. roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name)
  1493. row.Cells = append(row.Cells, obj.Name, roleRef, translateTimestampSince(obj.CreationTimestamp))
  1494. if options.Wide {
  1495. users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects)
  1496. row.Cells = append(row.Cells, strings.Join(users, ", "), strings.Join(groups, ", "), strings.Join(sas, ", "))
  1497. }
  1498. return []metav1.TableRow{row}, nil
  1499. }
  1500. // Prints the RoleBinding in a human-friendly format.
  1501. func printRoleBindingList(list *rbac.RoleBindingList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1502. rows := make([]metav1.TableRow, 0, len(list.Items))
  1503. for i := range list.Items {
  1504. r, err := printRoleBinding(&list.Items[i], options)
  1505. if err != nil {
  1506. return nil, err
  1507. }
  1508. rows = append(rows, r...)
  1509. }
  1510. return rows, nil
  1511. }
  1512. func printClusterRoleBinding(obj *rbac.ClusterRoleBinding, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1513. row := metav1.TableRow{
  1514. Object: runtime.RawExtension{Object: obj},
  1515. }
  1516. roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name)
  1517. row.Cells = append(row.Cells, obj.Name, roleRef, translateTimestampSince(obj.CreationTimestamp))
  1518. if options.Wide {
  1519. users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects)
  1520. row.Cells = append(row.Cells, strings.Join(users, ", "), strings.Join(groups, ", "), strings.Join(sas, ", "))
  1521. }
  1522. return []metav1.TableRow{row}, nil
  1523. }
  1524. // Prints the ClusterRoleBinding in a human-friendly format.
  1525. func printClusterRoleBindingList(list *rbac.ClusterRoleBindingList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1526. rows := make([]metav1.TableRow, 0, len(list.Items))
  1527. for i := range list.Items {
  1528. r, err := printClusterRoleBinding(&list.Items[i], options)
  1529. if err != nil {
  1530. return nil, err
  1531. }
  1532. rows = append(rows, r...)
  1533. }
  1534. return rows, nil
  1535. }
  1536. func printCertificateSigningRequest(obj *certificates.CertificateSigningRequest, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1537. row := metav1.TableRow{
  1538. Object: runtime.RawExtension{Object: obj},
  1539. }
  1540. status, err := extractCSRStatus(obj)
  1541. if err != nil {
  1542. return nil, err
  1543. }
  1544. row.Cells = append(row.Cells, obj.Name, translateTimestampSince(obj.CreationTimestamp), obj.Spec.Username, status)
  1545. return []metav1.TableRow{row}, nil
  1546. }
  1547. func extractCSRStatus(csr *certificates.CertificateSigningRequest) (string, error) {
  1548. var approved, denied bool
  1549. for _, c := range csr.Status.Conditions {
  1550. switch c.Type {
  1551. case certificates.CertificateApproved:
  1552. approved = true
  1553. case certificates.CertificateDenied:
  1554. denied = true
  1555. default:
  1556. return "", fmt.Errorf("unknown csr condition %q", c)
  1557. }
  1558. }
  1559. var status string
  1560. // must be in order of presidence
  1561. if denied {
  1562. status += "Denied"
  1563. } else if approved {
  1564. status += "Approved"
  1565. } else {
  1566. status += "Pending"
  1567. }
  1568. if len(csr.Status.Certificate) > 0 {
  1569. status += ",Issued"
  1570. }
  1571. return status, nil
  1572. }
  1573. func printCertificateSigningRequestList(list *certificates.CertificateSigningRequestList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1574. rows := make([]metav1.TableRow, 0, len(list.Items))
  1575. for i := range list.Items {
  1576. r, err := printCertificateSigningRequest(&list.Items[i], options)
  1577. if err != nil {
  1578. return nil, err
  1579. }
  1580. rows = append(rows, r...)
  1581. }
  1582. return rows, nil
  1583. }
  1584. func printComponentStatus(obj *api.ComponentStatus, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1585. row := metav1.TableRow{
  1586. Object: runtime.RawExtension{Object: obj},
  1587. }
  1588. status := "Unknown"
  1589. message := ""
  1590. error := ""
  1591. for _, condition := range obj.Conditions {
  1592. if condition.Type == api.ComponentHealthy {
  1593. if condition.Status == api.ConditionTrue {
  1594. status = "Healthy"
  1595. } else {
  1596. status = "Unhealthy"
  1597. }
  1598. message = condition.Message
  1599. error = condition.Error
  1600. break
  1601. }
  1602. }
  1603. row.Cells = append(row.Cells, obj.Name, status, message, error)
  1604. return []metav1.TableRow{row}, nil
  1605. }
  1606. func printComponentStatusList(list *api.ComponentStatusList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1607. rows := make([]metav1.TableRow, 0, len(list.Items))
  1608. for i := range list.Items {
  1609. r, err := printComponentStatus(&list.Items[i], options)
  1610. if err != nil {
  1611. return nil, err
  1612. }
  1613. rows = append(rows, r...)
  1614. }
  1615. return rows, nil
  1616. }
  1617. func printDeployment(obj *apps.Deployment, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1618. row := metav1.TableRow{
  1619. Object: runtime.RawExtension{Object: obj},
  1620. }
  1621. desiredReplicas := obj.Spec.Replicas
  1622. updatedReplicas := obj.Status.UpdatedReplicas
  1623. readyReplicas := obj.Status.ReadyReplicas
  1624. availableReplicas := obj.Status.AvailableReplicas
  1625. age := translateTimestampSince(obj.CreationTimestamp)
  1626. containers := obj.Spec.Template.Spec.Containers
  1627. selector, err := metav1.LabelSelectorAsSelector(obj.Spec.Selector)
  1628. if err != nil {
  1629. // this shouldn't happen if LabelSelector passed validation
  1630. return nil, err
  1631. }
  1632. row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%d/%d", int64(readyReplicas), int64(desiredReplicas)), int64(updatedReplicas), int64(availableReplicas), age)
  1633. if options.Wide {
  1634. containers, images := layoutContainerCells(containers)
  1635. row.Cells = append(row.Cells, containers, images, selector.String())
  1636. }
  1637. return []metav1.TableRow{row}, nil
  1638. }
  1639. func printDeploymentList(list *apps.DeploymentList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1640. rows := make([]metav1.TableRow, 0, len(list.Items))
  1641. for i := range list.Items {
  1642. r, err := printDeployment(&list.Items[i], options)
  1643. if err != nil {
  1644. return nil, err
  1645. }
  1646. rows = append(rows, r...)
  1647. }
  1648. return rows, nil
  1649. }
  1650. func formatHPAMetrics(specs []autoscaling.MetricSpec, statuses []autoscaling.MetricStatus) string {
  1651. if len(specs) == 0 {
  1652. return "<none>"
  1653. }
  1654. list := []string{}
  1655. max := 2
  1656. more := false
  1657. count := 0
  1658. for i, spec := range specs {
  1659. switch spec.Type {
  1660. case autoscaling.ExternalMetricSourceType:
  1661. if spec.External.Target.AverageValue != nil {
  1662. current := "<unknown>"
  1663. if len(statuses) > i && statuses[i].External != nil && statuses[i].External.Current.AverageValue != nil {
  1664. current = statuses[i].External.Current.AverageValue.String()
  1665. }
  1666. list = append(list, fmt.Sprintf("%s/%s (avg)", current, spec.External.Target.AverageValue.String()))
  1667. } else {
  1668. current := "<unknown>"
  1669. if len(statuses) > i && statuses[i].External != nil {
  1670. current = statuses[i].External.Current.Value.String()
  1671. }
  1672. list = append(list, fmt.Sprintf("%s/%s", current, spec.External.Target.Value.String()))
  1673. }
  1674. case autoscaling.PodsMetricSourceType:
  1675. current := "<unknown>"
  1676. if len(statuses) > i && statuses[i].Pods != nil {
  1677. current = statuses[i].Pods.Current.AverageValue.String()
  1678. }
  1679. list = append(list, fmt.Sprintf("%s/%s", current, spec.Pods.Target.AverageValue.String()))
  1680. case autoscaling.ObjectMetricSourceType:
  1681. current := "<unknown>"
  1682. if len(statuses) > i && statuses[i].Object != nil {
  1683. current = statuses[i].Object.Current.Value.String()
  1684. }
  1685. list = append(list, fmt.Sprintf("%s/%s", current, spec.Object.Target.Value.String()))
  1686. case autoscaling.ResourceMetricSourceType:
  1687. if spec.Resource.Target.AverageValue != nil {
  1688. current := "<unknown>"
  1689. if len(statuses) > i && statuses[i].Resource != nil {
  1690. current = statuses[i].Resource.Current.AverageValue.String()
  1691. }
  1692. list = append(list, fmt.Sprintf("%s/%s", current, spec.Resource.Target.AverageValue.String()))
  1693. } else {
  1694. current := "<unknown>"
  1695. if len(statuses) > i && statuses[i].Resource != nil && statuses[i].Resource.Current.AverageUtilization != nil {
  1696. current = fmt.Sprintf("%d%%", *statuses[i].Resource.Current.AverageUtilization)
  1697. }
  1698. target := "<auto>"
  1699. if spec.Resource.Target.AverageUtilization != nil {
  1700. target = fmt.Sprintf("%d%%", *spec.Resource.Target.AverageUtilization)
  1701. }
  1702. list = append(list, fmt.Sprintf("%s/%s", current, target))
  1703. }
  1704. default:
  1705. list = append(list, "<unknown type>")
  1706. }
  1707. count++
  1708. }
  1709. if count > max {
  1710. list = list[:max]
  1711. more = true
  1712. }
  1713. ret := strings.Join(list, ", ")
  1714. if more {
  1715. return fmt.Sprintf("%s + %d more...", ret, count-max)
  1716. }
  1717. return ret
  1718. }
  1719. func printHorizontalPodAutoscaler(obj *autoscaling.HorizontalPodAutoscaler, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1720. row := metav1.TableRow{
  1721. Object: runtime.RawExtension{Object: obj},
  1722. }
  1723. reference := fmt.Sprintf("%s/%s",
  1724. obj.Spec.ScaleTargetRef.Kind,
  1725. obj.Spec.ScaleTargetRef.Name)
  1726. minPods := "<unset>"
  1727. metrics := formatHPAMetrics(obj.Spec.Metrics, obj.Status.CurrentMetrics)
  1728. if obj.Spec.MinReplicas != nil {
  1729. minPods = fmt.Sprintf("%d", *obj.Spec.MinReplicas)
  1730. }
  1731. maxPods := obj.Spec.MaxReplicas
  1732. currentReplicas := obj.Status.CurrentReplicas
  1733. row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestampSince(obj.CreationTimestamp))
  1734. return []metav1.TableRow{row}, nil
  1735. }
  1736. func printHorizontalPodAutoscalerList(list *autoscaling.HorizontalPodAutoscalerList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1737. rows := make([]metav1.TableRow, 0, len(list.Items))
  1738. for i := range list.Items {
  1739. r, err := printHorizontalPodAutoscaler(&list.Items[i], options)
  1740. if err != nil {
  1741. return nil, err
  1742. }
  1743. rows = append(rows, r...)
  1744. }
  1745. return rows, nil
  1746. }
  1747. func printConfigMap(obj *api.ConfigMap, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1748. row := metav1.TableRow{
  1749. Object: runtime.RawExtension{Object: obj},
  1750. }
  1751. row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)+len(obj.BinaryData)), translateTimestampSince(obj.CreationTimestamp))
  1752. return []metav1.TableRow{row}, nil
  1753. }
  1754. func printConfigMapList(list *api.ConfigMapList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1755. rows := make([]metav1.TableRow, 0, len(list.Items))
  1756. for i := range list.Items {
  1757. r, err := printConfigMap(&list.Items[i], options)
  1758. if err != nil {
  1759. return nil, err
  1760. }
  1761. rows = append(rows, r...)
  1762. }
  1763. return rows, nil
  1764. }
  1765. func printPodSecurityPolicy(obj *policy.PodSecurityPolicy, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1766. row := metav1.TableRow{
  1767. Object: runtime.RawExtension{Object: obj},
  1768. }
  1769. capabilities := make([]string, len(obj.Spec.AllowedCapabilities))
  1770. for i, c := range obj.Spec.AllowedCapabilities {
  1771. capabilities[i] = string(c)
  1772. }
  1773. volumes := make([]string, len(obj.Spec.Volumes))
  1774. for i, v := range obj.Spec.Volumes {
  1775. volumes[i] = string(v)
  1776. }
  1777. row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%v", obj.Spec.Privileged),
  1778. strings.Join(capabilities, ","), string(obj.Spec.SELinux.Rule),
  1779. string(obj.Spec.RunAsUser.Rule), string(obj.Spec.FSGroup.Rule),
  1780. string(obj.Spec.SupplementalGroups.Rule), obj.Spec.ReadOnlyRootFilesystem,
  1781. strings.Join(volumes, ","))
  1782. return []metav1.TableRow{row}, nil
  1783. }
  1784. func printPodSecurityPolicyList(list *policy.PodSecurityPolicyList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1785. rows := make([]metav1.TableRow, 0, len(list.Items))
  1786. for i := range list.Items {
  1787. r, err := printPodSecurityPolicy(&list.Items[i], options)
  1788. if err != nil {
  1789. return nil, err
  1790. }
  1791. rows = append(rows, r...)
  1792. }
  1793. return rows, nil
  1794. }
  1795. func printNetworkPolicy(obj *networking.NetworkPolicy, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1796. row := metav1.TableRow{
  1797. Object: runtime.RawExtension{Object: obj},
  1798. }
  1799. row.Cells = append(row.Cells, obj.Name, metav1.FormatLabelSelector(&obj.Spec.PodSelector), translateTimestampSince(obj.CreationTimestamp))
  1800. return []metav1.TableRow{row}, nil
  1801. }
  1802. func printNetworkPolicyList(list *networking.NetworkPolicyList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1803. rows := make([]metav1.TableRow, 0, len(list.Items))
  1804. for i := range list.Items {
  1805. r, err := printNetworkPolicy(&list.Items[i], options)
  1806. if err != nil {
  1807. return nil, err
  1808. }
  1809. rows = append(rows, r...)
  1810. }
  1811. return rows, nil
  1812. }
  1813. func printStorageClass(obj *storage.StorageClass, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1814. row := metav1.TableRow{
  1815. Object: runtime.RawExtension{Object: obj},
  1816. }
  1817. name := obj.Name
  1818. if storageutil.IsDefaultAnnotation(obj.ObjectMeta) {
  1819. name += " (default)"
  1820. }
  1821. provtype := obj.Provisioner
  1822. reclaimPolicy := string(api.PersistentVolumeReclaimDelete)
  1823. if obj.ReclaimPolicy != nil {
  1824. reclaimPolicy = string(*obj.ReclaimPolicy)
  1825. }
  1826. volumeBindingMode := string(storage.VolumeBindingImmediate)
  1827. if obj.VolumeBindingMode != nil {
  1828. volumeBindingMode = string(*obj.VolumeBindingMode)
  1829. }
  1830. allowVolumeExpansion := false
  1831. if obj.AllowVolumeExpansion != nil {
  1832. allowVolumeExpansion = *obj.AllowVolumeExpansion
  1833. }
  1834. row.Cells = append(row.Cells, name, provtype, reclaimPolicy, volumeBindingMode, allowVolumeExpansion,
  1835. translateTimestampSince(obj.CreationTimestamp))
  1836. return []metav1.TableRow{row}, nil
  1837. }
  1838. func printStorageClassList(list *storage.StorageClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1839. rows := make([]metav1.TableRow, 0, len(list.Items))
  1840. for i := range list.Items {
  1841. r, err := printStorageClass(&list.Items[i], options)
  1842. if err != nil {
  1843. return nil, err
  1844. }
  1845. rows = append(rows, r...)
  1846. }
  1847. return rows, nil
  1848. }
  1849. func printLease(obj *coordination.Lease, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1850. row := metav1.TableRow{
  1851. Object: runtime.RawExtension{Object: obj},
  1852. }
  1853. var holderIdentity string
  1854. if obj.Spec.HolderIdentity != nil {
  1855. holderIdentity = *obj.Spec.HolderIdentity
  1856. }
  1857. row.Cells = append(row.Cells, obj.Name, holderIdentity, translateTimestampSince(obj.CreationTimestamp))
  1858. return []metav1.TableRow{row}, nil
  1859. }
  1860. func printLeaseList(list *coordination.LeaseList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1861. rows := make([]metav1.TableRow, 0, len(list.Items))
  1862. for i := range list.Items {
  1863. r, err := printLease(&list.Items[i], options)
  1864. if err != nil {
  1865. return nil, err
  1866. }
  1867. rows = append(rows, r...)
  1868. }
  1869. return rows, nil
  1870. }
  1871. func printStatus(obj *metav1.Status, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1872. row := metav1.TableRow{
  1873. Object: runtime.RawExtension{Object: obj},
  1874. }
  1875. row.Cells = append(row.Cells, obj.Status, obj.Reason, obj.Message)
  1876. return []metav1.TableRow{row}, nil
  1877. }
  1878. // Lay out all the containers on one line if use wide output.
  1879. func layoutContainerCells(containers []api.Container) (names string, images string) {
  1880. var namesBuffer bytes.Buffer
  1881. var imagesBuffer bytes.Buffer
  1882. for i, container := range containers {
  1883. namesBuffer.WriteString(container.Name)
  1884. imagesBuffer.WriteString(container.Image)
  1885. if i != len(containers)-1 {
  1886. namesBuffer.WriteString(",")
  1887. imagesBuffer.WriteString(",")
  1888. }
  1889. }
  1890. return namesBuffer.String(), imagesBuffer.String()
  1891. }
  1892. // formatEventSource formats EventSource as a comma separated string excluding Host when empty
  1893. func formatEventSource(es api.EventSource) string {
  1894. EventSourceString := []string{es.Component}
  1895. if len(es.Host) > 0 {
  1896. EventSourceString = append(EventSourceString, es.Host)
  1897. }
  1898. return strings.Join(EventSourceString, ", ")
  1899. }
  1900. func printControllerRevision(obj *apps.ControllerRevision, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1901. row := metav1.TableRow{
  1902. Object: runtime.RawExtension{Object: obj},
  1903. }
  1904. controllerRef := metav1.GetControllerOf(obj)
  1905. controllerName := "<none>"
  1906. if controllerRef != nil {
  1907. withKind := true
  1908. gv, err := schema.ParseGroupVersion(controllerRef.APIVersion)
  1909. if err != nil {
  1910. return nil, err
  1911. }
  1912. gvk := gv.WithKind(controllerRef.Kind)
  1913. controllerName = formatResourceName(gvk.GroupKind(), controllerRef.Name, withKind)
  1914. }
  1915. revision := obj.Revision
  1916. age := translateTimestampSince(obj.CreationTimestamp)
  1917. row.Cells = append(row.Cells, obj.Name, controllerName, revision, age)
  1918. return []metav1.TableRow{row}, nil
  1919. }
  1920. func printControllerRevisionList(list *apps.ControllerRevisionList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1921. rows := make([]metav1.TableRow, 0, len(list.Items))
  1922. for i := range list.Items {
  1923. r, err := printControllerRevision(&list.Items[i], options)
  1924. if err != nil {
  1925. return nil, err
  1926. }
  1927. rows = append(rows, r...)
  1928. }
  1929. return rows, nil
  1930. }
  1931. // formatResourceName receives a resource kind, name, and boolean specifying
  1932. // whether or not to update the current name to "kind/name"
  1933. func formatResourceName(kind schema.GroupKind, name string, withKind bool) string {
  1934. if !withKind || kind.Empty() {
  1935. return name
  1936. }
  1937. return strings.ToLower(kind.String()) + "/" + name
  1938. }
  1939. func printResourceQuota(resourceQuota *api.ResourceQuota, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1940. row := metav1.TableRow{
  1941. Object: runtime.RawExtension{Object: resourceQuota},
  1942. }
  1943. resources := make([]api.ResourceName, 0, len(resourceQuota.Status.Hard))
  1944. for resource := range resourceQuota.Status.Hard {
  1945. resources = append(resources, resource)
  1946. }
  1947. sort.Sort(SortableResourceNames(resources))
  1948. requestColumn := bytes.NewBuffer([]byte{})
  1949. limitColumn := bytes.NewBuffer([]byte{})
  1950. for i := range resources {
  1951. w := requestColumn
  1952. resource := resources[i]
  1953. usedQuantity := resourceQuota.Status.Used[resource]
  1954. hardQuantity := resourceQuota.Status.Hard[resource]
  1955. // use limitColumn writer if a resource name prefixed with "limits" is found
  1956. if pieces := strings.Split(resource.String(), "."); len(pieces) > 1 && pieces[0] == "limits" {
  1957. w = limitColumn
  1958. }
  1959. fmt.Fprintf(w, "%s: %s/%s, ", resource, usedQuantity.String(), hardQuantity.String())
  1960. }
  1961. age := translateTimestampSince(resourceQuota.CreationTimestamp)
  1962. row.Cells = append(row.Cells, resourceQuota.Name, age, strings.TrimSuffix(requestColumn.String(), ", "), strings.TrimSuffix(limitColumn.String(), ", "))
  1963. return []metav1.TableRow{row}, nil
  1964. }
  1965. func printResourceQuotaList(list *api.ResourceQuotaList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1966. rows := make([]metav1.TableRow, 0, len(list.Items))
  1967. for i := range list.Items {
  1968. r, err := printResourceQuota(&list.Items[i], options)
  1969. if err != nil {
  1970. return nil, err
  1971. }
  1972. rows = append(rows, r...)
  1973. }
  1974. return rows, nil
  1975. }
  1976. func printPriorityClass(obj *scheduling.PriorityClass, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1977. row := metav1.TableRow{
  1978. Object: runtime.RawExtension{Object: obj},
  1979. }
  1980. name := obj.Name
  1981. value := obj.Value
  1982. globalDefault := obj.GlobalDefault
  1983. row.Cells = append(row.Cells, name, int64(value), globalDefault, translateTimestampSince(obj.CreationTimestamp))
  1984. return []metav1.TableRow{row}, nil
  1985. }
  1986. func printPriorityClassList(list *scheduling.PriorityClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1987. rows := make([]metav1.TableRow, 0, len(list.Items))
  1988. for i := range list.Items {
  1989. r, err := printPriorityClass(&list.Items[i], options)
  1990. if err != nil {
  1991. return nil, err
  1992. }
  1993. rows = append(rows, r...)
  1994. }
  1995. return rows, nil
  1996. }
  1997. func printRuntimeClass(obj *nodeapi.RuntimeClass, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1998. row := metav1.TableRow{
  1999. Object: runtime.RawExtension{Object: obj},
  2000. }
  2001. name := obj.Name
  2002. handler := obj.Handler
  2003. row.Cells = append(row.Cells, name, handler, translateTimestampSince(obj.CreationTimestamp))
  2004. return []metav1.TableRow{row}, nil
  2005. }
  2006. func printRuntimeClassList(list *nodeapi.RuntimeClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2007. rows := make([]metav1.TableRow, 0, len(list.Items))
  2008. for i := range list.Items {
  2009. r, err := printRuntimeClass(&list.Items[i], options)
  2010. if err != nil {
  2011. return nil, err
  2012. }
  2013. rows = append(rows, r...)
  2014. }
  2015. return rows, nil
  2016. }
  2017. func printVolumeAttachment(obj *storage.VolumeAttachment, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2018. row := metav1.TableRow{
  2019. Object: runtime.RawExtension{Object: obj},
  2020. }
  2021. name := obj.Name
  2022. pvName := ""
  2023. if obj.Spec.Source.PersistentVolumeName != nil {
  2024. pvName = *obj.Spec.Source.PersistentVolumeName
  2025. }
  2026. row.Cells = append(row.Cells, name, obj.Spec.Attacher, pvName, obj.Spec.NodeName, obj.Status.Attached, translateTimestampSince(obj.CreationTimestamp))
  2027. return []metav1.TableRow{row}, nil
  2028. }
  2029. func printVolumeAttachmentList(list *storage.VolumeAttachmentList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2030. rows := make([]metav1.TableRow, 0, len(list.Items))
  2031. for i := range list.Items {
  2032. r, err := printVolumeAttachment(&list.Items[i], options)
  2033. if err != nil {
  2034. return nil, err
  2035. }
  2036. rows = append(rows, r...)
  2037. }
  2038. return rows, nil
  2039. }
  2040. func printFlowSchema(obj *flowcontrol.FlowSchema, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2041. row := metav1.TableRow{
  2042. Object: runtime.RawExtension{Object: obj},
  2043. }
  2044. name := obj.Name
  2045. plName := obj.Spec.PriorityLevelConfiguration.Name
  2046. distinguisherMethod := "<none>"
  2047. if obj.Spec.DistinguisherMethod != nil {
  2048. distinguisherMethod = string(obj.Spec.DistinguisherMethod.Type)
  2049. }
  2050. badPLRef := "?"
  2051. for _, cond := range obj.Status.Conditions {
  2052. if cond.Type == flowcontrol.FlowSchemaConditionDangling {
  2053. badPLRef = string(cond.Status)
  2054. break
  2055. }
  2056. }
  2057. row.Cells = append(row.Cells, name, plName, obj.Spec.MatchingPrecedence, distinguisherMethod, translateTimestampSince(obj.CreationTimestamp), badPLRef)
  2058. return []metav1.TableRow{row}, nil
  2059. }
  2060. func printFlowSchemaList(list *flowcontrol.FlowSchemaList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2061. rows := make([]metav1.TableRow, 0, len(list.Items))
  2062. fsSeq := make(apihelpers.FlowSchemaSequence, len(list.Items))
  2063. for i := range list.Items {
  2064. fsSeq[i] = &list.Items[i]
  2065. }
  2066. sort.Sort(fsSeq)
  2067. for i := range fsSeq {
  2068. r, err := printFlowSchema(fsSeq[i], options)
  2069. if err != nil {
  2070. return nil, err
  2071. }
  2072. rows = append(rows, r...)
  2073. }
  2074. return rows, nil
  2075. }
  2076. func printPriorityLevelConfiguration(obj *flowcontrol.PriorityLevelConfiguration, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2077. row := metav1.TableRow{
  2078. Object: runtime.RawExtension{Object: obj},
  2079. }
  2080. name := obj.Name
  2081. acs := interface{}("<none>")
  2082. queues := interface{}("<none>")
  2083. handSize := interface{}("<none>")
  2084. queueLengthLimit := interface{}("<none>")
  2085. if obj.Spec.Limited != nil {
  2086. acs = obj.Spec.Limited.AssuredConcurrencyShares
  2087. if qc := obj.Spec.Limited.LimitResponse.Queuing; qc != nil {
  2088. queues = qc.Queues
  2089. handSize = qc.HandSize
  2090. queueLengthLimit = qc.QueueLengthLimit
  2091. }
  2092. }
  2093. row.Cells = append(row.Cells, name, string(obj.Spec.Type), acs, queues, handSize, queueLengthLimit, translateTimestampSince(obj.CreationTimestamp))
  2094. return []metav1.TableRow{row}, nil
  2095. }
  2096. func printPriorityLevelConfigurationList(list *flowcontrol.PriorityLevelConfigurationList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2097. rows := make([]metav1.TableRow, 0, len(list.Items))
  2098. for i := range list.Items {
  2099. r, err := printPriorityLevelConfiguration(&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. func printBoolPtr(value *bool) string {
  2108. if value != nil {
  2109. return printBool(*value)
  2110. }
  2111. return "<unset>"
  2112. }
  2113. func printBool(value bool) string {
  2114. if value {
  2115. return "True"
  2116. }
  2117. return "False"
  2118. }
  2119. // SortableResourceNames - An array of sortable resource names
  2120. type SortableResourceNames []api.ResourceName
  2121. func (list SortableResourceNames) Len() int {
  2122. return len(list)
  2123. }
  2124. func (list SortableResourceNames) Swap(i, j int) {
  2125. list[i], list[j] = list[j], list[i]
  2126. }
  2127. func (list SortableResourceNames) Less(i, j int) bool {
  2128. return list[i] < list[j]
  2129. }