123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061 |
- /*
- Copyright 2014 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package internalversion
- import (
- "math"
- "reflect"
- "testing"
- "time"
- "k8s.io/apimachinery/pkg/api/resource"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/runtime/schema"
- "k8s.io/apimachinery/pkg/util/diff"
- "k8s.io/apimachinery/pkg/util/intstr"
- "k8s.io/kubernetes/pkg/apis/apps"
- "k8s.io/kubernetes/pkg/apis/autoscaling"
- "k8s.io/kubernetes/pkg/apis/batch"
- "k8s.io/kubernetes/pkg/apis/certificates"
- "k8s.io/kubernetes/pkg/apis/coordination"
- api "k8s.io/kubernetes/pkg/apis/core"
- "k8s.io/kubernetes/pkg/apis/discovery"
- "k8s.io/kubernetes/pkg/apis/flowcontrol"
- "k8s.io/kubernetes/pkg/apis/networking"
- nodeapi "k8s.io/kubernetes/pkg/apis/node"
- "k8s.io/kubernetes/pkg/apis/policy"
- "k8s.io/kubernetes/pkg/apis/rbac"
- "k8s.io/kubernetes/pkg/apis/scheduling"
- "k8s.io/kubernetes/pkg/apis/storage"
- "k8s.io/kubernetes/pkg/printers"
- utilpointer "k8s.io/utils/pointer"
- )
- func TestFormatResourceName(t *testing.T) {
- tests := []struct {
- kind schema.GroupKind
- name string
- want string
- }{
- {schema.GroupKind{}, "", ""},
- {schema.GroupKind{}, "name", "name"},
- {schema.GroupKind{Kind: "Kind"}, "", "kind/"}, // should not happen in practice
- {schema.GroupKind{Kind: "Kind"}, "name", "kind/name"},
- {schema.GroupKind{Group: "group", Kind: "Kind"}, "name", "kind.group/name"},
- }
- for _, tt := range tests {
- if got := formatResourceName(tt.kind, tt.name, true); got != tt.want {
- t.Errorf("formatResourceName(%q, %q) = %q, want %q", tt.kind, tt.name, got, tt.want)
- }
- }
- }
- type TestPrintHandler struct {
- numCalls int
- }
- func (t *TestPrintHandler) TableHandler(columnDefinitions []metav1.TableColumnDefinition, printFunc interface{}) error {
- t.numCalls++
- return nil
- }
- func (t *TestPrintHandler) getNumCalls() int {
- return t.numCalls
- }
- func TestAllHandlers(t *testing.T) {
- h := &TestPrintHandler{numCalls: 0}
- AddHandlers(h)
- if h.getNumCalls() == 0 {
- t.Error("TableHandler not called in AddHandlers")
- }
- }
- func TestPrintEvent(t *testing.T) {
- tests := []struct {
- event api.Event
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Basic event; no generate options
- {
- event: api.Event{
- Source: api.EventSource{Component: "kubelet"},
- InvolvedObject: api.ObjectReference{
- Kind: "Pod",
- Name: "Pod Name",
- FieldPath: "spec.containers{foo}",
- },
- Reason: "Event Reason",
- Message: "Message Data",
- FirstTimestamp: metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -3)},
- LastTimestamp: metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -2)},
- Count: 6,
- Type: api.EventTypeNormal,
- ObjectMeta: metav1.ObjectMeta{Name: "event1"},
- },
- options: printers.GenerateOptions{},
- // Columns: Last Seen, Type, Reason, Object, Message
- expected: []metav1.TableRow{{Cells: []interface{}{"2d", "Normal", "Event Reason", "pod/Pod Name", "Message Data"}}},
- },
- // Basic event; generate options=Wide
- {
- event: api.Event{
- Source: api.EventSource{
- Component: "kubelet",
- Host: "Node1",
- },
- InvolvedObject: api.ObjectReference{
- Kind: "Deployment",
- Name: "Deployment Name",
- FieldPath: "spec.containers{foo}",
- },
- Reason: "Event Reason",
- Message: "Message Data",
- FirstTimestamp: metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -3)},
- LastTimestamp: metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -2)},
- Count: 6,
- Type: api.EventTypeWarning,
- ObjectMeta: metav1.ObjectMeta{Name: "event2"},
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Last Seen, Type, Reason, Object, Subobject, Message, First Seen, Count, Name
- expected: []metav1.TableRow{{Cells: []interface{}{"2d", "Warning", "Event Reason", "deployment/Deployment Name", "spec.containers{foo}", "kubelet, Node1", "Message Data", "3d", int64(6), "event2"}}},
- },
- }
- for i, test := range tests {
- rows, err := printEvent(&test.event, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintEventsResultSorted(t *testing.T) {
- eventList := api.EventList{
- Items: []api.Event{
- {
- Source: api.EventSource{Component: "kubelet"},
- Message: "Item 1",
- FirstTimestamp: metav1.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
- LastTimestamp: metav1.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
- Count: 1,
- Type: api.EventTypeNormal,
- },
- {
- Source: api.EventSource{Component: "scheduler"},
- Message: "Item 2",
- FirstTimestamp: metav1.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
- LastTimestamp: metav1.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
- Count: 1,
- Type: api.EventTypeNormal,
- },
- {
- Source: api.EventSource{Component: "kubelet"},
- Message: "Item 3",
- FirstTimestamp: metav1.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
- LastTimestamp: metav1.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
- Count: 1,
- Type: api.EventTypeNormal,
- },
- },
- }
- rows, err := printEventList(&eventList, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- if len(rows) != 3 {
- t.Errorf("Generate Event List: Wrong number of table rows returned. Expected 3, got (%d)", len(rows))
- }
- // Verify the watch event dates are in order.
- firstRow := rows[0]
- message1 := firstRow.Cells[4]
- if message1.(string) != "Item 1" {
- t.Errorf("Wrong event ordering: expecting (Item 1), got (%s)", message1)
- }
- secondRow := rows[1]
- message2 := secondRow.Cells[4]
- if message2 != "Item 2" {
- t.Errorf("Wrong event ordering: expecting (Item 2), got (%s)", message2)
- }
- thirdRow := rows[2]
- message3 := thirdRow.Cells[4]
- if message3 != "Item 3" {
- t.Errorf("Wrong event ordering: expecting (Item 3), got (%s)", message3)
- }
- }
- func TestPrintNamespace(t *testing.T) {
- tests := []struct {
- namespace api.Namespace
- expected []metav1.TableRow
- }{
- // Basic namespace with status and age.
- {
- namespace: api.Namespace{
- ObjectMeta: metav1.ObjectMeta{
- Name: "namespace1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Status: api.NamespaceStatus{
- Phase: "FooStatus",
- },
- },
- // Columns: Name, Status, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"namespace1", "FooStatus", "0s"}}},
- },
- // Basic namespace without status or age.
- {
- namespace: api.Namespace{
- ObjectMeta: metav1.ObjectMeta{
- Name: "namespace2",
- },
- },
- // Columns: Name, Status, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"namespace2", "", "<unknown>"}}},
- },
- }
- for i, test := range tests {
- rows, err := printNamespace(&test.namespace, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintSecret(t *testing.T) {
- tests := []struct {
- secret api.Secret
- expected []metav1.TableRow
- }{
- // Basic namespace with type, data, and age.
- {
- secret: api.Secret{
- ObjectMeta: metav1.ObjectMeta{
- Name: "secret1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Type: "kubernetes.io/service-account-token",
- Data: map[string][]byte{
- "token": []byte("secret data"),
- },
- },
- // Columns: Name, Type, Data, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"secret1", "kubernetes.io/service-account-token", int64(1), "0s"}}},
- },
- // Basic namespace with type and age; no data.
- {
- secret: api.Secret{
- ObjectMeta: metav1.ObjectMeta{
- Name: "secret1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Type: "kubernetes.io/service-account-token",
- },
- // Columns: Name, Type, Data, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"secret1", "kubernetes.io/service-account-token", int64(0), "0s"}}},
- },
- }
- for i, test := range tests {
- rows, err := printSecret(&test.secret, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintServiceAccount(t *testing.T) {
- tests := []struct {
- serviceAccount api.ServiceAccount
- expected []metav1.TableRow
- }{
- // Basic service account without secrets
- {
- serviceAccount: api.ServiceAccount{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sa1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Secrets: []api.ObjectReference{},
- },
- // Columns: Name, (Num) Secrets, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"sa1", int64(0), "0s"}}},
- },
- // Basic service account with two secrets.
- {
- serviceAccount: api.ServiceAccount{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sa1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Secrets: []api.ObjectReference{
- {Name: "Secret1"},
- {Name: "Secret2"},
- },
- },
- // Columns: Name, (Num) Secrets, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"sa1", int64(2), "0s"}}},
- },
- }
- for i, test := range tests {
- rows, err := printServiceAccount(&test.serviceAccount, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeStatus(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionTrue}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo1", "Ready", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Spec: api.NodeSpec{Unschedulable: true},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionTrue}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo2", "Ready,SchedulingDisabled", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo3"},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{
- {Type: api.NodeReady, Status: api.ConditionTrue},
- {Type: api.NodeReady, Status: api.ConditionTrue}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo3", "Ready", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo4"},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionFalse}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo4", "NotReady", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo5"},
- Spec: api.NodeSpec{Unschedulable: true},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionFalse}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo5", "NotReady,SchedulingDisabled", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo6"},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: "InvalidValue", Status: api.ConditionTrue}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo6", "Unknown", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo7"},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo7", "Unknown", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo8"},
- Spec: api.NodeSpec{Unschedulable: true},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: "InvalidValue", Status: api.ConditionTrue}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo8", "Unknown,SchedulingDisabled", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo9"},
- Spec: api.NodeSpec{Unschedulable: true},
- Status: api.NodeStatus{Conditions: []api.NodeCondition{{}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo9", "Unknown,SchedulingDisabled", "<none>", "<unknown>", ""}}},
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error generating table rows for Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeRole(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo9"},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo9", "Unknown", "<none>", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{
- Name: "foo10",
- Labels: map[string]string{"node-role.kubernetes.io/master": "", "node-role.kubernetes.io/proxy": "", "kubernetes.io/role": "node"},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo10", "Unknown", "master,node,proxy", "<unknown>", ""}}},
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{
- Name: "foo11",
- Labels: map[string]string{"kubernetes.io/role": "node"},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"foo11", "Unknown", "node", "<unknown>", ""}}},
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("An error occurred generating table rows for Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeOSImage(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Status: api.NodeStatus{
- NodeInfo: api.NodeSystemInfo{OSImage: "fake-os-image"},
- Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo1", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "fake-os-image", "<unknown>", "<unknown>"},
- },
- },
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Status: api.NodeStatus{
- NodeInfo: api.NodeSystemInfo{KernelVersion: "fake-kernel-version"},
- Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo2", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "<unknown>", "fake-kernel-version", "<unknown>"},
- },
- },
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{Wide: true})
- if err != nil {
- t.Fatalf("An error occurred generating table for Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeKernelVersion(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Status: api.NodeStatus{
- NodeInfo: api.NodeSystemInfo{KernelVersion: "fake-kernel-version"},
- Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo1", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "<unknown>", "fake-kernel-version", "<unknown>"},
- },
- },
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Status: api.NodeStatus{
- NodeInfo: api.NodeSystemInfo{OSImage: "fake-os-image"},
- Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo2", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "fake-os-image", "<unknown>", "<unknown>"},
- },
- },
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{Wide: true})
- if err != nil {
- t.Fatalf("An error occurred generating table rows Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeContainerRuntimeVersion(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Status: api.NodeStatus{
- NodeInfo: api.NodeSystemInfo{ContainerRuntimeVersion: "foo://1.2.3"},
- Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo1", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "<unknown>", "<unknown>", "foo://1.2.3"},
- },
- },
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Status: api.NodeStatus{
- NodeInfo: api.NodeSystemInfo{},
- Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}},
- },
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo2", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "<unknown>", "<unknown>", "<unknown>"},
- },
- },
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{Wide: true})
- if err != nil {
- t.Fatalf("An error occurred generating table rows Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeName(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "127.0.0.1"},
- Status: api.NodeStatus{},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"127.0.0.1", "Unknown", "<none>", "<unknown>", ""}}}},
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: ""},
- Status: api.NodeStatus{},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion
- expected: []metav1.TableRow{{Cells: []interface{}{"", "Unknown", "<none>", "<unknown>", ""}}},
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("An error occurred generating table rows Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeExternalIP(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo1", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "<unknown>", "<unknown>", "<unknown>"},
- },
- },
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeInternalIP, Address: "1.1.1.1"}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo2", "Unknown", "<none>", "<unknown>", "", "1.1.1.1", "<none>", "<unknown>", "<unknown>", "<unknown>"},
- },
- },
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo3"},
- Status: api.NodeStatus{Addresses: []api.NodeAddress{
- {Type: api.NodeExternalIP, Address: "2.2.2.2"},
- {Type: api.NodeInternalIP, Address: "3.3.3.3"},
- {Type: api.NodeExternalIP, Address: "4.4.4.4"},
- }},
- },
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo3", "Unknown", "<none>", "<unknown>", "", "3.3.3.3", "2.2.2.2", "<unknown>", "<unknown>", "<unknown>"},
- },
- },
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{Wide: true})
- if err != nil {
- t.Fatalf("An error occurred generating table rows Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNodeInternalIP(t *testing.T) {
- table := []struct {
- node api.Node
- expected []metav1.TableRow
- }{
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeInternalIP, Address: "1.1.1.1"}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo1", "Unknown", "<none>", "<unknown>", "", "1.1.1.1", "<none>", "<unknown>", "<unknown>", "<unknown>"},
- },
- },
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}}},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo2", "Unknown", "<none>", "<unknown>", "", "<none>", "1.1.1.1", "<unknown>", "<unknown>", "<unknown>"},
- },
- },
- },
- {
- node: api.Node{
- ObjectMeta: metav1.ObjectMeta{Name: "foo3"},
- Status: api.NodeStatus{Addresses: []api.NodeAddress{
- {Type: api.NodeInternalIP, Address: "2.2.2.2"},
- {Type: api.NodeExternalIP, Address: "3.3.3.3"},
- {Type: api.NodeInternalIP, Address: "4.4.4.4"},
- }},
- },
- // Columns: Name, Status, Roles, Age, KubeletVersion, NodeInternalIP, NodeExternalIP, OSImage, KernelVersion, ContainerRuntimeVersion
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"foo3", "Unknown", "<none>", "<unknown>", "", "2.2.2.2", "3.3.3.3", "<unknown>", "<unknown>", "<unknown>"},
- },
- },
- },
- }
- for i, test := range table {
- rows, err := printNode(&test.node, printers.GenerateOptions{Wide: true})
- if err != nil {
- t.Fatalf("An error occurred generating table rows Node: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintIngress(t *testing.T) {
- ingress := networking.Ingress{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)},
- },
- Spec: networking.IngressSpec{
- Backend: &networking.IngressBackend{
- ServiceName: "svc",
- ServicePort: intstr.FromInt(93),
- },
- },
- Status: networking.IngressStatus{
- LoadBalancer: api.LoadBalancerStatus{
- Ingress: []api.LoadBalancerIngress{
- {
- IP: "2.3.4.5",
- Hostname: "localhost.localdomain",
- },
- },
- },
- },
- }
- // Columns: Name, Hosts, Address, Ports, Age
- expected := []metav1.TableRow{{Cells: []interface{}{"test1", "*", "2.3.4.5", "80", "10y"}}}
- rows, err := printIngress(&ingress, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error generating table rows for Ingress: %#v", err)
- }
- rows[0].Object.Object = nil
- if !reflect.DeepEqual(expected, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expected, rows))
- }
- }
- func TestPrintServiceLoadBalancer(t *testing.T) {
- tests := []struct {
- service api.Service
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Test load balancer service with multiple external IP's
- {
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "service1"},
- Spec: api.ServiceSpec{
- ClusterIP: "1.2.3.4",
- Type: "LoadBalancer",
- Ports: []api.ServicePort{{Port: 80, Protocol: "TCP"}},
- },
- Status: api.ServiceStatus{
- LoadBalancer: api.LoadBalancerStatus{
- Ingress: []api.LoadBalancerIngress{{IP: "2.3.4.5"}, {IP: "3.4.5.6"}}},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"service1", "LoadBalancer", "1.2.3.4", "2.3.4.5,3.4.5.6", "80/TCP", "<unknown>"}}},
- },
- // Test load balancer service with pending external IP.
- {
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "service2"},
- Spec: api.ServiceSpec{
- ClusterIP: "1.3.4.5",
- Type: "LoadBalancer",
- Ports: []api.ServicePort{{Port: 80, Protocol: "TCP"}, {Port: 8090, Protocol: "UDP"}, {Port: 8000, Protocol: "TCP"}, {Port: 7777, Protocol: "SCTP"}},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"service2", "LoadBalancer", "1.3.4.5", "<pending>", "80/TCP,8090/UDP,8000/TCP,7777/SCTP", "<unknown>"}}},
- },
- // Test load balancer service with multiple ports.
- {
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "service3"},
- Spec: api.ServiceSpec{
- ClusterIP: "1.4.5.6",
- Type: "LoadBalancer",
- Ports: []api.ServicePort{{Port: 80, Protocol: "TCP"}, {Port: 8090, Protocol: "UDP"}, {Port: 8000, Protocol: "TCP"}},
- },
- Status: api.ServiceStatus{
- LoadBalancer: api.LoadBalancerStatus{
- Ingress: []api.LoadBalancerIngress{{IP: "2.3.4.5"}}},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"service3", "LoadBalancer", "1.4.5.6", "2.3.4.5", "80/TCP,8090/UDP,8000/TCP", "<unknown>"}}},
- },
- // Long external IP's list gets elided.
- {
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "service4"},
- Spec: api.ServiceSpec{
- ClusterIP: "1.5.6.7",
- Type: "LoadBalancer",
- Ports: []api.ServicePort{{Port: 80, Protocol: "TCP"}, {Port: 8090, Protocol: "UDP"}, {Port: 8000, Protocol: "TCP"}},
- },
- Status: api.ServiceStatus{
- LoadBalancer: api.LoadBalancerStatus{
- Ingress: []api.LoadBalancerIngress{{IP: "2.3.4.5"}, {IP: "3.4.5.6"}, {IP: "5.6.7.8", Hostname: "host5678"}}},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"service4", "LoadBalancer", "1.5.6.7", "2.3.4.5,3.4.5...", "80/TCP,8090/UDP,8000/TCP", "<unknown>"}}},
- },
- // Generate options: Wide, includes selectors.
- {
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "service4"},
- Spec: api.ServiceSpec{
- ClusterIP: "1.5.6.7",
- Type: "LoadBalancer",
- Ports: []api.ServicePort{{Port: 80, Protocol: "TCP"}, {Port: 8090, Protocol: "UDP"}, {Port: 8000, Protocol: "TCP"}},
- Selector: map[string]string{"foo": "bar"},
- },
- Status: api.ServiceStatus{
- LoadBalancer: api.LoadBalancerStatus{
- Ingress: []api.LoadBalancerIngress{{IP: "2.3.4.5"}, {IP: "3.4.5.6"}, {IP: "5.6.7.8", Hostname: "host5678"}}},
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"service4", "LoadBalancer", "1.5.6.7", "2.3.4.5,3.4.5.6,5.6.7.8", "80/TCP,8090/UDP,8000/TCP", "<unknown>", "foo=bar"}}},
- },
- }
- for i, test := range tests {
- rows, err := printService(&test.service, test.options)
- if err != nil {
- t.Fatalf("Error printing table rows for Service: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintPod(t *testing.T) {
- tests := []struct {
- pod api.Pod
- expect []metav1.TableRow
- }{
- {
- // Test name, num of containers, restarts, container ready status
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test1"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "<unknown>"}}},
- },
- {
- // Test container error overwrites pod phase
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test2"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {State: api.ContainerState{Waiting: &api.ContainerStateWaiting{Reason: "ContainerWaitingReason"}}, RestartCount: 3},
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), "<unknown>"}}},
- },
- {
- // Test the same as the above but with Terminated state and the first container overwrites the rest
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test3"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {State: api.ContainerState{Waiting: &api.ContainerStateWaiting{Reason: "ContainerWaitingReason"}}, RestartCount: 3},
- {State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "ContainerTerminatedReason"}}, RestartCount: 3},
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test3", "0/2", "ContainerWaitingReason", int64(6), "<unknown>"}}},
- },
- {
- // Test ready is not enough for reporting running
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test4"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {Ready: true, RestartCount: 3},
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test4", "1/2", "podPhase", int64(6), "<unknown>"}}},
- },
- {
- // Test ready is not enough for reporting running
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test5"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Reason: "podReason",
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {Ready: true, RestartCount: 3},
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test5", "1/2", "podReason", int64(6), "<unknown>"}}},
- },
- {
- // Test pod has 2 containers, one is running and the other is completed.
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test6"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "Running",
- Reason: "",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}}},
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test6", "1/2", "Running", int64(6), "<unknown>"}}},
- },
- }
- for i, test := range tests {
- rows, err := printPod(&test.pod, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expect, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expect, rows))
- }
- }
- }
- func TestPrintPodwide(t *testing.T) {
- condition1 := "condition1"
- condition2 := "condition2"
- condition3 := "condition3"
- tests := []struct {
- pod api.Pod
- expect []metav1.TableRow
- }{
- {
- // Test when the NodeName and PodIP are not none
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test1"},
- Spec: api.PodSpec{
- Containers: make([]api.Container, 2),
- NodeName: "test1",
- ReadinessGates: []api.PodReadinessGate{
- {
- ConditionType: api.PodConditionType(condition1),
- },
- {
- ConditionType: api.PodConditionType(condition2),
- },
- {
- ConditionType: api.PodConditionType(condition3),
- },
- },
- },
- Status: api.PodStatus{
- Conditions: []api.PodCondition{
- {
- Type: api.PodConditionType(condition1),
- Status: api.ConditionFalse,
- },
- {
- Type: api.PodConditionType(condition2),
- Status: api.ConditionTrue,
- },
- },
- Phase: "podPhase",
- PodIPs: []api.PodIP{{IP: "1.1.1.1"}},
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- NominatedNodeName: "node1",
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "<unknown>", "1.1.1.1", "test1", "node1", "1/3"}}},
- },
- {
- // Test when the NodeName and PodIP are not none
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test1"},
- Spec: api.PodSpec{
- Containers: make([]api.Container, 2),
- NodeName: "test1",
- ReadinessGates: []api.PodReadinessGate{
- {
- ConditionType: api.PodConditionType(condition1),
- },
- {
- ConditionType: api.PodConditionType(condition2),
- },
- {
- ConditionType: api.PodConditionType(condition3),
- },
- },
- },
- Status: api.PodStatus{
- Conditions: []api.PodCondition{
- {
- Type: api.PodConditionType(condition1),
- Status: api.ConditionFalse,
- },
- {
- Type: api.PodConditionType(condition2),
- Status: api.ConditionTrue,
- },
- },
- Phase: "podPhase",
- PodIPs: []api.PodIP{{IP: "1.1.1.1"}, {IP: "2001:db8::"}},
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- NominatedNodeName: "node1",
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "<unknown>", "1.1.1.1", "test1", "node1", "1/3"}}},
- },
- {
- // Test when the NodeName and PodIP are none
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test2"},
- Spec: api.PodSpec{
- Containers: make([]api.Container, 2),
- NodeName: "",
- },
- Status: api.PodStatus{
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {State: api.ContainerState{Waiting: &api.ContainerStateWaiting{Reason: "ContainerWaitingReason"}}, RestartCount: 3},
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), "<unknown>", "<none>", "<none>", "<none>", "<none>"}}},
- },
- }
- for i, test := range tests {
- rows, err := printPod(&test.pod, printers.GenerateOptions{Wide: true})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expect, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expect, rows))
- }
- }
- }
- func TestPrintPodConditions(t *testing.T) {
- runningPod := &api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test1", Labels: map[string]string{"a": "1", "b": "2"}},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "Running",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- }
- succeededPod := &api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test1", Labels: map[string]string{"a": "1", "b": "2"}},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "Succeeded",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- }
- failedPod := &api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test2", Labels: map[string]string{"b": "2"}},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "Failed",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- }
- tests := []struct {
- pod *api.Pod
- expect []metav1.TableRow
- }{
- // Should not have TableRowCondition
- {
- pod: runningPod,
- // Columns: Name, Ready, Reason, Restarts, Age
- expect: []metav1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", int64(6), "<unknown>"}}},
- },
- // Should have TableRowCondition: podSuccessConditions
- {
- pod: succeededPod,
- expect: []metav1.TableRow{
- {
- // Columns: Name, Ready, Reason, Restarts, Age
- Cells: []interface{}{"test1", "1/2", "Succeeded", int64(6), "<unknown>"},
- Conditions: podSuccessConditions,
- },
- },
- },
- // Should have TableRowCondition: podFailedCondition
- {
- pod: failedPod,
- expect: []metav1.TableRow{
- {
- // Columns: Name, Ready, Reason, Restarts, Age
- Cells: []interface{}{"test2", "1/2", "Failed", int64(6), "<unknown>"},
- Conditions: podFailedConditions,
- },
- },
- },
- }
- for i, test := range tests {
- rows, err := printPod(test.pod, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expect, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expect, rows))
- }
- }
- }
- func TestPrintPodList(t *testing.T) {
- tests := []struct {
- pods api.PodList
- expect []metav1.TableRow
- }{
- // Test podList's pod: name, num of containers, restarts, container ready status
- {
- api.PodList{
- Items: []api.Pod{
- {
- ObjectMeta: metav1.ObjectMeta{Name: "test1"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- },
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: "test2"},
- Spec: api.PodSpec{Containers: make([]api.Container, 1)},
- Status: api.PodStatus{
- Phase: "podPhase",
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 1, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- },
- },
- },
- },
- },
- []metav1.TableRow{{Cells: []interface{}{"test1", "2/2", "podPhase", int64(6), "<unknown>"}}, {Cells: []interface{}{"test2", "1/1", "podPhase", int64(1), "<unknown>"}}},
- },
- }
- for _, test := range tests {
- rows, err := printPodList(&test.pods, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expect, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(test.expect, rows))
- }
- }
- }
- func TestPrintNonTerminatedPod(t *testing.T) {
- tests := []struct {
- pod api.Pod
- expect []metav1.TableRow
- }{
- {
- // Test pod phase Running should be printed
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test1"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: api.PodRunning,
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- },
- // Columns: Name, Ready, Reason, Restarts, Age
- []metav1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", int64(6), "<unknown>"}}},
- },
- {
- // Test pod phase Pending should be printed
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test2"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: api.PodPending,
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- },
- // Columns: Name, Ready, Reason, Restarts, Age
- []metav1.TableRow{{Cells: []interface{}{"test2", "1/2", "Pending", int64(6), "<unknown>"}}},
- },
- {
- // Test pod phase Unknown should be printed
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test3"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: api.PodUnknown,
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- },
- // Columns: Name, Ready, Reason, Restarts, Age
- []metav1.TableRow{{Cells: []interface{}{"test3", "1/2", "Unknown", int64(6), "<unknown>"}}},
- },
- {
- // Test pod phase Succeeded should be printed
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test4"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: api.PodSucceeded,
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {RestartCount: 3},
- },
- },
- },
- // Columns: Name, Ready, Reason, Restarts, Age
- []metav1.TableRow{
- {
- Cells: []interface{}{"test4", "1/2", "Succeeded", int64(6), "<unknown>"},
- Conditions: podSuccessConditions,
- },
- },
- },
- {
- // Test pod phase Failed shouldn't be printed
- api.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "test5"},
- Spec: api.PodSpec{Containers: make([]api.Container, 2)},
- Status: api.PodStatus{
- Phase: api.PodFailed,
- ContainerStatuses: []api.ContainerStatus{
- {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
- {Ready: true, RestartCount: 3},
- },
- },
- },
- // Columns: Name, Ready, Reason, Restarts, Age
- []metav1.TableRow{
- {
- Cells: []interface{}{"test5", "1/2", "Failed", int64(6), "<unknown>"},
- Conditions: podFailedConditions,
- },
- },
- },
- }
- for i, test := range tests {
- rows, err := printPod(&test.pod, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expect, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expect, rows))
- }
- }
- }
- func TestPrintPodTemplate(t *testing.T) {
- tests := []struct {
- podTemplate api.PodTemplate
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Test basic pod template with no containers.
- {
- podTemplate: api.PodTemplate{
- ObjectMeta: metav1.ObjectMeta{Name: "pod-template-1"},
- Template: api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{Name: "pod-template-1"},
- Spec: api.PodSpec{
- Containers: []api.Container{},
- },
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Containers, Images, Pod Labels
- expected: []metav1.TableRow{{Cells: []interface{}{"pod-template-1", "", "", "<none>"}}},
- },
- // Test basic pod template with two containers.
- {
- podTemplate: api.PodTemplate{
- ObjectMeta: metav1.ObjectMeta{Name: "pod-template-2"},
- Template: api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{Name: "pod-template-2"},
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Containers, Images, Pod Labels
- expected: []metav1.TableRow{{Cells: []interface{}{"pod-template-2", "fake-container1,fake-container2", "fake-image1,fake-image2", "<none>"}}},
- },
- // Test basic pod template with pod labels
- {
- podTemplate: api.PodTemplate{
- ObjectMeta: metav1.ObjectMeta{Name: "pod-template-3"},
- Template: api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod-template-3",
- Labels: map[string]string{"foo": "bar"},
- },
- Spec: api.PodSpec{
- Containers: []api.Container{},
- },
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Containers, Images, Pod Labels
- expected: []metav1.TableRow{{Cells: []interface{}{"pod-template-3", "", "", "foo=bar"}}},
- },
- }
- for i, test := range tests {
- rows, err := printPodTemplate(&test.podTemplate, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintPodTemplateList(t *testing.T) {
- templateList := api.PodTemplateList{
- Items: []api.PodTemplate{
- {
- ObjectMeta: metav1.ObjectMeta{Name: "pod-template-1"},
- Template: api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod-template-2",
- Labels: map[string]string{"foo": "bar"},
- },
- Spec: api.PodSpec{
- Containers: []api.Container{},
- },
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: "pod-template-2"},
- Template: api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod-template-2",
- Labels: map[string]string{"a": "b"},
- },
- Spec: api.PodSpec{
- Containers: []api.Container{},
- },
- },
- },
- },
- }
- // Columns: Name, Containers, Images, Pod Labels
- expectedRows := []metav1.TableRow{
- {Cells: []interface{}{"pod-template-1", "", "", "foo=bar"}},
- {Cells: []interface{}{"pod-template-2", "", "", "a=b"}},
- }
- rows, err := printPodTemplateList(&templateList, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error printing pod template list: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(expectedRows, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expectedRows, rows))
- }
- }
- type stringTestList []struct {
- name, got, exp string
- }
- func TestTranslateTimestampSince(t *testing.T) {
- tl := stringTestList{
- {"a while from now", translateTimestampSince(metav1.Time{Time: time.Now().Add(2.1e9)}), "<invalid>"},
- {"almost now", translateTimestampSince(metav1.Time{Time: time.Now().Add(1.9e9)}), "0s"},
- {"now", translateTimestampSince(metav1.Time{Time: time.Now()}), "0s"},
- {"unknown", translateTimestampSince(metav1.Time{}), "<unknown>"},
- {"30 seconds ago", translateTimestampSince(metav1.Time{Time: time.Now().Add(-3e10)}), "30s"},
- {"5 minutes ago", translateTimestampSince(metav1.Time{Time: time.Now().Add(-3e11)}), "5m"},
- {"an hour ago", translateTimestampSince(metav1.Time{Time: time.Now().Add(-6e12)}), "100m"},
- {"2 days ago", translateTimestampSince(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -2)}), "2d"},
- {"months ago", translateTimestampSince(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -90)}), "90d"},
- {"10 years ago", translateTimestampSince(metav1.Time{Time: time.Now().UTC().AddDate(-10, 0, 0)}), "10y"},
- }
- for _, test := range tl {
- if test.got != test.exp {
- t.Errorf("On %v, expected '%v', but got '%v'",
- test.name, test.exp, test.got)
- }
- }
- }
- func TestTranslateTimestampUntil(t *testing.T) {
- // Since this method compares the time with time.Now() internally,
- // small buffers of 0.1 seconds are added on comparing times to consider method call overhead.
- // Otherwise, the output strings become shorter than expected.
- const buf = 1e8
- tl := stringTestList{
- {"a while ago", translateTimestampUntil(metav1.Time{Time: time.Now().Add(-2.1e9)}), "<invalid>"},
- {"almost now", translateTimestampUntil(metav1.Time{Time: time.Now().Add(-1.9e9)}), "0s"},
- {"now", translateTimestampUntil(metav1.Time{Time: time.Now()}), "0s"},
- {"unknown", translateTimestampUntil(metav1.Time{}), "<unknown>"},
- {"in 30 seconds", translateTimestampUntil(metav1.Time{Time: time.Now().Add(3e10 + buf)}), "30s"},
- {"in 5 minutes", translateTimestampUntil(metav1.Time{Time: time.Now().Add(3e11 + buf)}), "5m"},
- {"in an hour", translateTimestampUntil(metav1.Time{Time: time.Now().Add(6e12 + buf)}), "100m"},
- {"in 2 days", translateTimestampUntil(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, 2).Add(buf)}), "2d"},
- {"in months", translateTimestampUntil(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, 90).Add(buf)}), "90d"},
- {"in 10 years", translateTimestampUntil(metav1.Time{Time: time.Now().UTC().AddDate(10, 0, 0).Add(buf)}), "10y"},
- }
- for _, test := range tl {
- if test.got != test.exp {
- t.Errorf("On %v, expected '%v', but got '%v'",
- test.name, test.exp, test.got)
- }
- }
- }
- func TestPrintDeployment(t *testing.T) {
- testDeployment := apps.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.DeploymentSpec{
- Replicas: 5,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- },
- Status: apps.DeploymentStatus{
- Replicas: 10,
- UpdatedReplicas: 2,
- AvailableReplicas: 1,
- UnavailableReplicas: 4,
- },
- }
- tests := []struct {
- deployment apps.Deployment
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Test Deployment with no generate options.
- {
- deployment: testDeployment,
- options: printers.GenerateOptions{},
- // Columns: Name, ReadyReplicas, UpdatedReplicas, AvailableReplicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "0/5", int64(2), int64(1), "0s"}}},
- },
- // Test generate options: Wide.
- {
- deployment: testDeployment,
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, ReadyReplicas, UpdatedReplicas, AvailableReplicas, Age, Containers, Images, Selectors
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "0/5", int64(2), int64(1), "0s", "fake-container1,fake-container2", "fake-image1,fake-image2", "foo=bar"}}},
- },
- }
- for i, test := range tests {
- rows, err := printDeployment(&test.deployment, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintDaemonSet(t *testing.T) {
- testDaemonSet := apps.DaemonSet{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.DaemonSetSpec{
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- },
- Status: apps.DaemonSetStatus{
- CurrentNumberScheduled: 2,
- DesiredNumberScheduled: 3,
- NumberReady: 1,
- UpdatedNumberScheduled: 2,
- NumberAvailable: 0,
- },
- }
- tests := []struct {
- daemonSet apps.DaemonSet
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Test generate daemon set with no generate options.
- {
- daemonSet: testDaemonSet,
- options: printers.GenerateOptions{},
- // Columns: Name, Num Desired, Num Current, Num Ready, Num Updated, Num Available, Selectors, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", int64(3), int64(2), int64(1), int64(2), int64(0), "<none>", "0s"}}},
- },
- // Test generate daemon set with "Wide" generate options.
- {
- daemonSet: testDaemonSet,
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Num Desired, Num Current, Num Ready, Num Updated, Num Available, Node Selectors, Age, Containers, Images, Labels
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", int64(3), int64(2), int64(1), int64(2), int64(0), "<none>", "0s", "fake-container1,fake-container2", "fake-image1,fake-image2", "foo=bar"}}},
- },
- }
- for i, test := range tests {
- rows, err := printDaemonSet(&test.daemonSet, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintDaemonSetList(t *testing.T) {
- daemonSetList := apps.DaemonSetList{
- Items: []apps.DaemonSet{
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "daemonset1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.DaemonSetSpec{
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- },
- Status: apps.DaemonSetStatus{
- CurrentNumberScheduled: 2,
- DesiredNumberScheduled: 3,
- NumberReady: 1,
- UpdatedNumberScheduled: 2,
- NumberAvailable: 0,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "daemonset2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.DaemonSetSpec{
- Template: api.PodTemplateSpec{},
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- },
- Status: apps.DaemonSetStatus{
- CurrentNumberScheduled: 4,
- DesiredNumberScheduled: 2,
- NumberReady: 9,
- UpdatedNumberScheduled: 3,
- NumberAvailable: 3,
- },
- },
- },
- }
- // Columns: Name, Num Desired, Num Current, Num Ready, Num Updated, Num Available, Selectors, Age
- expectedRows := []metav1.TableRow{
- {Cells: []interface{}{"daemonset1", int64(3), int64(2), int64(1), int64(2), int64(0), "<none>", "0s"}},
- {Cells: []interface{}{"daemonset2", int64(2), int64(4), int64(9), int64(3), int64(3), "<none>", "0s"}},
- }
- rows, err := printDaemonSetList(&daemonSetList, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error printing daemon set list: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(expectedRows, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expectedRows, rows))
- }
- }
- func TestPrintJob(t *testing.T) {
- now := time.Now()
- completions := int32(2)
- tests := []struct {
- job batch.Job
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- {
- // Generate table rows for Job with no generate options.
- job: batch.Job{
- ObjectMeta: metav1.ObjectMeta{
- Name: "job1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.JobSpec{
- Completions: &completions,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-job-container1",
- Image: "fake-job-image1",
- },
- {
- Name: "fake-job-container2",
- Image: "fake-job-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"job-label": "job-lable-value"}},
- },
- Status: batch.JobStatus{
- Succeeded: 1,
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Completions, Duration, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"job1", "1/2", "", "0s"}}},
- },
- // Generate table rows for Job with generate options "Wide".
- {
- job: batch.Job{
- ObjectMeta: metav1.ObjectMeta{
- Name: "job1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.JobSpec{
- Completions: &completions,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-job-container1",
- Image: "fake-job-image1",
- },
- {
- Name: "fake-job-container2",
- Image: "fake-job-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"job-label": "job-label-value"}},
- },
- Status: batch.JobStatus{
- Succeeded: 1,
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Completions, Duration, Age, Containers, Images, Selectors
- expected: []metav1.TableRow{
- {
- Cells: []interface{}{"job1", "1/2", "", "0s", "fake-job-container1,fake-job-container2", "fake-job-image1,fake-job-image2", "job-label=job-label-value"},
- },
- },
- },
- // Job with ten-year age.
- {
- job: batch.Job{
- ObjectMeta: metav1.ObjectMeta{
- Name: "job2",
- CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)},
- },
- Spec: batch.JobSpec{
- Completions: nil,
- },
- Status: batch.JobStatus{
- Succeeded: 0,
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Completions, Duration, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"job2", "0/1", "", "10y"}}},
- },
- // Job with duration.
- {
- job: batch.Job{
- ObjectMeta: metav1.ObjectMeta{
- Name: "job3",
- CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)},
- },
- Spec: batch.JobSpec{
- Completions: nil,
- },
- Status: batch.JobStatus{
- Succeeded: 0,
- StartTime: &metav1.Time{Time: now.Add(time.Minute)},
- CompletionTime: &metav1.Time{Time: now.Add(31 * time.Minute)},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Completions, Duration, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"job3", "0/1", "30m", "10y"}}},
- },
- {
- job: batch.Job{
- ObjectMeta: metav1.ObjectMeta{
- Name: "job4",
- CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)},
- },
- Spec: batch.JobSpec{
- Completions: nil,
- },
- Status: batch.JobStatus{
- Succeeded: 0,
- StartTime: &metav1.Time{Time: time.Now().Add(-20 * time.Minute)},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Completions, Duration, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"job4", "0/1", "20m", "10y"}}},
- },
- }
- for i, test := range tests {
- rows, err := printJob(&test.job, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintJobList(t *testing.T) {
- completions := int32(2)
- jobList := batch.JobList{
- Items: []batch.Job{
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "job1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.JobSpec{
- Completions: &completions,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-job-container1",
- Image: "fake-job-image1",
- },
- {
- Name: "fake-job-container2",
- Image: "fake-job-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"job-label": "job-lable-value"}},
- },
- Status: batch.JobStatus{
- Succeeded: 1,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "job2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.JobSpec{
- Completions: &completions,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-job-container1",
- Image: "fake-job-image1",
- },
- {
- Name: "fake-job-container2",
- Image: "fake-job-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"job-label": "job-lable-value"}},
- },
- Status: batch.JobStatus{
- Succeeded: 2,
- StartTime: &metav1.Time{Time: time.Now().Add(-20 * time.Minute)},
- },
- },
- },
- }
- // Columns: Name, Completions, Duration, Age
- expectedRows := []metav1.TableRow{
- {Cells: []interface{}{"job1", "1/2", "", "0s"}},
- {Cells: []interface{}{"job2", "2/2", "20m", "0s"}},
- }
- rows, err := printJobList(&jobList, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error printing job list: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(expectedRows, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expectedRows, rows))
- }
- }
- func TestPrintHPA(t *testing.T) {
- minReplicasVal := int32(2)
- targetUtilizationVal := int32(80)
- currentUtilizationVal := int32(50)
- metricLabelSelector, err := metav1.ParseToLabelSelector("label=value")
- if err != nil {
- t.Errorf("unable to parse label selector: %v", err)
- }
- tests := []struct {
- hpa autoscaling.HorizontalPodAutoscaler
- expected []metav1.TableRow
- }{
- // minReplicas unset
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MaxReplicas: 10,
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<none>", "<unset>", int64(10), int64(4), "<unknown>"}}},
- },
- // external source type, target average value (no current)
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ExternalMetricSourceType,
- External: &autoscaling.ExternalMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-external-metric",
- Selector: metricLabelSelector,
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/100m (avg)", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // external source type, target average value
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ExternalMetricSourceType,
- External: &autoscaling.ExternalMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-external-metric",
- Selector: metricLabelSelector,
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- CurrentMetrics: []autoscaling.MetricStatus{
- {
- Type: autoscaling.ExternalMetricSourceType,
- External: &autoscaling.ExternalMetricStatus{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-external-metric",
- Selector: metricLabelSelector,
- },
- Current: autoscaling.MetricValueStatus{
- AverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
- },
- },
- },
- },
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50m/100m (avg)", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // external source type, target value (no current)
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ExternalMetricSourceType,
- External: &autoscaling.ExternalMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-service-metric",
- Selector: metricLabelSelector,
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.ValueMetricType,
- Value: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // external source type, target value
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ExternalMetricSourceType,
- External: &autoscaling.ExternalMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-external-metric",
- Selector: metricLabelSelector,
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.ValueMetricType,
- Value: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- CurrentMetrics: []autoscaling.MetricStatus{
- {
- Type: autoscaling.ExternalMetricSourceType,
- External: &autoscaling.ExternalMetricStatus{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-external-metric",
- },
- Current: autoscaling.MetricValueStatus{
- Value: resource.NewMilliQuantity(50, resource.DecimalSI),
- },
- },
- },
- },
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50m/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // pods source type (no current)
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.PodsMetricSourceType,
- Pods: &autoscaling.PodsMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-pods-metric",
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // pods source type
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.PodsMetricSourceType,
- Pods: &autoscaling.PodsMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-pods-metric",
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- CurrentMetrics: []autoscaling.MetricStatus{
- {
- Type: autoscaling.PodsMetricSourceType,
- Pods: &autoscaling.PodsMetricStatus{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-pods-metric",
- },
- Current: autoscaling.MetricValueStatus{
- AverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
- },
- },
- },
- },
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50m/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // object source type (no current)
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ObjectMetricSourceType,
- Object: &autoscaling.ObjectMetricSource{
- DescribedObject: autoscaling.CrossVersionObjectReference{
- Name: "some-service",
- Kind: "Service",
- },
- Metric: autoscaling.MetricIdentifier{
- Name: "some-service-metric",
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.ValueMetricType,
- Value: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // object source type
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ObjectMetricSourceType,
- Object: &autoscaling.ObjectMetricSource{
- DescribedObject: autoscaling.CrossVersionObjectReference{
- Name: "some-service",
- Kind: "Service",
- },
- Metric: autoscaling.MetricIdentifier{
- Name: "some-service-metric",
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.ValueMetricType,
- Value: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- CurrentMetrics: []autoscaling.MetricStatus{
- {
- Type: autoscaling.ObjectMetricSourceType,
- Object: &autoscaling.ObjectMetricStatus{
- DescribedObject: autoscaling.CrossVersionObjectReference{
- Name: "some-service",
- Kind: "Service",
- },
- Metric: autoscaling.MetricIdentifier{
- Name: "some-service-metric",
- },
- Current: autoscaling.MetricValueStatus{
- Value: resource.NewMilliQuantity(50, resource.DecimalSI),
- },
- },
- },
- },
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50m/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // resource source type, targetVal (no current)
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricSource{
- Name: api.ResourceCPU,
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // resource source type, targetVal
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricSource{
- Name: api.ResourceCPU,
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- CurrentMetrics: []autoscaling.MetricStatus{
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricStatus{
- Name: api.ResourceCPU,
- Current: autoscaling.MetricValueStatus{
- AverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
- },
- },
- },
- },
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50m/100m", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // resource source type, targetUtil (no current)
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricSource{
- Name: api.ResourceCPU,
- Target: autoscaling.MetricTarget{
- Type: autoscaling.UtilizationMetricType,
- AverageUtilization: &targetUtilizationVal,
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/80%", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // resource source type, targetUtil
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricSource{
- Name: api.ResourceCPU,
- Target: autoscaling.MetricTarget{
- Type: autoscaling.UtilizationMetricType,
- AverageUtilization: &targetUtilizationVal,
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- CurrentMetrics: []autoscaling.MetricStatus{
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricStatus{
- Name: api.ResourceCPU,
- Current: autoscaling.MetricValueStatus{
- AverageUtilization: ¤tUtilizationVal,
- AverageValue: resource.NewMilliQuantity(40, resource.DecimalSI),
- },
- },
- },
- },
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50%/80%", "2", int64(10), int64(4), "<unknown>"}}},
- },
- // multiple specs
- {
- hpa: autoscaling.HorizontalPodAutoscaler{
- ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
- Spec: autoscaling.HorizontalPodAutoscalerSpec{
- ScaleTargetRef: autoscaling.CrossVersionObjectReference{
- Name: "some-rc",
- Kind: "ReplicationController",
- },
- MinReplicas: &minReplicasVal,
- MaxReplicas: 10,
- Metrics: []autoscaling.MetricSpec{
- {
- Type: autoscaling.PodsMetricSourceType,
- Pods: &autoscaling.PodsMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-pods-metric",
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
- },
- },
- },
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricSource{
- Name: api.ResourceCPU,
- Target: autoscaling.MetricTarget{
- Type: autoscaling.UtilizationMetricType,
- AverageUtilization: &targetUtilizationVal,
- },
- },
- },
- {
- Type: autoscaling.PodsMetricSourceType,
- Pods: &autoscaling.PodsMetricSource{
- Metric: autoscaling.MetricIdentifier{
- Name: "other-pods-metric",
- },
- Target: autoscaling.MetricTarget{
- Type: autoscaling.AverageValueMetricType,
- AverageValue: resource.NewMilliQuantity(400, resource.DecimalSI),
- },
- },
- },
- },
- },
- Status: autoscaling.HorizontalPodAutoscalerStatus{
- CurrentReplicas: 4,
- DesiredReplicas: 5,
- CurrentMetrics: []autoscaling.MetricStatus{
- {
- Type: autoscaling.PodsMetricSourceType,
- Pods: &autoscaling.PodsMetricStatus{
- Metric: autoscaling.MetricIdentifier{
- Name: "some-pods-metric",
- },
- Current: autoscaling.MetricValueStatus{
- AverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
- },
- },
- },
- {
- Type: autoscaling.ResourceMetricSourceType,
- Resource: &autoscaling.ResourceMetricStatus{
- Name: api.ResourceCPU,
- Current: autoscaling.MetricValueStatus{
- AverageUtilization: ¤tUtilizationVal,
- AverageValue: resource.NewMilliQuantity(40, resource.DecimalSI),
- },
- },
- },
- },
- },
- },
- // Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50m/100m, 50%/80% + 1 more...", "2", int64(10), int64(4), "<unknown>"}}},
- },
- }
- for i, test := range tests {
- rows, err := printHorizontalPodAutoscaler(&test.hpa, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintService(t *testing.T) {
- singleExternalIP := []string{"80.11.12.10"}
- mulExternalIP := []string{"80.11.12.10", "80.11.12.11"}
- tests := []struct {
- service api.Service
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- {
- // Test name, cluster ip, port with protocol
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test1"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeClusterIP,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 2233,
- },
- },
- ClusterIP: "10.9.8.7",
- Selector: map[string]string{"foo": "bar"}, // Does NOT get printed.
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "ClusterIP", "10.9.8.7", "<none>", "2233/tcp", "<unknown>"}}},
- },
- {
- // Test generate options: Wide includes selectors.
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test1"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeClusterIP,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 2233,
- },
- },
- ClusterIP: "10.9.8.7",
- Selector: map[string]string{"foo": "bar"},
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age, Selector
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "ClusterIP", "10.9.8.7", "<none>", "2233/tcp", "<unknown>", "foo=bar"}}},
- },
- {
- // Test NodePort service
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test2"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeNodePort,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 8888,
- NodePort: 9999,
- },
- },
- ClusterIP: "10.9.8.7",
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test2", "NodePort", "10.9.8.7", "<none>", "8888:9999/tcp", "<unknown>"}}},
- },
- {
- // Test LoadBalancer service
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test3"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeLoadBalancer,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 8888,
- },
- },
- ClusterIP: "10.9.8.7",
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test3", "LoadBalancer", "10.9.8.7", "<pending>", "8888/tcp", "<unknown>"}}},
- },
- {
- // Test LoadBalancer service with single ExternalIP and no LoadBalancerStatus
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test4"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeLoadBalancer,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 8888,
- },
- },
- ClusterIP: "10.9.8.7",
- ExternalIPs: singleExternalIP,
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test4", "LoadBalancer", "10.9.8.7", "80.11.12.10", "8888/tcp", "<unknown>"}}},
- },
- {
- // Test LoadBalancer service with single ExternalIP
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test5"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeLoadBalancer,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 8888,
- },
- },
- ClusterIP: "10.9.8.7",
- ExternalIPs: singleExternalIP,
- },
- Status: api.ServiceStatus{
- LoadBalancer: api.LoadBalancerStatus{
- Ingress: []api.LoadBalancerIngress{
- {
- IP: "3.4.5.6",
- Hostname: "test.cluster.com",
- },
- },
- },
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test5", "LoadBalancer", "10.9.8.7", "3.4.5.6,80.11.12.10", "8888/tcp", "<unknown>"}}},
- },
- {
- // Test LoadBalancer service with mul ExternalIPs
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test6"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeLoadBalancer,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 8888,
- },
- },
- ClusterIP: "10.9.8.7",
- ExternalIPs: mulExternalIP,
- },
- Status: api.ServiceStatus{
- LoadBalancer: api.LoadBalancerStatus{
- Ingress: []api.LoadBalancerIngress{
- {
- IP: "2.3.4.5",
- Hostname: "test.cluster.local",
- },
- {
- IP: "3.4.5.6",
- Hostname: "test.cluster.com",
- },
- },
- },
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test6", "LoadBalancer", "10.9.8.7", "2.3.4.5,3.4.5.6,80.11.12.10,80.11.12.11", "8888/tcp", "<unknown>"}}},
- },
- {
- // Test ExternalName service
- service: api.Service{
- ObjectMeta: metav1.ObjectMeta{Name: "test7"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeExternalName,
- ExternalName: "my.database.example.com",
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test7", "ExternalName", "<none>", "my.database.example.com", "<none>", "<unknown>"}}},
- },
- }
- for i, test := range tests {
- rows, err := printService(&test.service, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintServiceList(t *testing.T) {
- serviceList := api.ServiceList{
- Items: []api.Service{
- {
- ObjectMeta: metav1.ObjectMeta{Name: "service1"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeClusterIP,
- Ports: []api.ServicePort{
- {
- Protocol: "tcp",
- Port: 2233,
- },
- },
- ClusterIP: "10.9.8.7",
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: "service2"},
- Spec: api.ServiceSpec{
- Type: api.ServiceTypeNodePort,
- Ports: []api.ServicePort{
- {
- Protocol: "udp",
- Port: 5566,
- },
- },
- ClusterIP: "1.2.3.4",
- },
- },
- },
- }
- // Columns: Name, Type, Cluster-IP, External-IP, Port(s), Age
- expectedRows := []metav1.TableRow{
- {Cells: []interface{}{"service1", "ClusterIP", "10.9.8.7", "<none>", "2233/tcp", "<unknown>"}},
- {Cells: []interface{}{"service2", "NodePort", "1.2.3.4", "<none>", "5566/udp", "<unknown>"}},
- }
- rows, err := printServiceList(&serviceList, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error printing service list: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(expectedRows, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expectedRows, rows))
- }
- }
- func TestPrintPodDisruptionBudget(t *testing.T) {
- minAvailable := intstr.FromInt(22)
- maxUnavailable := intstr.FromInt(11)
- tests := []struct {
- pdb policy.PodDisruptionBudget
- expected []metav1.TableRow
- }{
- // Min Available set, no Max Available.
- {
- pdb: policy.PodDisruptionBudget{
- ObjectMeta: metav1.ObjectMeta{
- Namespace: "ns1",
- Name: "pdb1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: policy.PodDisruptionBudgetSpec{
- MinAvailable: &minAvailable,
- },
- Status: policy.PodDisruptionBudgetStatus{
- DisruptionsAllowed: 5,
- },
- },
- // Columns: Name, Min Available, Max Available, Allowed Disruptions, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"pdb1", "22", "N/A", int64(5), "0s"}}},
- },
- // Max Available set, no Min Available.
- {
- pdb: policy.PodDisruptionBudget{
- ObjectMeta: metav1.ObjectMeta{
- Namespace: "ns2",
- Name: "pdb2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: policy.PodDisruptionBudgetSpec{
- MaxUnavailable: &maxUnavailable,
- },
- Status: policy.PodDisruptionBudgetStatus{
- DisruptionsAllowed: 5,
- },
- },
- // Columns: Name, Min Available, Max Available, Allowed Disruptions, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"pdb2", "N/A", "11", int64(5), "0s"}}},
- }}
- for i, test := range tests {
- rows, err := printPodDisruptionBudget(&test.pdb, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintPodDisruptionBudgetList(t *testing.T) {
- minAvailable := intstr.FromInt(22)
- maxUnavailable := intstr.FromInt(11)
- pdbList := policy.PodDisruptionBudgetList{
- Items: []policy.PodDisruptionBudget{
- {
- ObjectMeta: metav1.ObjectMeta{
- Namespace: "ns1",
- Name: "pdb1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: policy.PodDisruptionBudgetSpec{
- MaxUnavailable: &maxUnavailable,
- },
- Status: policy.PodDisruptionBudgetStatus{
- DisruptionsAllowed: 5,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{
- Namespace: "ns2",
- Name: "pdb2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: policy.PodDisruptionBudgetSpec{
- MinAvailable: &minAvailable,
- },
- Status: policy.PodDisruptionBudgetStatus{
- DisruptionsAllowed: 3,
- },
- },
- },
- }
- // Columns: Name, Min Available, Max Available, Allowed Disruptions, Age
- expectedRows := []metav1.TableRow{
- {Cells: []interface{}{"pdb1", "N/A", "11", int64(5), "0s"}},
- {Cells: []interface{}{"pdb2", "22", "N/A", int64(3), "0s"}},
- }
- rows, err := printPodDisruptionBudgetList(&pdbList, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error printing pod template list: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(expectedRows, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expectedRows, rows))
- }
- }
- func TestPrintControllerRevision(t *testing.T) {
- tests := []struct {
- history apps.ControllerRevision
- expected []metav1.TableRow
- }{
- {
- history: apps.ControllerRevision{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- OwnerReferences: []metav1.OwnerReference{
- {
- Controller: boolP(true),
- APIVersion: "apps/v1",
- Kind: "DaemonSet",
- Name: "foo",
- },
- },
- },
- Revision: 1,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "daemonset.apps/foo", int64(1), "0s"}}},
- },
- {
- history: apps.ControllerRevision{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- OwnerReferences: []metav1.OwnerReference{
- {
- Controller: boolP(false),
- Kind: "ABC",
- Name: "foo",
- },
- },
- },
- Revision: 2,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test2", "<none>", int64(2), "0s"}}},
- },
- {
- history: apps.ControllerRevision{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test3",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- OwnerReferences: []metav1.OwnerReference{},
- },
- Revision: 3,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test3", "<none>", int64(3), "0s"}}},
- },
- {
- history: apps.ControllerRevision{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test4",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- OwnerReferences: nil,
- },
- Revision: 4,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test4", "<none>", int64(4), "0s"}}},
- },
- }
- for i, test := range tests {
- rows, err := printControllerRevision(&test.history, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func boolP(b bool) *bool {
- return &b
- }
- func TestPrintConfigMap(t *testing.T) {
- tests := []struct {
- configMap api.ConfigMap
- expected []metav1.TableRow
- }{
- // Basic config map with no data.
- {
- configMap: api.ConfigMap{
- ObjectMeta: metav1.ObjectMeta{
- Name: "configmap1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- },
- // Columns: Name, Data, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"configmap1", int64(0), "0s"}}},
- },
- // Basic config map with one data entry
- {
- configMap: api.ConfigMap{
- ObjectMeta: metav1.ObjectMeta{
- Name: "configmap2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Data: map[string]string{
- "foo": "bar",
- },
- },
- // Columns: Name, (Num) Data, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"configmap2", int64(1), "0s"}}},
- },
- // Basic config map with one data and one binary data entry.
- {
- configMap: api.ConfigMap{
- ObjectMeta: metav1.ObjectMeta{
- Name: "configmap3",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Data: map[string]string{
- "foo": "bar",
- },
- BinaryData: map[string][]byte{
- "bin": []byte("binary data"),
- },
- },
- // Columns: Name, (Num) Data, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"configmap3", int64(2), "0s"}}},
- },
- }
- for i, test := range tests {
- rows, err := printConfigMap(&test.configMap, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintNetworkPolicy(t *testing.T) {
- tests := []struct {
- policy networking.NetworkPolicy
- expected []metav1.TableRow
- }{
- // Basic network policy with empty spec.
- {
- policy: networking.NetworkPolicy{
- ObjectMeta: metav1.ObjectMeta{
- Name: "policy1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: networking.NetworkPolicySpec{},
- },
- // Columns: Name, Pod-Selector, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"policy1", "<none>", "0s"}}},
- },
- // Basic network policy with pod selector.
- {
- policy: networking.NetworkPolicy{
- ObjectMeta: metav1.ObjectMeta{
- Name: "policy2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: networking.NetworkPolicySpec{
- PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- },
- },
- // Columns: Name, Pod-Selector, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"policy2", "foo=bar", "0s"}}},
- },
- }
- for i, test := range tests {
- rows, err := printNetworkPolicy(&test.policy, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintRoleBinding(t *testing.T) {
- tests := []struct {
- binding rbac.RoleBinding
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Basic role binding
- {
- binding: rbac.RoleBinding{
- ObjectMeta: metav1.ObjectMeta{
- Name: "binding1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Subjects: []rbac.Subject{
- {
- Kind: "User",
- Name: "system:kube-controller-manager",
- },
- },
- RoleRef: rbac.RoleRef{
- Kind: "Role",
- Name: "extension-apiserver-authentication-reader",
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"binding1", "Role/extension-apiserver-authentication-reader", "0s"}}},
- },
- // Generate options=Wide; print subject and roles.
- {
- binding: rbac.RoleBinding{
- ObjectMeta: metav1.ObjectMeta{
- Name: "binding2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Subjects: []rbac.Subject{
- {
- Kind: "User",
- Name: "user-name",
- },
- {
- Kind: "Group",
- Name: "group-name",
- },
- {
- Kind: "ServiceAccount",
- Name: "service-account-name",
- Namespace: "service-account-namespace",
- },
- },
- RoleRef: rbac.RoleRef{
- Kind: "Role",
- Name: "role-name",
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Age, Role, Users, Groups, ServiceAccounts
- expected: []metav1.TableRow{{Cells: []interface{}{"binding2", "Role/role-name", "0s", "user-name", "group-name", "service-account-namespace/service-account-name"}}},
- },
- }
- for i, test := range tests {
- rows, err := printRoleBinding(&test.binding, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintClusterRoleBinding(t *testing.T) {
- tests := []struct {
- binding rbac.ClusterRoleBinding
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Basic cluster role binding
- {
- binding: rbac.ClusterRoleBinding{
- ObjectMeta: metav1.ObjectMeta{
- Name: "binding1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Subjects: []rbac.Subject{
- {
- Kind: "User",
- Name: "system:kube-controller-manager",
- },
- },
- RoleRef: rbac.RoleRef{
- Kind: "Role",
- Name: "extension-apiserver-authentication-reader",
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"binding1", "Role/extension-apiserver-authentication-reader", "0s"}}},
- },
- // Generate options=Wide; print subject and roles.
- {
- binding: rbac.ClusterRoleBinding{
- ObjectMeta: metav1.ObjectMeta{
- Name: "binding2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Subjects: []rbac.Subject{
- {
- Kind: "User",
- Name: "user-name",
- },
- {
- Kind: "Group",
- Name: "group-name",
- },
- {
- Kind: "ServiceAccount",
- Name: "service-account-name",
- Namespace: "service-account-namespace",
- },
- },
- RoleRef: rbac.RoleRef{
- Kind: "Role",
- Name: "role-name",
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Age, Role, Users, Groups, ServiceAccounts
- expected: []metav1.TableRow{{Cells: []interface{}{"binding2", "Role/role-name", "0s", "user-name", "group-name", "service-account-namespace/service-account-name"}}},
- },
- }
- for i, test := range tests {
- rows, err := printClusterRoleBinding(&test.binding, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintCertificateSigningRequest(t *testing.T) {
- tests := []struct {
- csr certificates.CertificateSigningRequest
- expected []metav1.TableRow
- }{
- // Basic CSR with no spec or status; defaults to status: Pending.
- {
- csr: certificates.CertificateSigningRequest{
- ObjectMeta: metav1.ObjectMeta{
- Name: "csr1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: certificates.CertificateSigningRequestSpec{},
- Status: certificates.CertificateSigningRequestStatus{},
- },
- // Columns: Name, Age, Requestor, Condition
- expected: []metav1.TableRow{{Cells: []interface{}{"csr1", "0s", "", "Pending"}}},
- },
- // Basic CSR with Spec and Status=Approved.
- {
- csr: certificates.CertificateSigningRequest{
- ObjectMeta: metav1.ObjectMeta{
- Name: "csr2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: certificates.CertificateSigningRequestSpec{
- Username: "CSR Requestor",
- },
- Status: certificates.CertificateSigningRequestStatus{
- Conditions: []certificates.CertificateSigningRequestCondition{
- {
- Type: certificates.CertificateApproved,
- },
- },
- },
- },
- // Columns: Name, Age, Requestor, Condition
- expected: []metav1.TableRow{{Cells: []interface{}{"csr2", "0s", "CSR Requestor", "Approved"}}},
- },
- // Basic CSR with Spec and Status=Approved; certificate issued.
- {
- csr: certificates.CertificateSigningRequest{
- ObjectMeta: metav1.ObjectMeta{
- Name: "csr2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: certificates.CertificateSigningRequestSpec{
- Username: "CSR Requestor",
- },
- Status: certificates.CertificateSigningRequestStatus{
- Conditions: []certificates.CertificateSigningRequestCondition{
- {
- Type: certificates.CertificateApproved,
- },
- },
- Certificate: []byte("cert data"),
- },
- },
- // Columns: Name, Age, Requestor, Condition
- expected: []metav1.TableRow{{Cells: []interface{}{"csr2", "0s", "CSR Requestor", "Approved,Issued"}}},
- },
- // Basic CSR with Spec and Status=Denied.
- {
- csr: certificates.CertificateSigningRequest{
- ObjectMeta: metav1.ObjectMeta{
- Name: "csr3",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: certificates.CertificateSigningRequestSpec{
- Username: "CSR Requestor",
- },
- Status: certificates.CertificateSigningRequestStatus{
- Conditions: []certificates.CertificateSigningRequestCondition{
- {
- Type: certificates.CertificateDenied,
- },
- },
- },
- },
- // Columns: Name, Age, Requestor, Condition
- expected: []metav1.TableRow{{Cells: []interface{}{"csr3", "0s", "CSR Requestor", "Denied"}}},
- },
- }
- for i, test := range tests {
- rows, err := printCertificateSigningRequest(&test.csr, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintReplicationController(t *testing.T) {
- tests := []struct {
- rc api.ReplicationController
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Basic print replication controller without replicas or status.
- {
- rc: api.ReplicationController{
- ObjectMeta: metav1.ObjectMeta{
- Name: "rc1",
- Namespace: "test-namespace",
- },
- Spec: api.ReplicationControllerSpec{
- Selector: map[string]string{"a": "b"},
- Template: &api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{"a": "b"},
- },
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "test",
- Image: "test_image",
- ImagePullPolicy: api.PullIfNotPresent,
- TerminationMessagePolicy: api.TerminationMessageReadFile,
- },
- },
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- },
- },
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Desired, Current, Ready, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"rc1", int64(0), int64(0), int64(0), "<unknown>"}}},
- },
- // Basic print replication controller with replicas; does not print containers or labels
- {
- rc: api.ReplicationController{
- ObjectMeta: metav1.ObjectMeta{
- Name: "rc1",
- Namespace: "test-namespace",
- },
- Spec: api.ReplicationControllerSpec{
- Replicas: 5,
- Selector: map[string]string{"a": "b"},
- Template: &api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{"a": "b"},
- },
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "test",
- Image: "test_image",
- ImagePullPolicy: api.PullIfNotPresent,
- TerminationMessagePolicy: api.TerminationMessageReadFile,
- },
- },
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- },
- },
- },
- Status: api.ReplicationControllerStatus{
- Replicas: 3,
- ReadyReplicas: 1,
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Desired, Current, Ready, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"rc1", int64(5), int64(3), int64(1), "<unknown>"}}},
- },
- // Generate options: Wide; print containers and labels.
- {
- rc: api.ReplicationController{
- ObjectMeta: metav1.ObjectMeta{
- Name: "rc1",
- },
- Spec: api.ReplicationControllerSpec{
- Replicas: 5,
- Selector: map[string]string{"a": "b"},
- Template: &api.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{"a": "b"},
- },
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "test",
- Image: "test_image",
- ImagePullPolicy: api.PullIfNotPresent,
- TerminationMessagePolicy: api.TerminationMessageReadFile,
- },
- },
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- },
- },
- },
- Status: api.ReplicationControllerStatus{
- Replicas: 3,
- ReadyReplicas: 1,
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Desired, Current, Ready, Age, Containers, Images, Selector
- expected: []metav1.TableRow{{Cells: []interface{}{"rc1", int64(5), int64(3), int64(1), "<unknown>", "test", "test_image", "a=b"}}},
- },
- }
- for i, test := range tests {
- rows, err := printReplicationController(&test.rc, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintReplicaSet(t *testing.T) {
- tests := []struct {
- replicaSet apps.ReplicaSet
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Generate options empty
- {
- replicaSet: apps.ReplicaSet{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.ReplicaSetSpec{
- Replicas: 5,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- },
- Status: apps.ReplicaSetStatus{
- Replicas: 5,
- ReadyReplicas: 2,
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Desired, Current, Ready, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", int64(5), int64(5), int64(2), "0s"}}},
- },
- // Generate options "Wide"
- {
- replicaSet: apps.ReplicaSet{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.ReplicaSetSpec{
- Replicas: 5,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- },
- Status: apps.ReplicaSetStatus{
- Replicas: 5,
- ReadyReplicas: 2,
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Desired, Current, Ready, Age, Containers, Images, Selector
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", int64(5), int64(5), int64(2), "0s", "fake-container1,fake-container2", "fake-image1,fake-image2", "foo=bar"}}},
- },
- }
- for i, test := range tests {
- rows, err := printReplicaSet(&test.replicaSet, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintReplicaSetList(t *testing.T) {
- replicaSetList := apps.ReplicaSetList{
- Items: []apps.ReplicaSet{
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "replicaset1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.ReplicaSetSpec{
- Replicas: 5,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- },
- Status: apps.ReplicaSetStatus{
- Replicas: 5,
- ReadyReplicas: 2,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "replicaset2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.ReplicaSetSpec{
- Replicas: 4,
- Template: api.PodTemplateSpec{},
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- },
- Status: apps.ReplicaSetStatus{
- Replicas: 3,
- ReadyReplicas: 1,
- },
- },
- },
- }
- // Columns: Name, Desired, Current, Ready, Age
- expectedRows := []metav1.TableRow{
- {Cells: []interface{}{"replicaset1", int64(5), int64(5), int64(2), "0s"}},
- {Cells: []interface{}{"replicaset2", int64(4), int64(3), int64(1), "0s"}},
- }
- rows, err := printReplicaSetList(&replicaSetList, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error printing replica set list: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(expectedRows, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expectedRows, rows))
- }
- }
- func TestPrintStatefulSet(t *testing.T) {
- tests := []struct {
- statefulSet apps.StatefulSet
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Basic stateful set; no generate options.
- {
- statefulSet: apps.StatefulSet{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.StatefulSetSpec{
- Replicas: 5,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- },
- Status: apps.StatefulSetStatus{
- Replicas: 5,
- ReadyReplicas: 2,
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Ready, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "2/5", "0s"}}},
- },
- // Generate options "Wide"; includes containers and images.
- {
- statefulSet: apps.StatefulSet{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: apps.StatefulSetSpec{
- Replicas: 5,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-container1",
- Image: "fake-image1",
- },
- {
- Name: "fake-container2",
- Image: "fake-image2",
- },
- },
- },
- },
- },
- Status: apps.StatefulSetStatus{
- Replicas: 5,
- ReadyReplicas: 2,
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Ready, Age, Containers, Images
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "2/5", "0s", "fake-container1,fake-container2", "fake-image1,fake-image2"}}},
- },
- }
- for i, test := range tests {
- rows, err := printStatefulSet(&test.statefulSet, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintPersistentVolume(t *testing.T) {
- myScn := "my-scn"
- claimRef := api.ObjectReference{
- Name: "test",
- Namespace: "default",
- }
- tests := []struct {
- pv api.PersistentVolume
- expected []metav1.TableRow
- }{
- {
- // Test bound
- pv: api.PersistentVolume{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- },
- Spec: api.PersistentVolumeSpec{
- ClaimRef: &claimRef,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("4Gi"),
- },
- },
- Status: api.PersistentVolumeStatus{
- Phase: api.VolumeBound,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "4Gi", "ROX", "", "Bound", "default/test", "", "", "<unknown>", "<unset>"}}},
- },
- {
- // Test failed
- pv: api.PersistentVolume{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test2",
- },
- Spec: api.PersistentVolumeSpec{
- ClaimRef: &claimRef,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("4Gi"),
- },
- },
- Status: api.PersistentVolumeStatus{
- Phase: api.VolumeFailed,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test2", "4Gi", "ROX", "", "Failed", "default/test", "", "", "<unknown>", "<unset>"}}},
- },
- {
- // Test pending
- pv: api.PersistentVolume{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test3",
- },
- Spec: api.PersistentVolumeSpec{
- ClaimRef: &claimRef,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteMany},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("10Gi"),
- },
- },
- Status: api.PersistentVolumeStatus{
- Phase: api.VolumePending,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test3", "10Gi", "RWX", "", "Pending", "default/test", "", "", "<unknown>", "<unset>"}}},
- },
- {
- // Test pending, storageClass
- pv: api.PersistentVolume{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test4",
- },
- Spec: api.PersistentVolumeSpec{
- ClaimRef: &claimRef,
- StorageClassName: myScn,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("10Gi"),
- },
- },
- Status: api.PersistentVolumeStatus{
- Phase: api.VolumePending,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test4", "10Gi", "RWO", "", "Pending", "default/test", "my-scn", "", "<unknown>", "<unset>"}}},
- },
- {
- // Test available
- pv: api.PersistentVolume{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test5",
- },
- Spec: api.PersistentVolumeSpec{
- ClaimRef: &claimRef,
- StorageClassName: myScn,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("10Gi"),
- },
- },
- Status: api.PersistentVolumeStatus{
- Phase: api.VolumeAvailable,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test5", "10Gi", "RWO", "", "Available", "default/test", "my-scn", "", "<unknown>", "<unset>"}}},
- },
- {
- // Test released
- pv: api.PersistentVolume{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test6",
- },
- Spec: api.PersistentVolumeSpec{
- ClaimRef: &claimRef,
- StorageClassName: myScn,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("10Gi"),
- },
- },
- Status: api.PersistentVolumeStatus{
- Phase: api.VolumeReleased,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test6", "10Gi", "RWO", "", "Released", "default/test", "my-scn", "", "<unknown>", "<unset>"}}},
- },
- }
- for i, test := range tests {
- rows, err := printPersistentVolume(&test.pv, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintPersistentVolumeClaim(t *testing.T) {
- volumeMode := api.PersistentVolumeFilesystem
- myScn := "my-scn"
- tests := []struct {
- pvc api.PersistentVolumeClaim
- expected []metav1.TableRow
- }{
- {
- // Test name, num of containers, restarts, container ready status
- pvc: api.PersistentVolumeClaim{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test1",
- },
- Spec: api.PersistentVolumeClaimSpec{
- VolumeName: "my-volume",
- VolumeMode: &volumeMode,
- },
- Status: api.PersistentVolumeClaimStatus{
- Phase: api.ClaimBound,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("4Gi"),
- },
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test1", "Bound", "my-volume", "4Gi", "ROX", "", "<unknown>", "Filesystem"}}},
- },
- {
- // Test name, num of containers, restarts, container ready status
- pvc: api.PersistentVolumeClaim{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test2",
- },
- Spec: api.PersistentVolumeClaimSpec{
- VolumeMode: &volumeMode,
- },
- Status: api.PersistentVolumeClaimStatus{
- Phase: api.ClaimLost,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("4Gi"),
- },
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test2", "Lost", "", "", "", "", "<unknown>", "Filesystem"}}},
- },
- {
- // Test name, num of containers, restarts, container ready status
- pvc: api.PersistentVolumeClaim{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test3",
- },
- Spec: api.PersistentVolumeClaimSpec{
- VolumeName: "my-volume",
- VolumeMode: &volumeMode,
- },
- Status: api.PersistentVolumeClaimStatus{
- Phase: api.ClaimPending,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteMany},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("10Gi"),
- },
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test3", "Pending", "my-volume", "10Gi", "RWX", "", "<unknown>", "Filesystem"}}},
- },
- {
- // Test name, num of containers, restarts, container ready status
- pvc: api.PersistentVolumeClaim{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test4",
- },
- Spec: api.PersistentVolumeClaimSpec{
- VolumeName: "my-volume",
- StorageClassName: &myScn,
- VolumeMode: &volumeMode,
- },
- Status: api.PersistentVolumeClaimStatus{
- Phase: api.ClaimPending,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("10Gi"),
- },
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test4", "Pending", "my-volume", "10Gi", "RWO", "my-scn", "<unknown>", "Filesystem"}}},
- },
- {
- // Test name, num of containers, restarts, container ready status
- pvc: api.PersistentVolumeClaim{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test5",
- },
- Spec: api.PersistentVolumeClaimSpec{
- VolumeName: "my-volume",
- StorageClassName: &myScn,
- },
- Status: api.PersistentVolumeClaimStatus{
- Phase: api.ClaimPending,
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
- Capacity: map[api.ResourceName]resource.Quantity{
- api.ResourceStorage: resource.MustParse("10Gi"),
- },
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"test5", "Pending", "my-volume", "10Gi", "RWO", "my-scn", "<unknown>", "<unset>"}}},
- },
- }
- for i, test := range tests {
- rows, err := printPersistentVolumeClaim(&test.pvc, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintComponentStatus(t *testing.T) {
- tests := []struct {
- componentStatus api.ComponentStatus
- expected []metav1.TableRow
- }{
- // Basic component status without conditions
- {
- componentStatus: api.ComponentStatus{
- ObjectMeta: metav1.ObjectMeta{
- Name: "cs1",
- },
- Conditions: []api.ComponentCondition{},
- },
- // Columns: Name, Status, Message, Error
- expected: []metav1.TableRow{{Cells: []interface{}{"cs1", "Unknown", "", ""}}},
- },
- // Basic component status with healthy condition.
- {
- componentStatus: api.ComponentStatus{
- ObjectMeta: metav1.ObjectMeta{
- Name: "cs2",
- },
- Conditions: []api.ComponentCondition{
- {
- Type: "Healthy",
- Status: api.ConditionTrue,
- Message: "test message",
- Error: "test error",
- },
- },
- },
- // Columns: Name, Status, Message, Error
- expected: []metav1.TableRow{{Cells: []interface{}{"cs2", "Healthy", "test message", "test error"}}},
- },
- // Basic component status with healthy condition.
- {
- componentStatus: api.ComponentStatus{
- ObjectMeta: metav1.ObjectMeta{
- Name: "cs3",
- },
- Conditions: []api.ComponentCondition{
- {
- Type: "Healthy",
- Status: api.ConditionFalse,
- Message: "test message",
- Error: "test error",
- },
- },
- },
- // Columns: Name, Status, Message, Error
- expected: []metav1.TableRow{{Cells: []interface{}{"cs3", "Unhealthy", "test message", "test error"}}},
- },
- }
- for i, test := range tests {
- rows, err := printComponentStatus(&test.componentStatus, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintCronJob(t *testing.T) {
- completions := int32(2)
- suspend := false
- tests := []struct {
- cronjob batch.CronJob
- options printers.GenerateOptions
- expected []metav1.TableRow
- }{
- // Basic cron job; does not print containers, images, or labels.
- {
- cronjob: batch.CronJob{
- ObjectMeta: metav1.ObjectMeta{
- Name: "cronjob1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.CronJobSpec{
- Schedule: "0/5 * * * ?",
- Suspend: &suspend,
- JobTemplate: batch.JobTemplateSpec{
- Spec: batch.JobSpec{
- Completions: &completions,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-job-container1",
- Image: "fake-job-image1",
- },
- {
- Name: "fake-job-container2",
- Image: "fake-job-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
- },
- },
- },
- Status: batch.CronJobStatus{
- LastScheduleTime: &metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Schedule, Suspend, Active, Last Schedule, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"cronjob1", "0/5 * * * ?", "False", int64(0), "0s", "0s"}}},
- },
- // Generate options: Wide; prints containers, images, and labels.
- {
- cronjob: batch.CronJob{
- ObjectMeta: metav1.ObjectMeta{
- Name: "cronjob1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.CronJobSpec{
- Schedule: "0/5 * * * ?",
- Suspend: &suspend,
- JobTemplate: batch.JobTemplateSpec{
- Spec: batch.JobSpec{
- Completions: &completions,
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "fake-job-container1",
- Image: "fake-job-image1",
- },
- {
- Name: "fake-job-container2",
- Image: "fake-job-image2",
- },
- },
- },
- },
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
- },
- },
- },
- Status: batch.CronJobStatus{
- LastScheduleTime: &metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- },
- options: printers.GenerateOptions{Wide: true},
- // Columns: Name, Schedule, Suspend, Active, Last Schedule, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"cronjob1", "0/5 * * * ?", "False", int64(0), "0s", "0s", "fake-job-container1,fake-job-container2", "fake-job-image1,fake-job-image2", "a=b"}}},
- },
- // CronJob with Last Schedule and Age
- {
- cronjob: batch.CronJob{
- ObjectMeta: metav1.ObjectMeta{
- Name: "cronjob2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Spec: batch.CronJobSpec{
- Schedule: "0/5 * * * ?",
- Suspend: &suspend,
- },
- Status: batch.CronJobStatus{
- LastScheduleTime: &metav1.Time{Time: time.Now().Add(-3e10)},
- },
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Schedule, Suspend, Active, Last Schedule, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"cronjob2", "0/5 * * * ?", "False", int64(0), "30s", "5m"}}},
- },
- // CronJob without Last Schedule
- {
- cronjob: batch.CronJob{
- ObjectMeta: metav1.ObjectMeta{
- Name: "cronjob3",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Spec: batch.CronJobSpec{
- Schedule: "0/5 * * * ?",
- Suspend: &suspend,
- },
- Status: batch.CronJobStatus{},
- },
- options: printers.GenerateOptions{},
- // Columns: Name, Schedule, Suspend, Active, Last Schedule, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"cronjob3", "0/5 * * * ?", "False", int64(0), "<none>", "5m"}}},
- },
- }
- for i, test := range tests {
- rows, err := printCronJob(&test.cronjob, test.options)
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintCronJobList(t *testing.T) {
- completions := int32(2)
- suspend := false
- cronJobList := batch.CronJobList{
- Items: []batch.CronJob{
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "cronjob1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.CronJobSpec{
- Schedule: "0/5 * * * ?",
- Suspend: &suspend,
- JobTemplate: batch.JobTemplateSpec{
- Spec: batch.JobSpec{
- Completions: &completions,
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
- },
- },
- },
- Status: batch.CronJobStatus{
- LastScheduleTime: &metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{
- Name: "cronjob2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: batch.CronJobSpec{
- Schedule: "4/5 1 1 1 ?",
- Suspend: &suspend,
- JobTemplate: batch.JobTemplateSpec{
- Spec: batch.JobSpec{
- Completions: &completions,
- Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
- },
- },
- },
- Status: batch.CronJobStatus{
- LastScheduleTime: &metav1.Time{Time: time.Now().Add(-20 * time.Minute)},
- },
- },
- },
- }
- // Columns: Name, Schedule, Suspend, Active, Last Schedule, Age
- expectedRows := []metav1.TableRow{
- {Cells: []interface{}{"cronjob1", "0/5 * * * ?", "False", int64(0), "0s", "0s"}},
- {Cells: []interface{}{"cronjob2", "4/5 1 1 1 ?", "False", int64(0), "20m", "0s"}},
- }
- rows, err := printCronJobList(&cronJobList, printers.GenerateOptions{})
- if err != nil {
- t.Fatalf("Error printing job list: %#v", err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(expectedRows, rows) {
- t.Errorf("mismatch: %s", diff.ObjectReflectDiff(expectedRows, rows))
- }
- }
- func TestPrintStorageClass(t *testing.T) {
- policyDelte := api.PersistentVolumeReclaimDelete
- policyRetain := api.PersistentVolumeReclaimRetain
- bindModeImmediate := storage.VolumeBindingImmediate
- bindModeWait := storage.VolumeBindingWaitForFirstConsumer
- tests := []struct {
- sc storage.StorageClass
- expected []metav1.TableRow
- }{
- {
- sc: storage.StorageClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sc1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Provisioner: "kubernetes.io/glusterfs",
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"sc1", "kubernetes.io/glusterfs", "Delete",
- "Immediate", false, "0s"}}},
- },
- {
- sc: storage.StorageClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sc2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Provisioner: "kubernetes.io/nfs",
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"sc2", "kubernetes.io/nfs", "Delete",
- "Immediate", false, "5m"}}},
- },
- {
- sc: storage.StorageClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sc3",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Provisioner: "kubernetes.io/nfs",
- ReclaimPolicy: &policyDelte,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"sc3", "kubernetes.io/nfs", "Delete",
- "Immediate", false, "5m"}}},
- },
- {
- sc: storage.StorageClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sc4",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Provisioner: "kubernetes.io/nfs",
- ReclaimPolicy: &policyRetain,
- VolumeBindingMode: &bindModeImmediate,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"sc4", "kubernetes.io/nfs", "Retain",
- "Immediate", false, "5m"}}},
- },
- {
- sc: storage.StorageClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sc5",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Provisioner: "kubernetes.io/nfs",
- ReclaimPolicy: &policyRetain,
- VolumeBindingMode: &bindModeWait,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"sc5", "kubernetes.io/nfs", "Retain",
- "WaitForFirstConsumer", false, "5m"}}},
- },
- {
- sc: storage.StorageClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "sc6",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Provisioner: "kubernetes.io/nfs",
- ReclaimPolicy: &policyRetain,
- AllowVolumeExpansion: boolP(true),
- VolumeBindingMode: &bindModeWait,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"sc6", "kubernetes.io/nfs", "Retain",
- "WaitForFirstConsumer", true, "5m"}}},
- },
- }
- for i, test := range tests {
- rows, err := printStorageClass(&test.sc, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintLease(t *testing.T) {
- holder1 := "holder1"
- holder2 := "holder2"
- tests := []struct {
- lease coordination.Lease
- expected []metav1.TableRow
- }{
- {
- lease: coordination.Lease{
- ObjectMeta: metav1.ObjectMeta{
- Name: "lease1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: coordination.LeaseSpec{
- HolderIdentity: &holder1,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"lease1", "holder1", "0s"}}},
- },
- {
- lease: coordination.Lease{
- ObjectMeta: metav1.ObjectMeta{
- Name: "lease2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Spec: coordination.LeaseSpec{
- HolderIdentity: &holder2,
- },
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"lease2", "holder2", "5m"}}},
- },
- }
- for i, test := range tests {
- rows, err := printLease(&test.lease, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintPriorityClass(t *testing.T) {
- tests := []struct {
- pc scheduling.PriorityClass
- expected []metav1.TableRow
- }{
- {
- pc: scheduling.PriorityClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pc1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Value: 1,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"pc1", int64(1), bool(false), "0s"}}},
- },
- {
- pc: scheduling.PriorityClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pc2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Value: 1000000000,
- GlobalDefault: true,
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"pc2", int64(1000000000), bool(true), "5m"}}},
- },
- }
- for i, test := range tests {
- rows, err := printPriorityClass(&test.pc, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintRuntimeClass(t *testing.T) {
- tests := []struct {
- rc nodeapi.RuntimeClass
- expected []metav1.TableRow
- }{
- {
- rc: nodeapi.RuntimeClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "rc1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Handler: "h1",
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"rc1", "h1", "0s"}}},
- },
- {
- rc: nodeapi.RuntimeClass{
- ObjectMeta: metav1.ObjectMeta{
- Name: "rc2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Handler: "h2",
- },
- expected: []metav1.TableRow{{Cells: []interface{}{"rc2", "h2", "5m"}}},
- },
- }
- for i, test := range tests {
- rows, err := printRuntimeClass(&test.rc, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintEndpoint(t *testing.T) {
- tests := []struct {
- endpoint api.Endpoints
- expected []metav1.TableRow
- }{
- // Basic endpoint with no IP's
- {
- endpoint: api.Endpoints{
- ObjectMeta: metav1.ObjectMeta{
- Name: "endpoint1",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- },
- // Columns: Name, Endpoints, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"endpoint1", "<none>", "0s"}}},
- },
- // Endpoint with no ports
- {
- endpoint: api.Endpoints{
- ObjectMeta: metav1.ObjectMeta{
- Name: "endpoint3",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Subsets: []api.EndpointSubset{
- {
- Addresses: []api.EndpointAddress{
- {
- IP: "1.2.3.4",
- },
- {
- IP: "5.6.7.8",
- },
- },
- },
- },
- },
- // Columns: Name, Endpoints, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"endpoint3", "1.2.3.4,5.6.7.8", "5m"}}},
- },
- // Basic endpoint with two IP's and one port
- {
- endpoint: api.Endpoints{
- ObjectMeta: metav1.ObjectMeta{
- Name: "endpoint2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Subsets: []api.EndpointSubset{
- {
- Addresses: []api.EndpointAddress{
- {
- IP: "1.2.3.4",
- },
- {
- IP: "5.6.7.8",
- },
- },
- Ports: []api.EndpointPort{
- {
- Port: 8001,
- Protocol: "tcp",
- },
- },
- },
- },
- },
- // Columns: Name, Endpoints, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"endpoint2", "1.2.3.4:8001,5.6.7.8:8001", "0s"}}},
- },
- // Basic endpoint with greater than three IP's triggering "more" string
- {
- endpoint: api.Endpoints{
- ObjectMeta: metav1.ObjectMeta{
- Name: "endpoint2",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Subsets: []api.EndpointSubset{
- {
- Addresses: []api.EndpointAddress{
- {
- IP: "1.2.3.4",
- },
- {
- IP: "5.6.7.8",
- },
- {
- IP: "9.8.7.6",
- },
- {
- IP: "6.6.6.6",
- },
- },
- Ports: []api.EndpointPort{
- {
- Port: 8001,
- Protocol: "tcp",
- },
- },
- },
- },
- },
- // Columns: Name, Endpoints, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"endpoint2", "1.2.3.4:8001,5.6.7.8:8001,9.8.7.6:8001 + 1 more...", "0s"}}},
- },
- }
- for i, test := range tests {
- rows, err := printEndpoints(&test.endpoint, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintEndpointSlice(t *testing.T) {
- tcpProtocol := api.ProtocolTCP
- tests := []struct {
- endpointSlice discovery.EndpointSlice
- expected []metav1.TableRow
- }{
- {
- endpointSlice: discovery.EndpointSlice{
- ObjectMeta: metav1.ObjectMeta{
- Name: "abcslice.123",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- AddressType: discovery.AddressTypeIPv4,
- Ports: []discovery.EndpointPort{{
- Name: utilpointer.StringPtr("http"),
- Port: utilpointer.Int32Ptr(80),
- Protocol: &tcpProtocol,
- }},
- Endpoints: []discovery.Endpoint{{
- Addresses: []string{"10.1.2.3", "2001:db8::1234:5678"},
- }},
- },
- // Columns: Name, AddressType, Ports, Endpoints, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"abcslice.123", "IPv4", "80", "10.1.2.3,2001:db8::1234:5678", "0s"}}},
- }, {
- endpointSlice: discovery.EndpointSlice{
- ObjectMeta: metav1.ObjectMeta{
- Name: "longerslicename.123",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- AddressType: discovery.AddressTypeIPv6,
- Ports: []discovery.EndpointPort{{
- Name: utilpointer.StringPtr("http"),
- Port: utilpointer.Int32Ptr(80),
- Protocol: &tcpProtocol,
- }, {
- Name: utilpointer.StringPtr("https"),
- Port: utilpointer.Int32Ptr(443),
- Protocol: &tcpProtocol,
- }},
- Endpoints: []discovery.Endpoint{{
- Addresses: []string{"10.1.2.3", "2001:db8::1234:5678"},
- }, {
- Addresses: []string{"10.2.3.4", "2001:db8::2345:6789"},
- }},
- },
- // Columns: Name, AddressType, Ports, Endpoints, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"longerslicename.123", "IPv6", "80,443", "10.1.2.3,2001:db8::1234:5678,10.2.3.4 + 1 more...", "5m"}}},
- }, {
- endpointSlice: discovery.EndpointSlice{
- ObjectMeta: metav1.ObjectMeta{
- Name: "multiportslice.123",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- AddressType: discovery.AddressTypeIPv4,
- Ports: []discovery.EndpointPort{{
- Name: utilpointer.StringPtr("http"),
- Port: utilpointer.Int32Ptr(80),
- Protocol: &tcpProtocol,
- }, {
- Name: utilpointer.StringPtr("https"),
- Port: utilpointer.Int32Ptr(443),
- Protocol: &tcpProtocol,
- }, {
- Name: utilpointer.StringPtr("extra1"),
- Port: utilpointer.Int32Ptr(3000),
- Protocol: &tcpProtocol,
- }, {
- Name: utilpointer.StringPtr("extra2"),
- Port: utilpointer.Int32Ptr(3001),
- Protocol: &tcpProtocol,
- }},
- Endpoints: []discovery.Endpoint{{
- Addresses: []string{"10.1.2.3", "2001:db8::1234:5678"},
- }, {
- Addresses: []string{"10.2.3.4", "2001:db8::2345:6789"},
- }},
- },
- // Columns: Name, AddressType, Ports, Endpoints, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"multiportslice.123", "IPv4", "80,443,3000 + 1 more...", "10.1.2.3,2001:db8::1234:5678,10.2.3.4 + 1 more...", "5m"}}},
- },
- }
- for i, test := range tests {
- rows, err := printEndpointSlice(&test.endpointSlice, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintFlowSchema(t *testing.T) {
- all := []string{"*"}
- tests := []struct {
- fs flowcontrol.FlowSchema
- expected []metav1.TableRow
- }{
- {
- fs: flowcontrol.FlowSchema{
- ObjectMeta: metav1.ObjectMeta{
- Name: "all-matcher",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: flowcontrol.FlowSchemaSpec{
- PriorityLevelConfiguration: flowcontrol.PriorityLevelConfigurationReference{Name: "allee"},
- MatchingPrecedence: math.MaxInt32,
- DistinguisherMethod: &flowcontrol.FlowDistinguisherMethod{Type: flowcontrol.FlowDistinguisherMethodByUserType},
- Rules: []flowcontrol.PolicyRulesWithSubjects{{
- Subjects: []flowcontrol.Subject{{
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:authenticated"},
- }},
- ResourceRules: []flowcontrol.ResourcePolicyRule{{
- Verbs: all,
- APIGroups: all,
- Resources: all,
- ClusterScope: true,
- Namespaces: all,
- }},
- }, {
- Subjects: []flowcontrol.Subject{{
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:unauthenticated"},
- }},
- ResourceRules: []flowcontrol.ResourcePolicyRule{{
- Verbs: all,
- APIGroups: all,
- Resources: all,
- ClusterScope: true,
- Namespaces: all,
- }},
- }, {
- Subjects: []flowcontrol.Subject{{
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:authenticated"},
- }, {
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:unauthenticated"},
- }},
- NonResourceRules: []flowcontrol.NonResourcePolicyRule{{
- Verbs: all,
- NonResourceURLs: all,
- }},
- }},
- },
- },
- // Columns: Name, PriorityLevelName, MatchingPrecedence, DistinguisherMethod, Age, MissingPL
- expected: []metav1.TableRow{{Cells: []interface{}{"all-matcher", "allee", int32(math.MaxInt32), "ByUser", "0s", "?"}}},
- }, {
- fs: flowcontrol.FlowSchema{
- ObjectMeta: metav1.ObjectMeta{
- Name: "some-matcher",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Spec: flowcontrol.FlowSchemaSpec{
- PriorityLevelConfiguration: flowcontrol.PriorityLevelConfigurationReference{Name: "allee"},
- MatchingPrecedence: 0,
- DistinguisherMethod: &flowcontrol.FlowDistinguisherMethod{Type: flowcontrol.FlowDistinguisherMethodByNamespaceType},
- Rules: []flowcontrol.PolicyRulesWithSubjects{{
- Subjects: []flowcontrol.Subject{{
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:unauthenticated"},
- }},
- ResourceRules: []flowcontrol.ResourcePolicyRule{{
- Verbs: all,
- APIGroups: all,
- Resources: all,
- ClusterScope: true,
- Namespaces: all,
- }},
- }, {
- Subjects: []flowcontrol.Subject{{
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:authenticated"},
- }, {
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:unauthenticated"},
- }},
- NonResourceRules: []flowcontrol.NonResourcePolicyRule{{
- Verbs: all,
- NonResourceURLs: all,
- }},
- }},
- },
- Status: flowcontrol.FlowSchemaStatus{
- Conditions: []flowcontrol.FlowSchemaCondition{{
- Type: flowcontrol.FlowSchemaConditionDangling,
- Status: "True",
- LastTransitionTime: metav1.Time{Time: time.Now().Add(-time.Hour)},
- }},
- },
- },
- // Columns: Name, PriorityLevelName, MatchingPrecedence, DistinguisherMethod, Age, MissingPL
- expected: []metav1.TableRow{{Cells: []interface{}{"some-matcher", "allee", int32(0), "ByNamespace", "5m", "True"}}},
- }, {
- fs: flowcontrol.FlowSchema{
- ObjectMeta: metav1.ObjectMeta{
- Name: "exempt",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(-3e11)},
- },
- Spec: flowcontrol.FlowSchemaSpec{
- PriorityLevelConfiguration: flowcontrol.PriorityLevelConfigurationReference{Name: "allee"},
- MatchingPrecedence: 0,
- DistinguisherMethod: nil,
- Rules: []flowcontrol.PolicyRulesWithSubjects{{
- Subjects: []flowcontrol.Subject{{
- Kind: flowcontrol.SubjectKindGroup,
- Group: &flowcontrol.GroupSubject{Name: "system:masters"},
- }},
- ResourceRules: []flowcontrol.ResourcePolicyRule{{
- Verbs: all,
- APIGroups: all,
- Resources: all,
- ClusterScope: true,
- Namespaces: all,
- }},
- }},
- },
- },
- // Columns: Name, PriorityLevelName, MatchingPrecedence, DistinguisherMethod, Age, MissingPL
- expected: []metav1.TableRow{{Cells: []interface{}{"exempt", "allee", int32(0), "<none>", "5m", "?"}}},
- },
- }
- for i, test := range tests {
- rows, err := printFlowSchema(&test.fs, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
- func TestPrintPriorityLevelConfiguration(t *testing.T) {
- tests := []struct {
- pl flowcontrol.PriorityLevelConfiguration
- expected []metav1.TableRow
- }{
- {
- pl: flowcontrol.PriorityLevelConfiguration{
- ObjectMeta: metav1.ObjectMeta{
- Name: "unlimited",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: flowcontrol.PriorityLevelConfigurationSpec{
- Type: flowcontrol.PriorityLevelEnablementExempt,
- },
- },
- // Columns: Name, Type, AssuredConcurrencyShares, Queues, HandSize, QueueLengthLimit, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"unlimited", "Exempt", "<none>", "<none>", "<none>", "<none>", "0s"}}},
- },
- {
- pl: flowcontrol.PriorityLevelConfiguration{
- ObjectMeta: metav1.ObjectMeta{
- Name: "unqueued",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: flowcontrol.PriorityLevelConfigurationSpec{
- Type: flowcontrol.PriorityLevelEnablementLimited,
- Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
- AssuredConcurrencyShares: 47,
- LimitResponse: flowcontrol.LimitResponse{
- Type: flowcontrol.LimitResponseTypeReject,
- },
- },
- },
- },
- // Columns: Name, Type, AssuredConcurrencyShares, Queues, HandSize, QueueLengthLimit, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"unqueued", "Limited", int32(47), "<none>", "<none>", "<none>", "0s"}}},
- },
- {
- pl: flowcontrol.PriorityLevelConfiguration{
- ObjectMeta: metav1.ObjectMeta{
- Name: "queued",
- CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)},
- },
- Spec: flowcontrol.PriorityLevelConfigurationSpec{
- Type: flowcontrol.PriorityLevelEnablementLimited,
- Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
- AssuredConcurrencyShares: 42,
- LimitResponse: flowcontrol.LimitResponse{
- Type: flowcontrol.LimitResponseTypeQueue,
- Queuing: &flowcontrol.QueuingConfiguration{
- Queues: 8,
- HandSize: 3,
- QueueLengthLimit: 4,
- },
- },
- },
- },
- },
- // Columns: Name, Type, AssuredConcurrencyShares, Queues, HandSize, QueueLengthLimit, Age
- expected: []metav1.TableRow{{Cells: []interface{}{"queued", "Limited", int32(42), int32(8), int32(3), int32(4), "0s"}}},
- },
- }
- for i, test := range tests {
- rows, err := printPriorityLevelConfiguration(&test.pl, printers.GenerateOptions{})
- if err != nil {
- t.Fatal(err)
- }
- for i := range rows {
- rows[i].Object.Object = nil
- }
- if !reflect.DeepEqual(test.expected, rows) {
- t.Errorf("%d mismatch: %s", i, diff.ObjectReflectDiff(test.expected, rows))
- }
- }
- }
|