// ĠCopyright Ġ 2 0 2 0 ĠThe ĠCross - Media ĠMeasurement Ġ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 Ġorg . wf an et . measurement . tools Ċ Ċ import Ġcom . google . gson . JsonObject Ċ import Ġcom . google . gson . Json Parser . parse Reader Ċ import Ġcom . google . gson . stream . Json Reader Ċ import Ġjava . io . Reader Ċ import Ġjava . lang . Exception Ċ import Ġjava . util . stream . Collectors Ċ import Ġkotlinx . coroutines . join All Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . run Blocking Ċ Ċ /** Ċ Ġ* ĠFetch Ġstate Ġof Ġa ĠKubernetes - in - Docker Ġ( kind ) Ġcluster . Ċ Ġ* Ċ Ġ* Ġ@ param Ġcluster Name ĠName Ġpassed Ġto Ġ` kind Ġcreate Ġcluster `. Ċ Ġ*/ Ċ class ĠCluster State ( private Ġval Ġcluster Name : ĠString Ġ= Ġ" kind ") Ġ{ ĊĠ Ġinit Ġ{ ĊĠĠĠ Ġrequire ( Regex ("[ A - z 0 - 9 _- ]+ "). matches ( cluster Name )) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ*/ ĊĠ Ġfun ĠgetNode Ip (): ĠString Ġ= ĊĠĠĠ Ġhandle Json (" kubectl Ġget Ġnode Ġ$ cluster Name - control - plane Ġ- o Ġjson ") Ġ{ Ġjson Ġ-> ĊĠĠĠĠĠ Ġjson ĊĠĠĠĠĠĠĠ Ġ. getAs JsonObject (" status ") ĊĠĠĠĠĠĠĠ Ġ. getAs JsonArray (" addresses ") ĊĠĠĠĠĠĠĠ Ġ. first Ġ{ Ġel Ġ-> Ġel . as JsonObject . getAs Json Primitive (" type "). asString Ġ== Ġ" Internal IP " Ġ} ĊĠĠĠĠĠĠĠ Ġ. as JsonObject ĊĠĠĠĠĠĠĠ Ġ. getAs Json Primitive (" address ") ĊĠĠĠĠĠĠĠ Ġ. asString ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠParses ĠKubernetes ĠService Ġspecs Ġto Ġfind Ġthe Ġones Ġthat Ġhave Ġnode Ġports Ġand Ġreturn Ġthem . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠFor Ġexample Ġthe Ġfollowing ĠJSON Ġwould Ġreturn Ġthe Ġsame ĠMap Ġas Ġthe ĠKotlin Ġcode : ĊĠĠ Ġ* Ġmap Of ( Pair (" my - service ", Ġmap Of ( Pair (" grpc ", Ġ 3 0 0 0 1 ), ĠPair (" http ", Ġ 3 0 0 0 2 )))) ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ{ Ġ" items ": Ġ[ ĊĠĠ Ġ* Ġ``` ĊĠĠ Ġ* ĠĠĠĠ Ġ" kind ": ĠService ĊĠĠ Ġ* ĠĠĠĠ Ġ" metadata ": Ġ{ ĊĠĠ Ġ* ĠĠĠĠĠĠ Ġ" name ": Ġ" my - service " ĊĠĠ Ġ* ĠĠĠĠ Ġ} ĊĠĠ Ġ* ĠĠĠĠ Ġ" spec ": Ġ{ ĊĠĠ Ġ* ĠĠĠĠĠĠ Ġ" type ": Ġ" Node Port " ĊĠĠ Ġ* ĠĠĠĠĠĠ Ġ" ports ": Ġ[ ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠĠĠ Ġ" name ": Ġ" grpc " ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠĠĠ Ġ" node Port ": Ġ 3 0 0 0 1 ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠ Ġ} ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠĠĠ Ġ" name ": Ġ" http " ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠĠĠ Ġ" node Port ": Ġ 3 0 0 0 2 ĊĠĠ Ġ* ĠĠĠĠĠĠĠĠ Ġ} ĊĠĠ Ġ* ĠĠĠĠĠĠ Ġ] ĊĠĠ Ġ* ĠĠĠĠ Ġ} ĊĠĠ Ġ* Ġ``` ĊĠĠ Ġ* Ġ] Ġ} ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ@ return ĠO uter Ġmap Ġcontains Ġone Ġentry Ġper ĠNode Port Ġtype Ġservice Ġkey ed Ġon Ġthe Ġservice Ġname . ĠThe ĊĠĠ Ġ* Ġ``` ĊĠĠ Ġ* ĠĠĠĠ Ġkey Ġof Ġthe Ġinner Ġmap Ġis Ġthe Ġport Ġname Ġand Ġthe Ġvalue Ġis Ġthe Ġport Ġnumber . ĊĠĠ Ġ* Ġ``` ĊĠĠ Ġ*/ ĊĠ Ġfun ĠgetNode Ports ( job Names : ĠList < String >): ĠMap < String , ĠMap < String , ĠInt >> Ġ= ĊĠĠĠ Ġhandle Json ( ĊĠĠĠĠĠ Ġ" kubectl Ġget Ġservices Ġ${ ĊĠĠĠĠĠ Ġjob Names . join ToString (" Ġ") ĊĠĠĠĠĠ Ġ} Ġ- o Ġjson Ġ-- context Ġkind -$ cluster Name " ĊĠĠĠ Ġ) Ġ{ Ġjson Ġ-> ĊĠĠĠĠĠ Ġjson ĊĠĠĠĠĠĠĠ Ġ. getAs JsonArray (" items ") ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . as JsonObject Ġ} ĊĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġel Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġel . getAs Json Primitive (" kind "). asString Ġ== Ġ" Service " Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠ Ġel . getAs JsonObject (" spec "). getAs Json Primitive (" type "). asString Ġ== Ġ" Node Port " ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ. associate Ġ{ Ġel Ġ-> ĊĠĠĠĠĠĠĠĠĠ ĠPair ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġel . getAs JsonObject (" metadata "). getAs Json Primitive (" name "). asString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġel . getAs JsonObject (" spec "). getAs JsonArray (" ports "). associate Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPair ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . as JsonObject . getAs Json Primitive (" name "). asString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . as JsonObject . getAs Json Primitive (" node Port "). as Int ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġjobs Succeeded ( job Names : ĠList < String >): ĠBoolean Ġ= ĊĠĠĠ Ġhandle Json ( ĊĠĠĠĠĠ Ġ" kubectl Ġget Ġjobs Ġ${ ĊĠĠĠĠĠ Ġjob Names . join ToString (" Ġ") ĊĠĠĠĠĠ Ġ} Ġ- o Ġjson Ġ-- context Ġkind -$ cluster Name " ĊĠĠĠ Ġ) Ġ{ Ġjson Ġ-> ĊĠĠĠĠĠ Ġjson . getAs JsonArray (" items "). all Ġ{ Ġel Ġ-> ĊĠĠĠĠĠĠĠ Ġel . as JsonObject . getAs JsonObject (" status "). has (" succeeded ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġget Pod Statuses (): ĠMap < String , ĠString > Ġ= ĊĠĠĠ Ġexec ( ĊĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠ Ġ" kubectl ", ĊĠĠĠĠĠĠĠ Ġ" get ", ĊĠĠĠĠĠĠĠ Ġ" pods ", ĊĠĠĠĠĠĠĠ Ġ"-- context ", ĊĠĠĠĠĠĠĠ Ġ" kind -$ cluster Name ", ĊĠĠĠĠĠĠĠ Ġ"- o = json path ={ range Ġ. items [* ] }{ . metadata . name }{ \" =\" }{ . status . phase }{ \" \\ n \" }{ end }" ĊĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ) Ġ{ Ġreader Ġ-> ĊĠĠĠĠĠ Ġreader . read Lines (). associate Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstr Ġ= Ġit . split (" =") ĊĠĠĠĠĠĠĠ Ġrequire ( str . size Ġ== Ġ 2 ) ĊĠĠĠĠĠĠĠ ĠPair ( str [ 0 ], Ġstr [ 1 ]) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġ< T > Ġhandle Json ( command : ĠString , Ġparse : Ġ( JsonObject ) Ġ-> ĠT ): ĠT Ġ= ĊĠ Ġexec ( command . split ("\\ s ". to Regex ())) Ġ{ Ġreader Ġ-> ĊĠĠĠ Ġval Ġelement Ġ= Ġparse Reader ( Json Reader ( reader )) ĊĠĠĠ Ġparse ( element . as JsonObject ) ĊĠ Ġ} Ċ Ċ /** ĠRuns Ġa Ġsubprocess Ġand Ġruns Ġits Ġstdout Ġthrough Ġthe Ġparser . Ġ*/ Ċ private Ġfun Ġ< T > Ġexec ( command : ĠList < String >, Ġparse : Ġ( Reader ) Ġ-> ĠT ): ĠT Ġ{ ĊĠ Ġval Ġprocess Ġ= ĠProcess Builder ( command ). start () ĊĠ Ġvar ĠerrorMessage : ĠString ? Ġ= Ġnull ĊĠ Ġvar Ġresult : ĠT ? Ġ= Ġnull ĊĊĠ Ġrun Blocking Ġ{ ĊĠĠĠ Ġjoin All ( ĊĠĠĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠ ĠerrorMessage Ġ= ĊĠĠĠĠĠĠĠĠĠ Ġprocess ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. error Stream ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. buffered Reader () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. lines () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. collect ( Collectors . join ing ( System . line Separator ())) ĊĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠ Ġlaunch Ġ{ Ġresult Ġ= Ġparse ( process . inputStream . buffered Reader ()) Ġ} ĊĠĠĠ Ġ) ĊĠ Ġ} ĊĊĠ Ġprocess . waitFor () ĊĊĠ Ġ// ĠNote Ġthat Ġthis Ġcheck Ġis Ġsomewhat Ġun reli able Ġsince Ġsome Ġapplications , Ġkubectl Ġin Ġparticular , ĊĠ Ġ// Ġreturn Ġexit Ġvalue Ġzero Ġand Ġwrite Ġerror Ġmessages Ġto Ġstdout Ġwhen Ġthey Ġreceive Ġinvalid Ġarguments . ĊĠ Ġif Ġ( process . exit Value () Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠ Ġthrow ĠException ( errorMessage ) ĊĠ Ġ} ĊĊĠ Ġreturn Ġresult !! Ċ } Ċ