printers.go 94 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378
  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. var target string
  1444. if len(obj.InvolvedObject.Name) > 0 {
  1445. target = fmt.Sprintf("%s/%s", strings.ToLower(obj.InvolvedObject.Kind), obj.InvolvedObject.Name)
  1446. } else {
  1447. target = strings.ToLower(obj.InvolvedObject.Kind)
  1448. }
  1449. if options.Wide {
  1450. row.Cells = append(row.Cells,
  1451. lastTimestamp,
  1452. obj.Type,
  1453. obj.Reason,
  1454. target,
  1455. obj.InvolvedObject.FieldPath,
  1456. formatEventSource(obj.Source),
  1457. strings.TrimSpace(obj.Message),
  1458. firstTimestamp,
  1459. int64(obj.Count),
  1460. obj.Name,
  1461. )
  1462. } else {
  1463. row.Cells = append(row.Cells,
  1464. lastTimestamp,
  1465. obj.Type,
  1466. obj.Reason,
  1467. target,
  1468. strings.TrimSpace(obj.Message),
  1469. )
  1470. }
  1471. return []metav1.TableRow{row}, nil
  1472. }
  1473. // Sorts and prints the EventList in a human-friendly format.
  1474. func printEventList(list *api.EventList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1475. rows := make([]metav1.TableRow, 0, len(list.Items))
  1476. for i := range list.Items {
  1477. r, err := printEvent(&list.Items[i], options)
  1478. if err != nil {
  1479. return nil, err
  1480. }
  1481. rows = append(rows, r...)
  1482. }
  1483. return rows, nil
  1484. }
  1485. func printRoleBinding(obj *rbac.RoleBinding, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1486. row := metav1.TableRow{
  1487. Object: runtime.RawExtension{Object: obj},
  1488. }
  1489. roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name)
  1490. row.Cells = append(row.Cells, obj.Name, roleRef, translateTimestampSince(obj.CreationTimestamp))
  1491. if options.Wide {
  1492. users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects)
  1493. row.Cells = append(row.Cells, strings.Join(users, ", "), strings.Join(groups, ", "), strings.Join(sas, ", "))
  1494. }
  1495. return []metav1.TableRow{row}, nil
  1496. }
  1497. // Prints the RoleBinding in a human-friendly format.
  1498. func printRoleBindingList(list *rbac.RoleBindingList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1499. rows := make([]metav1.TableRow, 0, len(list.Items))
  1500. for i := range list.Items {
  1501. r, err := printRoleBinding(&list.Items[i], options)
  1502. if err != nil {
  1503. return nil, err
  1504. }
  1505. rows = append(rows, r...)
  1506. }
  1507. return rows, nil
  1508. }
  1509. func printClusterRoleBinding(obj *rbac.ClusterRoleBinding, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1510. row := metav1.TableRow{
  1511. Object: runtime.RawExtension{Object: obj},
  1512. }
  1513. roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name)
  1514. row.Cells = append(row.Cells, obj.Name, roleRef, translateTimestampSince(obj.CreationTimestamp))
  1515. if options.Wide {
  1516. users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects)
  1517. row.Cells = append(row.Cells, strings.Join(users, ", "), strings.Join(groups, ", "), strings.Join(sas, ", "))
  1518. }
  1519. return []metav1.TableRow{row}, nil
  1520. }
  1521. // Prints the ClusterRoleBinding in a human-friendly format.
  1522. func printClusterRoleBindingList(list *rbac.ClusterRoleBindingList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1523. rows := make([]metav1.TableRow, 0, len(list.Items))
  1524. for i := range list.Items {
  1525. r, err := printClusterRoleBinding(&list.Items[i], options)
  1526. if err != nil {
  1527. return nil, err
  1528. }
  1529. rows = append(rows, r...)
  1530. }
  1531. return rows, nil
  1532. }
  1533. func printCertificateSigningRequest(obj *certificates.CertificateSigningRequest, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1534. row := metav1.TableRow{
  1535. Object: runtime.RawExtension{Object: obj},
  1536. }
  1537. status, err := extractCSRStatus(obj)
  1538. if err != nil {
  1539. return nil, err
  1540. }
  1541. row.Cells = append(row.Cells, obj.Name, translateTimestampSince(obj.CreationTimestamp), obj.Spec.Username, status)
  1542. return []metav1.TableRow{row}, nil
  1543. }
  1544. func extractCSRStatus(csr *certificates.CertificateSigningRequest) (string, error) {
  1545. var approved, denied bool
  1546. for _, c := range csr.Status.Conditions {
  1547. switch c.Type {
  1548. case certificates.CertificateApproved:
  1549. approved = true
  1550. case certificates.CertificateDenied:
  1551. denied = true
  1552. default:
  1553. return "", fmt.Errorf("unknown csr condition %q", c)
  1554. }
  1555. }
  1556. var status string
  1557. // must be in order of presidence
  1558. if denied {
  1559. status += "Denied"
  1560. } else if approved {
  1561. status += "Approved"
  1562. } else {
  1563. status += "Pending"
  1564. }
  1565. if len(csr.Status.Certificate) > 0 {
  1566. status += ",Issued"
  1567. }
  1568. return status, nil
  1569. }
  1570. func printCertificateSigningRequestList(list *certificates.CertificateSigningRequestList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1571. rows := make([]metav1.TableRow, 0, len(list.Items))
  1572. for i := range list.Items {
  1573. r, err := printCertificateSigningRequest(&list.Items[i], options)
  1574. if err != nil {
  1575. return nil, err
  1576. }
  1577. rows = append(rows, r...)
  1578. }
  1579. return rows, nil
  1580. }
  1581. func printComponentStatus(obj *api.ComponentStatus, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1582. row := metav1.TableRow{
  1583. Object: runtime.RawExtension{Object: obj},
  1584. }
  1585. status := "Unknown"
  1586. message := ""
  1587. error := ""
  1588. for _, condition := range obj.Conditions {
  1589. if condition.Type == api.ComponentHealthy {
  1590. if condition.Status == api.ConditionTrue {
  1591. status = "Healthy"
  1592. } else {
  1593. status = "Unhealthy"
  1594. }
  1595. message = condition.Message
  1596. error = condition.Error
  1597. break
  1598. }
  1599. }
  1600. row.Cells = append(row.Cells, obj.Name, status, message, error)
  1601. return []metav1.TableRow{row}, nil
  1602. }
  1603. func printComponentStatusList(list *api.ComponentStatusList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1604. rows := make([]metav1.TableRow, 0, len(list.Items))
  1605. for i := range list.Items {
  1606. r, err := printComponentStatus(&list.Items[i], options)
  1607. if err != nil {
  1608. return nil, err
  1609. }
  1610. rows = append(rows, r...)
  1611. }
  1612. return rows, nil
  1613. }
  1614. func printDeployment(obj *apps.Deployment, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1615. row := metav1.TableRow{
  1616. Object: runtime.RawExtension{Object: obj},
  1617. }
  1618. desiredReplicas := obj.Spec.Replicas
  1619. updatedReplicas := obj.Status.UpdatedReplicas
  1620. readyReplicas := obj.Status.ReadyReplicas
  1621. availableReplicas := obj.Status.AvailableReplicas
  1622. age := translateTimestampSince(obj.CreationTimestamp)
  1623. containers := obj.Spec.Template.Spec.Containers
  1624. selector, err := metav1.LabelSelectorAsSelector(obj.Spec.Selector)
  1625. if err != nil {
  1626. // this shouldn't happen if LabelSelector passed validation
  1627. return nil, err
  1628. }
  1629. row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%d/%d", int64(readyReplicas), int64(desiredReplicas)), int64(updatedReplicas), int64(availableReplicas), age)
  1630. if options.Wide {
  1631. containers, images := layoutContainerCells(containers)
  1632. row.Cells = append(row.Cells, containers, images, selector.String())
  1633. }
  1634. return []metav1.TableRow{row}, nil
  1635. }
  1636. func printDeploymentList(list *apps.DeploymentList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1637. rows := make([]metav1.TableRow, 0, len(list.Items))
  1638. for i := range list.Items {
  1639. r, err := printDeployment(&list.Items[i], options)
  1640. if err != nil {
  1641. return nil, err
  1642. }
  1643. rows = append(rows, r...)
  1644. }
  1645. return rows, nil
  1646. }
  1647. func formatHPAMetrics(specs []autoscaling.MetricSpec, statuses []autoscaling.MetricStatus) string {
  1648. if len(specs) == 0 {
  1649. return "<none>"
  1650. }
  1651. list := []string{}
  1652. max := 2
  1653. more := false
  1654. count := 0
  1655. for i, spec := range specs {
  1656. switch spec.Type {
  1657. case autoscaling.ExternalMetricSourceType:
  1658. if spec.External.Target.AverageValue != nil {
  1659. current := "<unknown>"
  1660. if len(statuses) > i && statuses[i].External != nil && statuses[i].External.Current.AverageValue != nil {
  1661. current = statuses[i].External.Current.AverageValue.String()
  1662. }
  1663. list = append(list, fmt.Sprintf("%s/%s (avg)", current, spec.External.Target.AverageValue.String()))
  1664. } else {
  1665. current := "<unknown>"
  1666. if len(statuses) > i && statuses[i].External != nil {
  1667. current = statuses[i].External.Current.Value.String()
  1668. }
  1669. list = append(list, fmt.Sprintf("%s/%s", current, spec.External.Target.Value.String()))
  1670. }
  1671. case autoscaling.PodsMetricSourceType:
  1672. current := "<unknown>"
  1673. if len(statuses) > i && statuses[i].Pods != nil {
  1674. current = statuses[i].Pods.Current.AverageValue.String()
  1675. }
  1676. list = append(list, fmt.Sprintf("%s/%s", current, spec.Pods.Target.AverageValue.String()))
  1677. case autoscaling.ObjectMetricSourceType:
  1678. current := "<unknown>"
  1679. if len(statuses) > i && statuses[i].Object != nil {
  1680. current = statuses[i].Object.Current.Value.String()
  1681. }
  1682. list = append(list, fmt.Sprintf("%s/%s", current, spec.Object.Target.Value.String()))
  1683. case autoscaling.ResourceMetricSourceType:
  1684. if spec.Resource.Target.AverageValue != nil {
  1685. current := "<unknown>"
  1686. if len(statuses) > i && statuses[i].Resource != nil {
  1687. current = statuses[i].Resource.Current.AverageValue.String()
  1688. }
  1689. list = append(list, fmt.Sprintf("%s/%s", current, spec.Resource.Target.AverageValue.String()))
  1690. } else {
  1691. current := "<unknown>"
  1692. if len(statuses) > i && statuses[i].Resource != nil && statuses[i].Resource.Current.AverageUtilization != nil {
  1693. current = fmt.Sprintf("%d%%", *statuses[i].Resource.Current.AverageUtilization)
  1694. }
  1695. target := "<auto>"
  1696. if spec.Resource.Target.AverageUtilization != nil {
  1697. target = fmt.Sprintf("%d%%", *spec.Resource.Target.AverageUtilization)
  1698. }
  1699. list = append(list, fmt.Sprintf("%s/%s", current, target))
  1700. }
  1701. default:
  1702. list = append(list, "<unknown type>")
  1703. }
  1704. count++
  1705. }
  1706. if count > max {
  1707. list = list[:max]
  1708. more = true
  1709. }
  1710. ret := strings.Join(list, ", ")
  1711. if more {
  1712. return fmt.Sprintf("%s + %d more...", ret, count-max)
  1713. }
  1714. return ret
  1715. }
  1716. func printHorizontalPodAutoscaler(obj *autoscaling.HorizontalPodAutoscaler, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1717. row := metav1.TableRow{
  1718. Object: runtime.RawExtension{Object: obj},
  1719. }
  1720. reference := fmt.Sprintf("%s/%s",
  1721. obj.Spec.ScaleTargetRef.Kind,
  1722. obj.Spec.ScaleTargetRef.Name)
  1723. minPods := "<unset>"
  1724. metrics := formatHPAMetrics(obj.Spec.Metrics, obj.Status.CurrentMetrics)
  1725. if obj.Spec.MinReplicas != nil {
  1726. minPods = fmt.Sprintf("%d", *obj.Spec.MinReplicas)
  1727. }
  1728. maxPods := obj.Spec.MaxReplicas
  1729. currentReplicas := obj.Status.CurrentReplicas
  1730. row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestampSince(obj.CreationTimestamp))
  1731. return []metav1.TableRow{row}, nil
  1732. }
  1733. func printHorizontalPodAutoscalerList(list *autoscaling.HorizontalPodAutoscalerList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1734. rows := make([]metav1.TableRow, 0, len(list.Items))
  1735. for i := range list.Items {
  1736. r, err := printHorizontalPodAutoscaler(&list.Items[i], options)
  1737. if err != nil {
  1738. return nil, err
  1739. }
  1740. rows = append(rows, r...)
  1741. }
  1742. return rows, nil
  1743. }
  1744. func printConfigMap(obj *api.ConfigMap, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1745. row := metav1.TableRow{
  1746. Object: runtime.RawExtension{Object: obj},
  1747. }
  1748. row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)+len(obj.BinaryData)), translateTimestampSince(obj.CreationTimestamp))
  1749. return []metav1.TableRow{row}, nil
  1750. }
  1751. func printConfigMapList(list *api.ConfigMapList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1752. rows := make([]metav1.TableRow, 0, len(list.Items))
  1753. for i := range list.Items {
  1754. r, err := printConfigMap(&list.Items[i], options)
  1755. if err != nil {
  1756. return nil, err
  1757. }
  1758. rows = append(rows, r...)
  1759. }
  1760. return rows, nil
  1761. }
  1762. func printPodSecurityPolicy(obj *policy.PodSecurityPolicy, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1763. row := metav1.TableRow{
  1764. Object: runtime.RawExtension{Object: obj},
  1765. }
  1766. capabilities := make([]string, len(obj.Spec.AllowedCapabilities))
  1767. for i, c := range obj.Spec.AllowedCapabilities {
  1768. capabilities[i] = string(c)
  1769. }
  1770. volumes := make([]string, len(obj.Spec.Volumes))
  1771. for i, v := range obj.Spec.Volumes {
  1772. volumes[i] = string(v)
  1773. }
  1774. row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%v", obj.Spec.Privileged),
  1775. strings.Join(capabilities, ","), string(obj.Spec.SELinux.Rule),
  1776. string(obj.Spec.RunAsUser.Rule), string(obj.Spec.FSGroup.Rule),
  1777. string(obj.Spec.SupplementalGroups.Rule), obj.Spec.ReadOnlyRootFilesystem,
  1778. strings.Join(volumes, ","))
  1779. return []metav1.TableRow{row}, nil
  1780. }
  1781. func printPodSecurityPolicyList(list *policy.PodSecurityPolicyList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1782. rows := make([]metav1.TableRow, 0, len(list.Items))
  1783. for i := range list.Items {
  1784. r, err := printPodSecurityPolicy(&list.Items[i], options)
  1785. if err != nil {
  1786. return nil, err
  1787. }
  1788. rows = append(rows, r...)
  1789. }
  1790. return rows, nil
  1791. }
  1792. func printNetworkPolicy(obj *networking.NetworkPolicy, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1793. row := metav1.TableRow{
  1794. Object: runtime.RawExtension{Object: obj},
  1795. }
  1796. row.Cells = append(row.Cells, obj.Name, metav1.FormatLabelSelector(&obj.Spec.PodSelector), translateTimestampSince(obj.CreationTimestamp))
  1797. return []metav1.TableRow{row}, nil
  1798. }
  1799. func printNetworkPolicyList(list *networking.NetworkPolicyList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1800. rows := make([]metav1.TableRow, 0, len(list.Items))
  1801. for i := range list.Items {
  1802. r, err := printNetworkPolicy(&list.Items[i], options)
  1803. if err != nil {
  1804. return nil, err
  1805. }
  1806. rows = append(rows, r...)
  1807. }
  1808. return rows, nil
  1809. }
  1810. func printStorageClass(obj *storage.StorageClass, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1811. row := metav1.TableRow{
  1812. Object: runtime.RawExtension{Object: obj},
  1813. }
  1814. name := obj.Name
  1815. if storageutil.IsDefaultAnnotation(obj.ObjectMeta) {
  1816. name += " (default)"
  1817. }
  1818. provtype := obj.Provisioner
  1819. reclaimPolicy := string(api.PersistentVolumeReclaimDelete)
  1820. if obj.ReclaimPolicy != nil {
  1821. reclaimPolicy = string(*obj.ReclaimPolicy)
  1822. }
  1823. volumeBindingMode := string(storage.VolumeBindingImmediate)
  1824. if obj.VolumeBindingMode != nil {
  1825. volumeBindingMode = string(*obj.VolumeBindingMode)
  1826. }
  1827. allowVolumeExpansion := false
  1828. if obj.AllowVolumeExpansion != nil {
  1829. allowVolumeExpansion = *obj.AllowVolumeExpansion
  1830. }
  1831. row.Cells = append(row.Cells, name, provtype, reclaimPolicy, volumeBindingMode, allowVolumeExpansion,
  1832. translateTimestampSince(obj.CreationTimestamp))
  1833. return []metav1.TableRow{row}, nil
  1834. }
  1835. func printStorageClassList(list *storage.StorageClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1836. rows := make([]metav1.TableRow, 0, len(list.Items))
  1837. for i := range list.Items {
  1838. r, err := printStorageClass(&list.Items[i], options)
  1839. if err != nil {
  1840. return nil, err
  1841. }
  1842. rows = append(rows, r...)
  1843. }
  1844. return rows, nil
  1845. }
  1846. func printLease(obj *coordination.Lease, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1847. row := metav1.TableRow{
  1848. Object: runtime.RawExtension{Object: obj},
  1849. }
  1850. var holderIdentity string
  1851. if obj.Spec.HolderIdentity != nil {
  1852. holderIdentity = *obj.Spec.HolderIdentity
  1853. }
  1854. row.Cells = append(row.Cells, obj.Name, holderIdentity, translateTimestampSince(obj.CreationTimestamp))
  1855. return []metav1.TableRow{row}, nil
  1856. }
  1857. func printLeaseList(list *coordination.LeaseList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1858. rows := make([]metav1.TableRow, 0, len(list.Items))
  1859. for i := range list.Items {
  1860. r, err := printLease(&list.Items[i], options)
  1861. if err != nil {
  1862. return nil, err
  1863. }
  1864. rows = append(rows, r...)
  1865. }
  1866. return rows, nil
  1867. }
  1868. func printStatus(obj *metav1.Status, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1869. row := metav1.TableRow{
  1870. Object: runtime.RawExtension{Object: obj},
  1871. }
  1872. row.Cells = append(row.Cells, obj.Status, obj.Reason, obj.Message)
  1873. return []metav1.TableRow{row}, nil
  1874. }
  1875. // Lay out all the containers on one line if use wide output.
  1876. func layoutContainerCells(containers []api.Container) (names string, images string) {
  1877. var namesBuffer bytes.Buffer
  1878. var imagesBuffer bytes.Buffer
  1879. for i, container := range containers {
  1880. namesBuffer.WriteString(container.Name)
  1881. imagesBuffer.WriteString(container.Image)
  1882. if i != len(containers)-1 {
  1883. namesBuffer.WriteString(",")
  1884. imagesBuffer.WriteString(",")
  1885. }
  1886. }
  1887. return namesBuffer.String(), imagesBuffer.String()
  1888. }
  1889. // formatEventSource formats EventSource as a comma separated string excluding Host when empty
  1890. func formatEventSource(es api.EventSource) string {
  1891. EventSourceString := []string{es.Component}
  1892. if len(es.Host) > 0 {
  1893. EventSourceString = append(EventSourceString, es.Host)
  1894. }
  1895. return strings.Join(EventSourceString, ", ")
  1896. }
  1897. func printControllerRevision(obj *apps.ControllerRevision, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1898. row := metav1.TableRow{
  1899. Object: runtime.RawExtension{Object: obj},
  1900. }
  1901. controllerRef := metav1.GetControllerOf(obj)
  1902. controllerName := "<none>"
  1903. if controllerRef != nil {
  1904. withKind := true
  1905. gv, err := schema.ParseGroupVersion(controllerRef.APIVersion)
  1906. if err != nil {
  1907. return nil, err
  1908. }
  1909. gvk := gv.WithKind(controllerRef.Kind)
  1910. controllerName = formatResourceName(gvk.GroupKind(), controllerRef.Name, withKind)
  1911. }
  1912. revision := obj.Revision
  1913. age := translateTimestampSince(obj.CreationTimestamp)
  1914. row.Cells = append(row.Cells, obj.Name, controllerName, revision, age)
  1915. return []metav1.TableRow{row}, nil
  1916. }
  1917. func printControllerRevisionList(list *apps.ControllerRevisionList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1918. rows := make([]metav1.TableRow, 0, len(list.Items))
  1919. for i := range list.Items {
  1920. r, err := printControllerRevision(&list.Items[i], options)
  1921. if err != nil {
  1922. return nil, err
  1923. }
  1924. rows = append(rows, r...)
  1925. }
  1926. return rows, nil
  1927. }
  1928. // formatResourceName receives a resource kind, name, and boolean specifying
  1929. // whether or not to update the current name to "kind/name"
  1930. func formatResourceName(kind schema.GroupKind, name string, withKind bool) string {
  1931. if !withKind || kind.Empty() {
  1932. return name
  1933. }
  1934. return strings.ToLower(kind.String()) + "/" + name
  1935. }
  1936. func printResourceQuota(resourceQuota *api.ResourceQuota, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1937. row := metav1.TableRow{
  1938. Object: runtime.RawExtension{Object: resourceQuota},
  1939. }
  1940. resources := make([]api.ResourceName, 0, len(resourceQuota.Status.Hard))
  1941. for resource := range resourceQuota.Status.Hard {
  1942. resources = append(resources, resource)
  1943. }
  1944. sort.Sort(SortableResourceNames(resources))
  1945. requestColumn := bytes.NewBuffer([]byte{})
  1946. limitColumn := bytes.NewBuffer([]byte{})
  1947. for i := range resources {
  1948. w := requestColumn
  1949. resource := resources[i]
  1950. usedQuantity := resourceQuota.Status.Used[resource]
  1951. hardQuantity := resourceQuota.Status.Hard[resource]
  1952. // use limitColumn writer if a resource name prefixed with "limits" is found
  1953. if pieces := strings.Split(resource.String(), "."); len(pieces) > 1 && pieces[0] == "limits" {
  1954. w = limitColumn
  1955. }
  1956. fmt.Fprintf(w, "%s: %s/%s, ", resource, usedQuantity.String(), hardQuantity.String())
  1957. }
  1958. age := translateTimestampSince(resourceQuota.CreationTimestamp)
  1959. row.Cells = append(row.Cells, resourceQuota.Name, age, strings.TrimSuffix(requestColumn.String(), ", "), strings.TrimSuffix(limitColumn.String(), ", "))
  1960. return []metav1.TableRow{row}, nil
  1961. }
  1962. func printResourceQuotaList(list *api.ResourceQuotaList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1963. rows := make([]metav1.TableRow, 0, len(list.Items))
  1964. for i := range list.Items {
  1965. r, err := printResourceQuota(&list.Items[i], options)
  1966. if err != nil {
  1967. return nil, err
  1968. }
  1969. rows = append(rows, r...)
  1970. }
  1971. return rows, nil
  1972. }
  1973. func printPriorityClass(obj *scheduling.PriorityClass, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1974. row := metav1.TableRow{
  1975. Object: runtime.RawExtension{Object: obj},
  1976. }
  1977. name := obj.Name
  1978. value := obj.Value
  1979. globalDefault := obj.GlobalDefault
  1980. row.Cells = append(row.Cells, name, int64(value), globalDefault, translateTimestampSince(obj.CreationTimestamp))
  1981. return []metav1.TableRow{row}, nil
  1982. }
  1983. func printPriorityClassList(list *scheduling.PriorityClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1984. rows := make([]metav1.TableRow, 0, len(list.Items))
  1985. for i := range list.Items {
  1986. r, err := printPriorityClass(&list.Items[i], options)
  1987. if err != nil {
  1988. return nil, err
  1989. }
  1990. rows = append(rows, r...)
  1991. }
  1992. return rows, nil
  1993. }
  1994. func printRuntimeClass(obj *nodeapi.RuntimeClass, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  1995. row := metav1.TableRow{
  1996. Object: runtime.RawExtension{Object: obj},
  1997. }
  1998. name := obj.Name
  1999. handler := obj.Handler
  2000. row.Cells = append(row.Cells, name, handler, translateTimestampSince(obj.CreationTimestamp))
  2001. return []metav1.TableRow{row}, nil
  2002. }
  2003. func printRuntimeClassList(list *nodeapi.RuntimeClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2004. rows := make([]metav1.TableRow, 0, len(list.Items))
  2005. for i := range list.Items {
  2006. r, err := printRuntimeClass(&list.Items[i], options)
  2007. if err != nil {
  2008. return nil, err
  2009. }
  2010. rows = append(rows, r...)
  2011. }
  2012. return rows, nil
  2013. }
  2014. func printVolumeAttachment(obj *storage.VolumeAttachment, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2015. row := metav1.TableRow{
  2016. Object: runtime.RawExtension{Object: obj},
  2017. }
  2018. name := obj.Name
  2019. pvName := ""
  2020. if obj.Spec.Source.PersistentVolumeName != nil {
  2021. pvName = *obj.Spec.Source.PersistentVolumeName
  2022. }
  2023. row.Cells = append(row.Cells, name, obj.Spec.Attacher, pvName, obj.Spec.NodeName, obj.Status.Attached, translateTimestampSince(obj.CreationTimestamp))
  2024. return []metav1.TableRow{row}, nil
  2025. }
  2026. func printVolumeAttachmentList(list *storage.VolumeAttachmentList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2027. rows := make([]metav1.TableRow, 0, len(list.Items))
  2028. for i := range list.Items {
  2029. r, err := printVolumeAttachment(&list.Items[i], options)
  2030. if err != nil {
  2031. return nil, err
  2032. }
  2033. rows = append(rows, r...)
  2034. }
  2035. return rows, nil
  2036. }
  2037. func printFlowSchema(obj *flowcontrol.FlowSchema, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2038. row := metav1.TableRow{
  2039. Object: runtime.RawExtension{Object: obj},
  2040. }
  2041. name := obj.Name
  2042. plName := obj.Spec.PriorityLevelConfiguration.Name
  2043. distinguisherMethod := "<none>"
  2044. if obj.Spec.DistinguisherMethod != nil {
  2045. distinguisherMethod = string(obj.Spec.DistinguisherMethod.Type)
  2046. }
  2047. badPLRef := "?"
  2048. for _, cond := range obj.Status.Conditions {
  2049. if cond.Type == flowcontrol.FlowSchemaConditionDangling {
  2050. badPLRef = string(cond.Status)
  2051. break
  2052. }
  2053. }
  2054. row.Cells = append(row.Cells, name, plName, obj.Spec.MatchingPrecedence, distinguisherMethod, translateTimestampSince(obj.CreationTimestamp), badPLRef)
  2055. return []metav1.TableRow{row}, nil
  2056. }
  2057. func printFlowSchemaList(list *flowcontrol.FlowSchemaList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2058. rows := make([]metav1.TableRow, 0, len(list.Items))
  2059. fsSeq := make(apihelpers.FlowSchemaSequence, len(list.Items))
  2060. for i := range list.Items {
  2061. fsSeq[i] = &list.Items[i]
  2062. }
  2063. sort.Sort(fsSeq)
  2064. for i := range fsSeq {
  2065. r, err := printFlowSchema(fsSeq[i], options)
  2066. if err != nil {
  2067. return nil, err
  2068. }
  2069. rows = append(rows, r...)
  2070. }
  2071. return rows, nil
  2072. }
  2073. func printPriorityLevelConfiguration(obj *flowcontrol.PriorityLevelConfiguration, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2074. row := metav1.TableRow{
  2075. Object: runtime.RawExtension{Object: obj},
  2076. }
  2077. name := obj.Name
  2078. acs := interface{}("<none>")
  2079. queues := interface{}("<none>")
  2080. handSize := interface{}("<none>")
  2081. queueLengthLimit := interface{}("<none>")
  2082. if obj.Spec.Limited != nil {
  2083. acs = obj.Spec.Limited.AssuredConcurrencyShares
  2084. if qc := obj.Spec.Limited.LimitResponse.Queuing; qc != nil {
  2085. queues = qc.Queues
  2086. handSize = qc.HandSize
  2087. queueLengthLimit = qc.QueueLengthLimit
  2088. }
  2089. }
  2090. row.Cells = append(row.Cells, name, string(obj.Spec.Type), acs, queues, handSize, queueLengthLimit, translateTimestampSince(obj.CreationTimestamp))
  2091. return []metav1.TableRow{row}, nil
  2092. }
  2093. func printPriorityLevelConfigurationList(list *flowcontrol.PriorityLevelConfigurationList, options printers.GenerateOptions) ([]metav1.TableRow, error) {
  2094. rows := make([]metav1.TableRow, 0, len(list.Items))
  2095. for i := range list.Items {
  2096. r, err := printPriorityLevelConfiguration(&list.Items[i], options)
  2097. if err != nil {
  2098. return nil, err
  2099. }
  2100. rows = append(rows, r...)
  2101. }
  2102. return rows, nil
  2103. }
  2104. func printBoolPtr(value *bool) string {
  2105. if value != nil {
  2106. return printBool(*value)
  2107. }
  2108. return "<unset>"
  2109. }
  2110. func printBool(value bool) string {
  2111. if value {
  2112. return "True"
  2113. }
  2114. return "False"
  2115. }
  2116. // SortableResourceNames - An array of sortable resource names
  2117. type SortableResourceNames []api.ResourceName
  2118. func (list SortableResourceNames) Len() int {
  2119. return len(list)
  2120. }
  2121. func (list SortableResourceNames) Swap(i, j int) {
  2122. list[i], list[j] = list[j], list[i]
  2123. }
  2124. func (list SortableResourceNames) Less(i, j int) bool {
  2125. return list[i] < list[j]
  2126. }