@codiac.io/codiac-cli 1.2.156 → 1.2.164

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (600) hide show
  1. package/README.md +4481 -3784
  2. package/bin/dev +16 -16
  3. package/bin/dev.cmd +2 -2
  4. package/bin/run +3 -3
  5. package/bin/run.cmd +3 -3
  6. package/codiac.json +9 -9
  7. package/lib/apis/codiac-api/common/api-client-base.d.ts +165 -165
  8. package/lib/apis/codiac-api/common/api-client-base.js +547 -547
  9. package/lib/apis/codiac-api/common/api-user-creds.d.ts +7 -7
  10. package/lib/apis/codiac-api/common/api-user-creds.js +18 -18
  11. package/lib/apis/codiac-api/common/config-loader.d.ts +6 -6
  12. package/lib/apis/codiac-api/common/config-loader.js +18 -18
  13. package/lib/apis/codiac-api/common/endpoint-spec.d.ts +17 -17
  14. package/lib/apis/codiac-api/common/endpoint-spec.js +27 -27
  15. package/lib/apis/codiac-api/common/security/api-auth-methods-legacy.d.ts +87 -87
  16. package/lib/apis/codiac-api/common/security/api-auth-methods-legacy.js +367 -367
  17. package/lib/apis/codiac-api/common/security/auth-constants.d.ts +15 -15
  18. package/lib/apis/codiac-api/common/security/auth-constants.js +21 -21
  19. package/lib/apis/codiac-api/common/security/i-auth-client.d.ts +44 -44
  20. package/lib/apis/codiac-api/common/security/i-auth-client.js +2 -2
  21. package/lib/apis/codiac-api/common/security/token-holder.d.ts +13 -13
  22. package/lib/apis/codiac-api/common/security/token-holder.js +17 -17
  23. package/lib/apis/codiac-api/common/utils.d.ts +23 -23
  24. package/lib/apis/codiac-api/common/utils.js +82 -82
  25. package/lib/apis/codiac-api/contracts/index.d.ts +1 -1
  26. package/lib/apis/codiac-api/contracts/index.js +4 -4
  27. package/lib/apis/codiac-api/gen/client-config.d.ts +10 -10
  28. package/lib/apis/codiac-api/gen/client-config.js +28 -28
  29. package/lib/apis/codiac-api/gen/client.d.ts +1663 -1663
  30. package/lib/apis/codiac-api/gen/client.js +15629 -15629
  31. package/lib/apis/codiac-api/gen/contracts.d.ts +2722 -2722
  32. package/lib/apis/codiac-api/gen/contracts.js +402 -402
  33. package/lib/apis/codiac-api/index.d.ts +3 -3
  34. package/lib/apis/codiac-api/index.js +8 -8
  35. package/lib/apis/codiac-relay/common/api-client-base.d.ts +165 -165
  36. package/lib/apis/codiac-relay/common/api-client-base.js +547 -547
  37. package/lib/apis/codiac-relay/common/api-user-creds.d.ts +7 -7
  38. package/lib/apis/codiac-relay/common/api-user-creds.js +18 -18
  39. package/lib/apis/codiac-relay/common/config-loader.d.ts +6 -6
  40. package/lib/apis/codiac-relay/common/config-loader.js +18 -18
  41. package/lib/apis/codiac-relay/common/endpoint-spec.d.ts +17 -17
  42. package/lib/apis/codiac-relay/common/endpoint-spec.js +27 -27
  43. package/lib/apis/codiac-relay/common/security/api-auth-methods-legacy.d.ts +87 -87
  44. package/lib/apis/codiac-relay/common/security/api-auth-methods-legacy.js +367 -367
  45. package/lib/apis/codiac-relay/common/security/auth-constants.d.ts +15 -15
  46. package/lib/apis/codiac-relay/common/security/auth-constants.js +21 -21
  47. package/lib/apis/codiac-relay/common/security/i-auth-client.d.ts +44 -44
  48. package/lib/apis/codiac-relay/common/security/i-auth-client.js +2 -2
  49. package/lib/apis/codiac-relay/common/security/token-holder.d.ts +13 -13
  50. package/lib/apis/codiac-relay/common/security/token-holder.js +17 -17
  51. package/lib/apis/codiac-relay/common/utils.d.ts +23 -23
  52. package/lib/apis/codiac-relay/common/utils.js +82 -82
  53. package/lib/apis/codiac-relay/contracts/index.d.ts +1 -1
  54. package/lib/apis/codiac-relay/contracts/index.js +4 -4
  55. package/lib/apis/codiac-relay/gen/client-config.d.ts +10 -10
  56. package/lib/apis/codiac-relay/gen/client-config.js +28 -28
  57. package/lib/apis/codiac-relay/gen/client.d.ts +244 -242
  58. package/lib/apis/codiac-relay/gen/client.js +1862 -1848
  59. package/lib/apis/codiac-relay/gen/client.js.map +1 -1
  60. package/lib/apis/codiac-relay/gen/contracts.d.ts +3108 -3097
  61. package/lib/apis/codiac-relay/gen/contracts.js +434 -431
  62. package/lib/apis/codiac-relay/gen/contracts.js.map +1 -1
  63. package/lib/apis/codiac-relay/index.d.ts +3 -3
  64. package/lib/apis/codiac-relay/index.js +8 -8
  65. package/lib/cli-common/ImagesList.js +66 -66
  66. package/lib/cli-common/ImagesList.js.map +1 -1
  67. package/lib/cli-common/argument-manager.d.ts +28 -28
  68. package/lib/cli-common/argument-manager.js +194 -194
  69. package/lib/cli-common/built-in-cli-user-input.d.ts +18 -18
  70. package/lib/cli-common/built-in-cli-user-input.js +309 -309
  71. package/lib/cli-common/built-in-cli-user-input.js.map +1 -1
  72. package/lib/cli-common/cli-interfaces.js +6 -6
  73. package/lib/cli-common/command-base.d.ts +72 -74
  74. package/lib/cli-common/command-base.js +181 -179
  75. package/lib/cli-common/command-base.js.map +1 -1
  76. package/lib/cli-common/entities/index.d.ts +1 -1
  77. package/lib/cli-common/entities/index.js +4 -4
  78. package/lib/cli-common/entities/prompt-choice.d.ts +7 -7
  79. package/lib/cli-common/entities/prompt-choice.js +2 -2
  80. package/lib/cli-common/file-selector.d.ts +48 -48
  81. package/lib/cli-common/file-selector.js +186 -186
  82. package/lib/cli-common/i-user-input-provider.js +18 -18
  83. package/lib/cli-common/index.d.ts +4 -4
  84. package/lib/cli-common/index.js +10 -10
  85. package/lib/cli-common/mock-ui.d.ts +27 -27
  86. package/lib/cli-common/mock-ui.js +82 -82
  87. package/lib/cli-common/prompt-select-fuzzy.d.ts +19 -19
  88. package/lib/cli-common/prompt-select-fuzzy.js +118 -118
  89. package/lib/cli-common/tenant-contextualizer.js +435 -435
  90. package/lib/cli-common/test/tenant-contextualizer.spec.js +142 -142
  91. package/lib/cli-entities/output-format-enum.d.ts +7 -7
  92. package/lib/cli-entities/output-format-enum.js +11 -11
  93. package/lib/cli-entities/prompt-choice.js +5 -5
  94. package/lib/codiac-constants.d.ts +35 -35
  95. package/lib/codiac-constants.js +40 -40
  96. package/lib/codiac-entities/asset-binding.d.ts +12 -12
  97. package/lib/codiac-entities/asset-binding.js +17 -17
  98. package/lib/codiac-entities/azure-container-registry.d.ts +4 -4
  99. package/lib/codiac-entities/azure-container-registry.js +2 -2
  100. package/lib/codiac-entities/azure-service-principal.d.ts +23 -23
  101. package/lib/codiac-entities/azure-service-principal.js +23 -23
  102. package/lib/codiac-entities/cloud-account-ref.d.ts +28 -28
  103. package/lib/codiac-entities/cloud-account-ref.js +36 -36
  104. package/lib/codiac-entities/deployment-temp.js +132 -132
  105. package/lib/codiac-entities/i-cloud-account-ref.d.ts +5 -5
  106. package/lib/codiac-entities/i-cloud-account-ref.js +2 -2
  107. package/lib/command-base-enterprise.d.ts +121 -121
  108. package/lib/command-base-enterprise.js +523 -523
  109. package/lib/command-base-tenantless.d.ts +44 -44
  110. package/lib/command-base-tenantless.js +172 -172
  111. package/lib/commands/asset/create.d.ts +42 -42
  112. package/lib/commands/asset/create.js +466 -466
  113. package/lib/commands/asset/destroy.d.ts +20 -20
  114. package/lib/commands/asset/destroy.js +128 -128
  115. package/lib/commands/asset/helm.d.ts +23 -24
  116. package/lib/commands/asset/helm.js +152 -150
  117. package/lib/commands/asset/helm.js.map +1 -1
  118. package/lib/commands/asset/list.d.ts +28 -29
  119. package/lib/commands/asset/list.js +171 -170
  120. package/lib/commands/asset/list.js.map +1 -1
  121. package/lib/commands/asset/probe/create.d.ts +38 -41
  122. package/lib/commands/asset/probe/create.js +186 -181
  123. package/lib/commands/asset/probe/create.js.map +1 -1
  124. package/lib/commands/asset/recycle.d.ts +23 -23
  125. package/lib/commands/asset/recycle.js +174 -174
  126. package/lib/commands/asset/view.d.ts +188 -189
  127. package/lib/commands/asset/view.js +1364 -1360
  128. package/lib/commands/asset/view.js.map +1 -1
  129. package/lib/commands/asset/volume/create.d.ts +23 -25
  130. package/lib/commands/asset/volume/create.js +175 -173
  131. package/lib/commands/asset/volume/create.js.map +1 -1
  132. package/lib/commands/asset/volume/delete.d.ts +19 -19
  133. package/lib/commands/asset/volume/delete.js +111 -111
  134. package/lib/commands/asset/volume/list.d.ts +19 -20
  135. package/lib/commands/asset/volume/list.js +69 -68
  136. package/lib/commands/asset/volume/list.js.map +1 -1
  137. package/lib/commands/branch/current.d.ts +10 -10
  138. package/lib/commands/branch/current.js +33 -33
  139. package/lib/commands/branch/list.d.ts +15 -15
  140. package/lib/commands/branch/list.js +55 -55
  141. package/lib/commands/branch/list.js.map +1 -1
  142. package/lib/commands/branch.d.ts +12 -13
  143. package/lib/commands/branch.js +41 -39
  144. package/lib/commands/branch.js.map +1 -1
  145. package/lib/commands/build.d.ts +37 -37
  146. package/lib/commands/build.js +118 -115
  147. package/lib/commands/build.js.map +1 -1
  148. package/lib/commands/cabinet/create.d.ts +21 -23
  149. package/lib/commands/cabinet/create.js +107 -105
  150. package/lib/commands/cabinet/create.js.map +1 -1
  151. package/lib/commands/cabinet/list.d.ts +23 -24
  152. package/lib/commands/cabinet/list.js +133 -131
  153. package/lib/commands/cabinet/list.js.map +1 -1
  154. package/lib/commands/cabinet/obliterate.d.ts +20 -22
  155. package/lib/commands/cabinet/obliterate.js +82 -80
  156. package/lib/commands/cabinet/obliterate.js.map +1 -1
  157. package/lib/commands/cli.d.ts +10 -10
  158. package/lib/commands/cli.js +99 -99
  159. package/lib/commands/cli.js.map +1 -1
  160. package/lib/commands/commit.d.ts +11 -13
  161. package/lib/commands/commit.js +39 -37
  162. package/lib/commands/commit.js.map +1 -1
  163. package/lib/commands/config/add.d.ts +78 -79
  164. package/lib/commands/config/add.js +559 -557
  165. package/lib/commands/config/add.js.map +1 -1
  166. package/lib/commands/config/delete.d.ts +18 -19
  167. package/lib/commands/config/delete.js +118 -113
  168. package/lib/commands/config/delete.js.map +1 -1
  169. package/lib/commands/config/deploy.d.ts +22 -22
  170. package/lib/commands/config/deploy.js +124 -124
  171. package/lib/commands/config/import.d.ts +27 -28
  172. package/lib/commands/config/import.js +195 -193
  173. package/lib/commands/config/import.js.map +1 -1
  174. package/lib/commands/config/view.d.ts +25 -28
  175. package/lib/commands/config/view.js +120 -117
  176. package/lib/commands/config/view.js.map +1 -1
  177. package/lib/commands/csp/login.d.ts +18 -22
  178. package/lib/commands/csp/login.js +108 -106
  179. package/lib/commands/csp/login.js.map +1 -1
  180. package/lib/commands/csp/logout.d.ts +15 -19
  181. package/lib/commands/csp/logout.js +73 -71
  182. package/lib/commands/csp/logout.js.map +1 -1
  183. package/lib/commands/dep/create.d.ts +13 -14
  184. package/lib/commands/dep/create.js +40 -35
  185. package/lib/commands/dep/create.js.map +1 -1
  186. package/lib/commands/dep/install.d.ts +9 -9
  187. package/lib/commands/dep/install.js +29 -29
  188. package/lib/commands/dep/list.d.ts +55 -55
  189. package/lib/commands/dep/list.js +97 -97
  190. package/lib/commands/dep/remove.d.ts +12 -13
  191. package/lib/commands/dep/remove.js +61 -59
  192. package/lib/commands/dep/remove.js.map +1 -1
  193. package/lib/commands/dep/source.d.ts +13 -14
  194. package/lib/commands/dep/source.js +82 -80
  195. package/lib/commands/dep/source.js.map +1 -1
  196. package/lib/commands/dep/syncup.d.ts +11 -12
  197. package/lib/commands/dep/syncup.js +53 -51
  198. package/lib/commands/dep/syncup.js.map +1 -1
  199. package/lib/commands/dep/unsource.d.ts +14 -15
  200. package/lib/commands/dep/unsource.js +67 -60
  201. package/lib/commands/dep/unsource.js.map +1 -1
  202. package/lib/commands/dep/upgrade.d.ts +44 -45
  203. package/lib/commands/dep/upgrade.js +243 -241
  204. package/lib/commands/dep/upgrade.js.map +1 -1
  205. package/lib/commands/dep.d.ts +12 -13
  206. package/lib/commands/dep.js +50 -48
  207. package/lib/commands/dep.js.map +1 -1
  208. package/lib/commands/deploy.d.ts +38 -31
  209. package/lib/commands/deploy.js +382 -357
  210. package/lib/commands/deploy.js.map +1 -1
  211. package/lib/commands/enterprise/create.d.ts +20 -22
  212. package/lib/commands/enterprise/create.js +97 -95
  213. package/lib/commands/enterprise/create.js.map +1 -1
  214. package/lib/commands/enterprise/list.d.ts +14 -15
  215. package/lib/commands/enterprise/list.js +83 -82
  216. package/lib/commands/enterprise/list.js.map +1 -1
  217. package/lib/commands/env/add.d.ts +22 -23
  218. package/lib/commands/env/add.js +199 -196
  219. package/lib/commands/env/add.js.map +1 -1
  220. package/lib/commands/environment/create.d.ts +19 -21
  221. package/lib/commands/environment/create.js +88 -86
  222. package/lib/commands/environment/create.js.map +1 -1
  223. package/lib/commands/environment/list.d.ts +25 -26
  224. package/lib/commands/environment/list.js +157 -155
  225. package/lib/commands/environment/list.js.map +1 -1
  226. package/lib/commands/filestore/capture.d.ts +31 -31
  227. package/lib/commands/filestore/capture.js +341 -341
  228. package/lib/commands/host/map.d.ts +33 -35
  229. package/lib/commands/host/map.js +346 -344
  230. package/lib/commands/host/map.js.map +1 -1
  231. package/lib/commands/identity/delete.d.ts +15 -16
  232. package/lib/commands/identity/delete.js +82 -78
  233. package/lib/commands/identity/delete.js.map +1 -1
  234. package/lib/commands/identity/list.d.ts +11 -11
  235. package/lib/commands/identity/list.js +42 -42
  236. package/lib/commands/identity/list.js.map +1 -1
  237. package/lib/commands/identity.d.ts +22 -24
  238. package/lib/commands/identity.js +76 -74
  239. package/lib/commands/identity.js.map +1 -1
  240. package/lib/commands/imageRegistry/capture.d.ts +27 -28
  241. package/lib/commands/imageRegistry/capture.js +159 -159
  242. package/lib/commands/imageRegistry/capture.js.map +1 -1
  243. package/lib/commands/imageRegistry/forget.d.ts +23 -23
  244. package/lib/commands/imageRegistry/forget.js +160 -160
  245. package/lib/commands/imageRegistry/pullSecret/set.d.ts +27 -28
  246. package/lib/commands/imageRegistry/pullSecret/set.js +299 -299
  247. package/lib/commands/imageRegistry/pullSecret/set.js.map +1 -1
  248. package/lib/commands/imageRegistry/pullSecret/unset.d.ts +24 -24
  249. package/lib/commands/imageRegistry/pullSecret/unset.js +242 -242
  250. package/lib/commands/imageRegistry/pullSecret/unset.js.map +1 -1
  251. package/lib/commands/images/add.d.ts +25 -27
  252. package/lib/commands/images/add.js +75 -70
  253. package/lib/commands/images/add.js.map +1 -1
  254. package/lib/commands/images/list.d.ts +14 -16
  255. package/lib/commands/images/list.js +71 -71
  256. package/lib/commands/images/list.js.map +1 -1
  257. package/lib/commands/images/patch.d.ts +14 -16
  258. package/lib/commands/images/patch.js +92 -90
  259. package/lib/commands/images/patch.js.map +1 -1
  260. package/lib/commands/images/remove.d.ts +12 -14
  261. package/lib/commands/images/remove.js +37 -35
  262. package/lib/commands/images/remove.js.map +1 -1
  263. package/lib/commands/images/version.d.ts +16 -16
  264. package/lib/commands/images/version.js +64 -62
  265. package/lib/commands/images/version.js.map +1 -1
  266. package/lib/commands/init.d.ts +17 -19
  267. package/lib/commands/init.js +130 -130
  268. package/lib/commands/init.js.map +1 -1
  269. package/lib/commands/kit/create.d.ts +25 -26
  270. package/lib/commands/kit/create.js +141 -139
  271. package/lib/commands/kit/create.js.map +1 -1
  272. package/lib/commands/login.d.ts +22 -22
  273. package/lib/commands/login.js +92 -92
  274. package/lib/commands/logout.d.ts +8 -8
  275. package/lib/commands/logout.js +36 -36
  276. package/lib/commands/merge.d.ts +12 -14
  277. package/lib/commands/merge.js +42 -40
  278. package/lib/commands/merge.js.map +1 -1
  279. package/lib/commands/noc/cluster/create.d.ts +28 -29
  280. package/lib/commands/noc/cluster/create.js +132 -130
  281. package/lib/commands/noc/cluster/create.js.map +1 -1
  282. package/lib/commands/noc/cluster/deinit.d.ts +17 -18
  283. package/lib/commands/noc/cluster/deinit.js +116 -113
  284. package/lib/commands/noc/cluster/deinit.js.map +1 -1
  285. package/lib/commands/noc/cluster/destroy.d.ts +20 -21
  286. package/lib/commands/noc/cluster/destroy.js +137 -134
  287. package/lib/commands/noc/cluster/destroy.js.map +1 -1
  288. package/lib/commands/noc/cluster/grant.d.ts +24 -0
  289. package/lib/commands/noc/cluster/grant.js +160 -0
  290. package/lib/commands/noc/cluster/grant.js.map +1 -0
  291. package/lib/commands/noc/cluster/init.d.ts +17 -18
  292. package/lib/commands/noc/cluster/init.js +116 -113
  293. package/lib/commands/noc/cluster/init.js.map +1 -1
  294. package/lib/commands/noc/cluster/list.d.ts +21 -22
  295. package/lib/commands/noc/cluster/list.js +83 -82
  296. package/lib/commands/noc/cluster/list.js.map +1 -1
  297. package/lib/commands/noc/cluster/recreate.d.ts +28 -31
  298. package/lib/commands/noc/cluster/recreate.js +185 -182
  299. package/lib/commands/noc/cluster/recreate.js.map +1 -1
  300. package/lib/commands/pkg/add.d.ts +15 -17
  301. package/lib/commands/pkg/add.js +42 -40
  302. package/lib/commands/pkg/add.js.map +1 -1
  303. package/lib/commands/pkg/list.d.ts +9 -11
  304. package/lib/commands/pkg/list.js +32 -32
  305. package/lib/commands/pkg/list.js.map +1 -1
  306. package/lib/commands/pkg/patch.d.ts +13 -15
  307. package/lib/commands/pkg/patch.js +78 -76
  308. package/lib/commands/pkg/patch.js.map +1 -1
  309. package/lib/commands/pkg/remove.d.ts +12 -14
  310. package/lib/commands/pkg/remove.js +69 -67
  311. package/lib/commands/pkg/remove.js.map +1 -1
  312. package/lib/commands/portal.d.ts +11 -11
  313. package/lib/commands/portal.js +81 -81
  314. package/lib/commands/publish.d.ts +21 -23
  315. package/lib/commands/publish.js +51 -51
  316. package/lib/commands/publish.js.map +1 -1
  317. package/lib/commands/pull.d.ts +13 -15
  318. package/lib/commands/pull.js +29 -29
  319. package/lib/commands/pull.js.map +1 -1
  320. package/lib/commands/push.d.ts +13 -15
  321. package/lib/commands/push.js +29 -29
  322. package/lib/commands/push.js.map +1 -1
  323. package/lib/commands/run.d.ts +35 -35
  324. package/lib/commands/run.js +193 -193
  325. package/lib/commands/secretStore/capture.d.ts +27 -28
  326. package/lib/commands/secretStore/capture.js +174 -173
  327. package/lib/commands/secretStore/capture.js.map +1 -1
  328. package/lib/commands/secretStore/forget.d.ts +20 -20
  329. package/lib/commands/secretStore/forget.js +146 -146
  330. package/lib/commands/stage.d.ts +13 -15
  331. package/lib/commands/stage.js +64 -62
  332. package/lib/commands/stage.js.map +1 -1
  333. package/lib/commands/stash.d.ts +13 -13
  334. package/lib/commands/stash.js +30 -28
  335. package/lib/commands/stash.js.map +1 -1
  336. package/lib/commands/status.d.ts +12 -12
  337. package/lib/commands/status.js +48 -48
  338. package/lib/commands/stop.d.ts +10 -10
  339. package/lib/commands/stop.js +51 -51
  340. package/lib/commands/switch.d.ts +11 -12
  341. package/lib/commands/switch.js +41 -36
  342. package/lib/commands/switch.js.map +1 -1
  343. package/lib/commands/sync.d.ts +14 -16
  344. package/lib/commands/sync.js +20 -20
  345. package/lib/commands/sync.js.map +1 -1
  346. package/lib/commands/tenant/create.d.ts +27 -29
  347. package/lib/commands/tenant/create.js +119 -117
  348. package/lib/commands/tenant/create.js.map +1 -1
  349. package/lib/commands/tenant/switch.d.ts +24 -26
  350. package/lib/commands/tenant/switch.js +108 -106
  351. package/lib/commands/tenant/switch.js.map +1 -1
  352. package/lib/commands/unstage.d.ts +12 -14
  353. package/lib/commands/unstage.js +57 -55
  354. package/lib/commands/unstage.js.map +1 -1
  355. package/lib/commands/whereami.d.ts +15 -17
  356. package/lib/commands/whereami.js +122 -122
  357. package/lib/commands/whereami.js.map +1 -1
  358. package/lib/commands/whoami.d.ts +8 -11
  359. package/lib/commands/whoami.js +39 -40
  360. package/lib/commands/whoami.js.map +1 -1
  361. package/lib/errors/NoMembershipError.d.ts +8 -8
  362. package/lib/errors/NoMembershipError.js +14 -14
  363. package/lib/index.d.ts +1 -1
  364. package/lib/index.js +16 -16
  365. package/lib/log-update-wrapper.d.ts +24 -24
  366. package/lib/log-update-wrapper.js +28 -28
  367. package/lib/log4js-logger.d.ts +26 -26
  368. package/lib/log4js-logger.js +137 -137
  369. package/lib/ops/INTERFACES_CLI.d.ts +3 -3
  370. package/lib/ops/INTERFACES_CLI.js +7 -7
  371. package/lib/ops/LocalOps.d.ts +444 -444
  372. package/lib/ops/LocalOps.js +3183 -3183
  373. package/lib/ops/azure-container-registry-client/azure-container-registry-client.js +147 -147
  374. package/lib/ops/cli-path-walker.js +54 -54
  375. package/lib/ops/codiac-entities/dependency.d.ts +5 -5
  376. package/lib/ops/codiac-entities/dependency.js +10 -10
  377. package/lib/ops/codiac-entities/index.d.ts +1 -1
  378. package/lib/ops/codiac-entities/index.js +4 -4
  379. package/lib/ops/composite-image-registry-client.js +73 -73
  380. package/lib/ops/data/cli-context-repo.d.ts +61 -61
  381. package/lib/ops/data/cli-context-repo.js +269 -269
  382. package/lib/ops/data/index.d.ts +2 -2
  383. package/lib/ops/data/index.js +5 -5
  384. package/lib/ops/data/npm-config-repo.d.ts +13 -13
  385. package/lib/ops/data/npm-config-repo.js +64 -64
  386. package/lib/ops/docker-config.js +130 -130
  387. package/lib/ops/docker-constants.js +21 -21
  388. package/lib/ops/docker-credentials-store.js +237 -237
  389. package/lib/ops/docker-registry-api-client/docker-registry-api-client.js +288 -288
  390. package/lib/ops/docker-registry-api-client/entities/blob-sum.d.ts +7 -7
  391. package/lib/ops/docker-registry-api-client/entities/blob-sum.js +12 -12
  392. package/lib/ops/docker-registry-api-client/entities/docker-access-actions-enum.d.ts +5 -5
  393. package/lib/ops/docker-registry-api-client/entities/docker-access-actions-enum.js +9 -9
  394. package/lib/ops/docker-registry-api-client/entities/docker-auth-token-criteria.d.ts +30 -30
  395. package/lib/ops/docker-registry-api-client/entities/docker-auth-token-criteria.js +35 -35
  396. package/lib/ops/docker-registry-api-client/entities/i-docker-error-response.d.ts +55 -55
  397. package/lib/ops/docker-registry-api-client/entities/i-docker-error-response.js +51 -51
  398. package/lib/ops/docker-registry-api-client/entities/i-docker-list-response.d.ts +7 -7
  399. package/lib/ops/docker-registry-api-client/entities/i-docker-list-response.js +2 -2
  400. package/lib/ops/docker-registry-api-client/entities/image-repository.d.ts +31 -31
  401. package/lib/ops/docker-registry-api-client/entities/image-repository.js +29 -29
  402. package/lib/ops/docker-registry-api-client/entities/image-tag-criteria.d.ts +8 -8
  403. package/lib/ops/docker-registry-api-client/entities/image-tag-criteria.js +13 -13
  404. package/lib/ops/docker-registry-api-client/entities/image-tag-list.d.ts +7 -7
  405. package/lib/ops/docker-registry-api-client/entities/image-tag-list.js +12 -12
  406. package/lib/ops/docker-registry-api-client/entities/manifest-criteria.d.ts +9 -9
  407. package/lib/ops/docker-registry-api-client/entities/manifest-criteria.js +14 -14
  408. package/lib/ops/docker-registry-api-client/entities/manifest.d.ts +15 -15
  409. package/lib/ops/docker-registry-api-client/entities/manifest.js +20 -20
  410. package/lib/ops/docker-registry-api-client/entities/repository-criteria.d.ts +16 -16
  411. package/lib/ops/docker-registry-api-client/entities/repository-criteria.js +23 -23
  412. package/lib/ops/docker-registry-api-client/entities/token-response.d.ts +15 -15
  413. package/lib/ops/docker-registry-api-client/entities/token-response.js +14 -14
  414. package/lib/ops/docker-registry-api-client/entities/token.d.ts +17 -17
  415. package/lib/ops/docker-registry-api-client/entities/token.js +21 -21
  416. package/lib/ops/docker-registry-api-client/entities/version-check-criteria.d.ts +4 -4
  417. package/lib/ops/docker-registry-api-client/entities/version-check-criteria.js +9 -9
  418. package/lib/ops/dx-constants.d.ts +26 -26
  419. package/lib/ops/dx-constants.js +42 -42
  420. package/lib/ops/entities/ImageBuildContext.d.ts +12 -12
  421. package/lib/ops/entities/ImageBuildContext.js +18 -18
  422. package/lib/ops/entities/PipelineContext.d.ts +21 -21
  423. package/lib/ops/entities/PipelineContext.js +22 -22
  424. package/lib/ops/entities/TenantContext.d.ts +10 -10
  425. package/lib/ops/entities/TenantContext.js +15 -15
  426. package/lib/ops/entities/ThaulConfig.js +29 -29
  427. package/lib/ops/entities/azure-service-principal.d.ts +23 -23
  428. package/lib/ops/entities/azure-service-principal.js +23 -23
  429. package/lib/ops/entities/better-logger.js +1 -1
  430. package/lib/ops/entities/branch.d.ts +13 -13
  431. package/lib/ops/entities/branch.js +15 -15
  432. package/lib/ops/entities/cli-config.d.ts +48 -48
  433. package/lib/ops/entities/cli-config.js +60 -60
  434. package/lib/ops/entities/docker-image.d.ts +60 -60
  435. package/lib/ops/entities/docker-image.js +2 -2
  436. package/lib/ops/entities/helm-spec.d.ts +15 -15
  437. package/lib/ops/entities/helm-spec.js +22 -22
  438. package/lib/ops/entities/index.d.ts +4 -4
  439. package/lib/ops/entities/index.js +11 -11
  440. package/lib/ops/entities/operation-meta.d.ts +8 -8
  441. package/lib/ops/entities/operation-meta.js +18 -18
  442. package/lib/ops/entities/scaffolding.d.ts +19 -19
  443. package/lib/ops/entities/scaffolding.js +20 -20
  444. package/lib/ops/extensions/azart-identity-adapter.d.ts +19 -19
  445. package/lib/ops/extensions/azart-identity-adapter.js +96 -96
  446. package/lib/ops/extensions/npm-identity-adapter-base.d.ts +13 -13
  447. package/lib/ops/extensions/npm-identity-adapter-base.js +2 -2
  448. package/lib/ops/extensions/npmjs-identity-adapter.d.ts +13 -13
  449. package/lib/ops/extensions/npmjs-identity-adapter.js +63 -63
  450. package/lib/ops/git-ops.d.ts +8 -8
  451. package/lib/ops/git-ops.js +13 -13
  452. package/lib/ops/i-client-for-image-registry.js +16 -16
  453. package/lib/ops/i-identity-handler.d.ts +33 -33
  454. package/lib/ops/i-identity-handler.js +164 -164
  455. package/lib/ops/i-output-styler.js +16 -16
  456. package/lib/ops/index.d.ts +12 -12
  457. package/lib/ops/index.js +14 -14
  458. package/lib/ops/json-utils.js +58 -58
  459. package/lib/ops/no-style-output-styler.js +29 -29
  460. package/lib/ops/oauth2-client.ts/oauth2-client.d.ts +23 -23
  461. package/lib/ops/oauth2-client.ts/oauth2-client.js +63 -63
  462. package/lib/ops/project-initializer.d.ts +36 -36
  463. package/lib/ops/project-initializer.js +218 -218
  464. package/lib/ops/scaffolding/base-scaffolding.d.ts +7 -7
  465. package/lib/ops/scaffolding/base-scaffolding.js +20 -20
  466. package/lib/ops/scaffolding/codiac-api-scaffolding.d.ts +7 -7
  467. package/lib/ops/scaffolding/codiac-api-scaffolding.js +63 -63
  468. package/lib/ops/scaffolding/typescript-scaffolding.d.ts +15 -15
  469. package/lib/ops/scaffolding/typescript-scaffolding.js +162 -162
  470. package/lib/ops/test/mock-ui.d.ts +26 -26
  471. package/lib/ops/test/mock-ui.js +87 -87
  472. package/lib/ops/test/test-extensions.d.ts +13 -13
  473. package/lib/ops/test/test-extensions.js +70 -70
  474. package/lib/ops/test/when-a-recursive-file-search-is-run.spec.d.ts +2 -2
  475. package/lib/ops/test/when-a-recursive-file-search-is-run.spec.js +54 -54
  476. package/lib/ops/test/when-git-branchline-is-attempted.spec.d.ts +2 -2
  477. package/lib/ops/test/when-git-branchline-is-attempted.spec.js +37 -37
  478. package/lib/ops/test/when-versions-are-parsed.spec.d.ts +2 -2
  479. package/lib/ops/test/when-versions-are-parsed.spec.js +59 -59
  480. package/lib/ops/throwing-user-input-provider.js +36 -36
  481. package/lib/prettify.d.ts +7 -7
  482. package/lib/prettify.js +23 -23
  483. package/lib/read-stdin.d.ts +2 -2
  484. package/lib/read-stdin.js +28 -28
  485. package/lib/relay/contracts/contracts.d.ts +207 -196
  486. package/lib/relay/contracts/contracts.js +229 -212
  487. package/lib/relay/contracts/contracts.js.map +1 -1
  488. package/lib/relay/extended-relay-client.d.ts +27 -27
  489. package/lib/relay/extended-relay-client.js +27 -27
  490. package/lib/relay/relay-container.d.ts +41 -41
  491. package/lib/relay/relay-container.js +297 -297
  492. package/lib/relay/wsclient/relay-socket-listener.d.ts +68 -68
  493. package/lib/relay/wsclient/relay-socket-listener.js +164 -164
  494. package/lib/relay/wsclient/relay-websocket-client.d.ts +33 -33
  495. package/lib/relay/wsclient/relay-websocket-client.js +178 -178
  496. package/lib/relay/wsclient/rx-websocket-subject.d.ts +25 -25
  497. package/lib/relay/wsclient/rx-websocket-subject.js +133 -133
  498. package/lib/relay/wsclient/socket-contracts.d.ts +22 -22
  499. package/lib/relay/wsclient/socket-contracts.js +2 -2
  500. package/lib/standard-probes.d.ts +5 -5
  501. package/lib/standard-probes.js +21 -21
  502. package/lib/uilogic/build-configurator.d.ts +21 -21
  503. package/lib/uilogic/build-configurator.js +110 -110
  504. package/lib/uilogic/cloud-provider-contextualizer.d.ts +46 -46
  505. package/lib/uilogic/cloud-provider-contextualizer.js +193 -193
  506. package/lib/uilogic/cloud-resource-configurator-factory.d.ts +41 -41
  507. package/lib/uilogic/cloud-resource-configurator-factory.js +157 -158
  508. package/lib/uilogic/cloud-resource-configurator-factory.js.map +1 -1
  509. package/lib/uilogic/cloud-resource-configurators/aws-resource-configurator.d.ts +38 -33
  510. package/lib/uilogic/cloud-resource-configurators/aws-resource-configurator.js +347 -296
  511. package/lib/uilogic/cloud-resource-configurators/aws-resource-configurator.js.map +1 -1
  512. package/lib/uilogic/cloud-resource-configurators/az-acr-cli-authenticator.js +77 -77
  513. package/lib/uilogic/cloud-resource-configurators/az-interactive-login-configurator.d.ts +42 -42
  514. package/lib/uilogic/cloud-resource-configurators/az-interactive-login-configurator.js +247 -247
  515. package/lib/uilogic/cloud-resource-configurators/azure-resource-configurator.d.ts +110 -110
  516. package/lib/uilogic/cloud-resource-configurators/azure-resource-configurator.js +781 -781
  517. package/lib/uilogic/cloud-resource-configurators/azure-types.js +9 -9
  518. package/lib/uilogic/cloud-resource-configurators/docker-hub-resource-configurator.d.ts +24 -24
  519. package/lib/uilogic/cloud-resource-configurators/docker-hub-resource-configurator.js +105 -105
  520. package/lib/uilogic/cloud-resource-configurators/helm-resource-configurator.d.ts +16 -16
  521. package/lib/uilogic/cloud-resource-configurators/helm-resource-configurator.js +44 -44
  522. package/lib/uilogic/cloud-resource-configurators/unsupported-resource-configurator.d.ts +18 -18
  523. package/lib/uilogic/cloud-resource-configurators/unsupported-resource-configurator.js +61 -61
  524. package/lib/uilogic/enterprise-contextualizer.d.ts +76 -76
  525. package/lib/uilogic/enterprise-contextualizer.js +670 -670
  526. package/lib/uilogic/environment-contextualizer.d.ts +15 -15
  527. package/lib/uilogic/environment-contextualizer.js +42 -42
  528. package/lib/uilogic/i-cluster-configurator.d.ts +9 -9
  529. package/lib/uilogic/i-cluster-configurator.js +2 -2
  530. package/lib/uilogic/i-login-configurator.d.ts +6 -6
  531. package/lib/uilogic/i-login-configurator.js +2 -2
  532. package/lib/uilogic/i-registry-configurator.d.ts +6 -6
  533. package/lib/uilogic/i-registry-configurator.js +2 -2
  534. package/lib/uilogic/i-secret-store-configurator.d.ts +7 -7
  535. package/lib/uilogic/i-secret-store-configurator.js +2 -2
  536. package/lib/uilogic/image-configurator.d.ts +133 -133
  537. package/lib/uilogic/image-configurator.js +577 -577
  538. package/lib/uilogic/image-contextualizer.d.ts +24 -24
  539. package/lib/uilogic/image-contextualizer.js +89 -89
  540. package/lib/uilogic/image-registry-contextualizer.d.ts +28 -28
  541. package/lib/uilogic/image-registry-contextualizer.js +126 -126
  542. package/lib/uilogic/index.d.ts +9 -9
  543. package/lib/uilogic/index.js +13 -13
  544. package/lib/uilogic/prompt-select-fuzzy.js +138 -138
  545. package/lib/uilogic/render-methods.d.ts +12 -12
  546. package/lib/uilogic/render-methods.js +64 -64
  547. package/lib/uilogic/tenant-contextualizer.d.ts +79 -79
  548. package/lib/uilogic/tenant-contextualizer.js +573 -573
  549. package/lib/user-context-loader.d.ts +60 -60
  550. package/lib/user-context-loader.js +183 -183
  551. package/oclif.manifest.json +221 -3309
  552. package/package.json +150 -151
  553. package/scaffolding/api/.gitignore-scaffolding +68 -68
  554. package/scaffolding/api/.vscode/launch.json +16 -16
  555. package/scaffolding/api/.vscode/settings.json +7 -7
  556. package/scaffolding/api/.vscode/tasks.json +15 -15
  557. package/scaffolding/api/src/app-config.json +2 -2
  558. package/scaffolding/api/src/index.ts-scaffolding +13 -13
  559. package/scaffolding/api/src/myApiDef.ts-scaffolding +25 -25
  560. package/scaffolding/default/.gitignore-scaffolding +2 -2
  561. package/scaffolding/typescript/.gitignore-scaffolding +69 -69
  562. package/scaffolding/typescript/.vscode/launch.json +16 -16
  563. package/scaffolding/typescript/.vscode/settings.json +7 -7
  564. package/scaffolding/typescript/.vscode/tasks.json +15 -15
  565. package/lib/api-command-base.d.ts +0 -0
  566. package/lib/api-command-base.js +0 -52
  567. package/lib/api-command-base.js.map +0 -1
  568. package/lib/azure-rest-client.d.ts +0 -6
  569. package/lib/azure-rest-client.js +0 -36
  570. package/lib/azure-rest-client.js.map +0 -1
  571. package/lib/commands/view/dashboard.d.ts +0 -17
  572. package/lib/commands/view/dashboard.js +0 -88
  573. package/lib/commands/view/dashboard.js.map +0 -1
  574. package/lib/commands/view/pods.d.ts +0 -14
  575. package/lib/commands/view/pods.js +0 -88
  576. package/lib/commands/view/pods.js.map +0 -1
  577. package/lib/deployment.d.ts +0 -2
  578. package/lib/deployment.js +0 -7
  579. package/lib/deployment.js.map +0 -1
  580. package/lib/k8s-command-base.d.ts +0 -60
  581. package/lib/k8s-command-base.js +0 -204
  582. package/lib/k8s-command-base.js.map +0 -1
  583. package/lib/relay/data/aws-k8s-versions.d.ts +0 -6
  584. package/lib/relay/data/aws-k8s-versions.js +0 -16
  585. package/lib/relay/data/aws-k8s-versions.js.map +0 -1
  586. package/lib/relay/data/aws-node-types.d.ts +0 -37
  587. package/lib/relay/data/aws-node-types.js +0 -4246
  588. package/lib/relay/data/aws-node-types.js.map +0 -1
  589. package/lib/relay/data/aws-regions.d.ts +0 -6
  590. package/lib/relay/data/aws-regions.js +0 -34
  591. package/lib/relay/data/aws-regions.js.map +0 -1
  592. package/lib/uilogic/cloud-resource-configurators/aws-k8s-versions.d.ts +0 -11
  593. package/lib/uilogic/cloud-resource-configurators/aws-k8s-versions.js +0 -16
  594. package/lib/uilogic/cloud-resource-configurators/aws-k8s-versions.js.map +0 -1
  595. package/lib/uilogic/cloud-resource-configurators/aws-node-types.d.ts +0 -5
  596. package/lib/uilogic/cloud-resource-configurators/aws-node-types.js +0 -536
  597. package/lib/uilogic/cloud-resource-configurators/aws-node-types.js.map +0 -1
  598. package/lib/uilogic/cloud-resource-configurators/aws-regions.d.ts +0 -10
  599. package/lib/uilogic/cloud-resource-configurators/aws-regions.js +0 -34
  600. package/lib/uilogic/cloud-resource-configurators/aws-regions.js.map +0 -1
@@ -1,1361 +1,1365 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LogStreamer = exports.K8sContainerRef = exports.TermArgs = exports.ConfigFileArgs = exports.ExecArgs = exports.K8S_POD_PHASES = exports.InteractionModes = exports.AssetContentType = exports.PROMPT_ME_DESIGNATOR = void 0;
4
- const tslib_1 = require("tslib");
5
- //import * as path from 'path';
6
- const stream = require("stream");
7
- const core_1 = require("@oclif/core");
8
- const _ = require("lodash");
9
- const SplitCmd = require('split-cmd');
10
- const request = require("request");
11
- const semver = require("semver");
12
- const k8s = require("@kubernetes/client-node");
13
- const codiac_relay_contracts_1 = require("@codiac.io/codiac-relay-contracts");
14
- const command_base_enterprise_1 = require("../../command-base-enterprise");
15
- const render = require("../../uilogic/render-methods");
16
- const cloud_provider_contextualizer_1 = require("../../uilogic/cloud-provider-contextualizer");
17
- const client_node_1 = require("@kubernetes/client-node");
18
- const web_socket_handler_1 = require("@kubernetes/client-node/dist/web-socket-handler");
19
- const codiac_ops_common_1 = require("@codiac.io/codiac-ops-common");
20
- // let logUpdate: any;
21
- // (async function () {
22
- // logUpdate = (await import("log-update")).default;
23
- // })()
24
- // import * as logUpdate from "log-update";
25
- // import logUpdate from "log-update";
26
- // const logUpdate = (await import("log-update/index.js")).default
27
- // import { logUpdate } from "log-update";
28
- // const logUpdate = require("log-update");
29
- const log_update_wrapper_1 = require("../../log-update-wrapper");
30
- const codiac_constants_1 = require("../../codiac-constants");
31
- // const { selectFiles, COMPLETED, CANCELLED } = require('select-files-cli'); // gd js wo ts...
32
- // const { selectFiles, COMPLETED, CANCELLED } = require('../../uilogic/file-selector'); // gd js wo ts...
33
- /** The value provided as input that indicates
34
- * a user's desire to be prompted with a list from which choose the value(s),
35
- * instead of entering them manually or taking a default. */
36
- exports.PROMPT_ME_DESIGNATOR = "?";
37
- var AssetContentType;
38
- (function (AssetContentType) {
39
- AssetContentType["logs"] = "logs";
40
- AssetContentType["term"] = "term";
41
- AssetContentType["exec"] = "exec";
42
- AssetContentType["env"] = "env";
43
- AssetContentType["config"] = "config";
44
- AssetContentType["status"] = "status";
45
- // | "footprint-usage" | "infrx"
46
- // | "ingress-domains" | "ingress-nslookup" | "ingress-routes" | "ingress-logs" | "ssl-certs" | "ssl-logs" | "ssl-cert-history";
47
- })(AssetContentType = exports.AssetContentType || (exports.AssetContentType = {}));
48
- const DEFAULT_TERMINAL_STARTER = "bash";
49
- /** The quantity of lines of backlog to include in the log output. */
50
- const DEFAULT_LOG_TAIL = 10;
51
- var InteractionModes;
52
- (function (InteractionModes) {
53
- InteractionModes["echo"] = "echo";
54
- InteractionModes["toscript"] = "toscript";
55
- InteractionModes["silent"] = "silent";
56
- })(InteractionModes = exports.InteractionModes || (exports.InteractionModes = {}));
57
- /** This belongs to k8s - not us, but @kubernetes/client-node has no enum or constants for these magic strings...
58
- *
59
- * @see https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
60
- */
61
- var K8S_POD_PHASES;
62
- (function (K8S_POD_PHASES) {
63
- K8S_POD_PHASES["Pending"] = "Pending";
64
- K8S_POD_PHASES["Running"] = "Running";
65
- K8S_POD_PHASES["Succeeded"] = "Succeeded";
66
- K8S_POD_PHASES["Failed"] = "Failed";
67
- K8S_POD_PHASES["Unknown"] = "Unknown";
68
- })(K8S_POD_PHASES = exports.K8S_POD_PHASES || (exports.K8S_POD_PHASES = {}));
69
- class AssetView extends command_base_enterprise_1.CommandBaseEnterprise {
70
- constructor() {
71
- super(...arguments);
72
- this.takeDefaults = false;
73
- }
74
- get uiCloudPvd() {
75
- if (this._uiCloudPvd_backer === undefined) {
76
- this._uiCloudPvd_backer = this.ioc.get(cloud_provider_contextualizer_1.CloudProviderContextualizer);
77
- }
78
- return this._uiCloudPvd_backer;
79
- }
80
- bootstrap() {
81
- super.bootstrap();
82
- cloud_provider_contextualizer_1.CloudProviderContextualizer.bootstrap(this.ioc); // (idempotent) this is a dependency of the configurators
83
- }
84
- run() {
85
- var _a, _b, _c;
86
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
87
- try {
88
- // ==================================================
89
- // 1. Bootstrap
90
- // ==================================================
91
- this.bootstrap();
92
- // this._relayContainer?.ready$
93
- // .subscribe(async (ready: boolean) => {
94
- // ==================================================
95
- // 2. Gather cli input
96
- // ==================================================
97
- const { args, flags } = yield this.parse(AssetView);
98
- const interactionMode = (_b = (_a = (flags.echo ? InteractionModes.echo : undefined)) !== null && _a !== void 0 ? _a : (flags.toscript ? InteractionModes.toscript : undefined)) !== null && _b !== void 0 ? _b : (flags.silent ? InteractionModes.silent : undefined);
99
- this.takeDefaults = (_c = flags.takeDefaults) !== null && _c !== void 0 ? _c : false;
100
- let partialReq = {};
101
- partialReq.enterprise = flags.enterprise;
102
- partialReq.asset = flags.asset;
103
- partialReq.environment = flags.environment;
104
- partialReq.cabinet = flags.cabinet;
105
- partialReq.content = (flags.type); // TODO: Look up that crazy typescript enum parsing syntax (I think api base has it)
106
- partialReq.replica = flags.replica;
107
- if (args.cmd) {
108
- let isep = this.argv.indexOf("--");
109
- if (isep >= 0) {
110
- if (isep + 1 < this.argv.length) {
111
- args.cmd = this.argv.slice(isep + 1);
112
- }
113
- else {
114
- args.cmd = undefined;
115
- }
116
- }
117
- }
118
- let contentOptions = {
119
- follow: flags.logsFollow,
120
- tailLines: flags.logsTail,
121
- /* tty: flags.tty, */
122
- command: args.cmd,
123
- terminalStartup: flags.terminal,
124
- rootPathName: flags.configFile
125
- };
126
- // ==================================================
127
- // 3. Assemble candidate
128
- // ==================================================
129
- let candidate;
130
- let cmd;
131
- if (interactionMode == InteractionModes.silent) {
132
- candidate = yield this.buildCandidate_silently(partialReq, partialReq.content, contentOptions);
133
- }
134
- else {
135
- [candidate, cmd] = yield this.buildCandidate_interactively(partialReq, partialReq.content, contentOptions);
136
- }
137
- // ==================================================
138
- // 4. Render ultimate command string
139
- // ==================================================
140
- if (interactionMode == InteractionModes.echo || interactionMode == InteractionModes.toscript) {
141
- if (cmd && cmd.length > 0) {
142
- this._ui.userMessage(cmd.join(" "));
143
- }
144
- }
145
- // ==================================================
146
- // 5. Execute
147
- // ==================================================
148
- if (interactionMode != InteractionModes.toscript) {
149
- yield this.renderSelectedContent(candidate.context, candidate.contentType, candidate.k8sEntities, candidate.contentOptions, candidate.replicas);
150
- }
151
- // return;
152
- // });
153
- return;
154
- }
155
- catch (err) {
156
- this.handleError(err);
157
- throw err;
158
- }
159
- });
160
- }
161
- buildCandidate_silently(partialReq, content, contentOptions) {
162
- var _a, _b, _c, _d, _e, _f;
163
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
164
- this.__ui = new codiac_ops_common_1.ThrowingUserInputProvider(this.logger);
165
- if (content === undefined || _.isEmpty(partialReq.content))
166
- throw new Error(`No content type specified.`);
167
- if (partialReq.enterprise === undefined || _.isEmpty(partialReq.enterprise))
168
- throw new Error(`No enterprise specified.`);
169
- if (partialReq.asset === undefined || _.isEmpty(partialReq.asset))
170
- throw new Error(`No asset specified.`);
171
- if (partialReq.environment === undefined || _.isEmpty(partialReq.environment))
172
- throw new Error(`No environment specified.`);
173
- if (partialReq.cabinet === undefined || _.isEmpty(partialReq.cabinet))
174
- throw new Error(`No cabinet specified.`);
175
- // Replica should not be required
176
- // (though this can be confusing when there's more than one;
177
- // the user will have to know they're only getting a single replica of logs,
178
- // and they need to know they might have to call out for one.
179
- // if (partialReq.replica === undefined || _.isEmpty(partialReq.replica)) throw new Error(`No replica specified.`);
180
- let options;
181
- switch (partialReq.content) {
182
- case AssetContentType.logs:
183
- options = (contentOptions !== null && contentOptions !== void 0 ? contentOptions : {});
184
- // defaults?
185
- break;
186
- case AssetContentType.exec:
187
- if (_.isEmpty(contentOptions.command))
188
- throw new Error(`No command specified.`);
189
- options = {
190
- command: contentOptions.command,
191
- tty: (_a = contentOptions.tty) !== null && _a !== void 0 ? _a : false
192
- };
193
- break;
194
- case AssetContentType.config:
195
- if (_.isEmpty(contentOptions.rootPathName))
196
- throw new Error(`No file specified.`);
197
- options = {
198
- rootPathName: contentOptions.rootPathName
199
- };
200
- break;
201
- case AssetContentType.term:
202
- options = {
203
- terminalStartup: (_b = contentOptions.terminalStartup) !== null && _b !== void 0 ? _b : DEFAULT_TERMINAL_STARTER
204
- };
205
- break;
206
- case AssetContentType.env: /* env has no user input */
207
- default:
208
- options = {};
209
- break;
210
- }
211
- // Retrieve the list of replicas for the given cabinet.
212
- let rootMap = yield this.getRootMap(partialReq.enterprise);
213
- let env = this.deriveEnvironmentFrom(partialReq.enterprise, partialReq.cabinet, rootMap); // this is fkng stupid. Put this value into the cab value
214
- let cabObj = this.getCabinetInfrx(partialReq.enterprise, env.name, partialReq.cabinet, rootMap);
215
- if (cabObj.infrx == undefined || _.isEmpty(cabObj.infrx))
216
- throw new Error(`Cannot connect to cabinet ${cabObj.name}: it has no infrastructure record.`);
217
- let k8sObj = { namespace: cabObj.infrx.namespace };
218
- let replicas = yield this.fetchReplicas(partialReq, cabObj.infrx.namespace);
219
- if (replicas.length > 0) {
220
- // Set first as default
221
- partialReq.replica = (_d = (_c = replicas[0].metadata) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : "unnamed";
222
- k8sObj = {
223
- namespace: cabObj.infrx.namespace,
224
- pod: partialReq.replica,
225
- container: (_f = (_e = replicas[0].spec) === null || _e === void 0 ? void 0 : _e.containers[0].name) !== null && _f !== void 0 ? _f : "unnamed"
226
- };
227
- // Select a replica unless it's an asset-level operation
228
- if (content !== AssetContentType.status) {
229
- // This method falls back to first found as default, throws if not enough info is provided
230
- k8sObj = yield this.promptForReplica(replicas, undefined, partialReq.replica);
231
- partialReq.replica = k8sObj.pod;
232
- }
233
- }
234
- // Assemble
235
- let candidate = {
236
- context: {
237
- enterprise: partialReq.enterprise,
238
- environment: partialReq.environment,
239
- asset: partialReq.asset,
240
- cabinet: partialReq.cabinet,
241
- replica: partialReq.replica
242
- },
243
- contentType: content,
244
- contentOptions: options,
245
- k8sEntities: k8sObj,
246
- replicas: replicas
247
- };
248
- return candidate;
249
- });
250
- }
251
- buildCandidate_interactively(partialReq, content, contentOptions) {
252
- var _a, _b, _c, _d;
253
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
254
- this._userCntx = yield this.establishTenantContext(this._userCntx);
255
- let enterprise = (yield this.establishEnterpriseContext()).enterprise;
256
- partialReq.enterprise = enterprise.code;
257
- let rootMap = yield this.getRootMap(enterprise.code);
258
- let replicas;
259
- let k8sObj;
260
- let confirmed = false;
261
- let optionsArgs = [];
262
- do {
263
- // 1. Select Asset
264
- partialReq.asset = yield this.promptForAsset(enterprise.assets, partialReq.asset);
265
- // 2. Cabinet
266
- let cabObj = yield this.promptForCabinet(partialReq.enterprise, rootMap, partialReq.cabinet);
267
- partialReq.cabinet = cabObj.name;
268
- partialReq.environment = this.deriveEnvironmentFrom(partialReq.enterprise, partialReq.cabinet, rootMap).name;
269
- let cluster = this.deriveClusterFrom(partialReq.enterprise, partialReq.environment, partialReq.cabinet, rootMap);
270
- // partialReq.cabinet = await this.establishCabinetContext(partialReq.cabinet);
271
- if (cabObj.infrx == undefined || _.isEmpty(cabObj.infrx))
272
- throw new Error(`Cannot connect to cabinet ${cabObj.name}: it has no infrastructure record.`);
273
- k8sObj = { namespace: cabObj.infrx.namespace };
274
- // 3. Content type
275
- content = yield this.promptForContentType(content);
276
- // 4. Content-specific arguments
277
- // MarkStartHere("implement prompt-me designator.")
278
- // MarkStartHere("Support the current logger or ioc ctr inside the ws event handlers");
279
- // MarkStartHere("Need UI to operate a different stream than stdout (so piping stdout wont include the ui content");
280
- [contentOptions, optionsArgs] = yield this.promptForContentOptions(content, partialReq, contentOptions);
281
- // 5. Authenticate with CSP
282
- this.uiCloudPvd.takeDefaults = this.takeDefaults;
283
- yield this.uiCloudPvd.promptForCloudProviderCreds(this.ioc, cluster.provider);
284
- // 6. Replica (Pod)
285
- if (cabObj.infrx == undefined || _.isEmpty(cabObj.infrx))
286
- throw new Error(`Cannot connect to cabinet ${cabObj.name}: it has no infrastructure record.`);
287
- replicas = yield this.fetchReplicas(partialReq, cabObj.infrx.namespace);
288
- if (replicas.length > 0) {
289
- // Set first as default
290
- partialReq.replica = (_b = (_a = replicas[0].metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
291
- k8sObj = {
292
- namespace: cabObj.infrx.namespace,
293
- pod: partialReq.replica,
294
- container: (_d = (_c = replicas[0].spec) === null || _c === void 0 ? void 0 : _c.containers[0].name) !== null && _d !== void 0 ? _d : "unnamed"
295
- };
296
- // Select a replica unless it's an asset-level operation
297
- if (content !== AssetContentType.status) {
298
- k8sObj = yield this.promptForReplica(replicas, undefined, partialReq.replica);
299
- partialReq.replica = k8sObj.pod;
300
- }
301
- }
302
- // 7. Confirm or loop back around to enterprise
303
- confirmed = true; // This is a readonly ui (no danger), and we want to enable fast switching among diff content types, so let's not waste time confirming. // await this._ui.promptConfirm("confirm", "Apply? ");
304
- } while (!confirmed);
305
- // We're hard-coding instead of casting here to validate at build-time that each partial property is fully-hydrated.
306
- // Assemble
307
- let candidate = {
308
- context: {
309
- enterprise: partialReq.enterprise,
310
- environment: partialReq.environment,
311
- asset: partialReq.asset,
312
- cabinet: partialReq.cabinet,
313
- replica: partialReq.replica
314
- },
315
- contentType: content,
316
- contentOptions: contentOptions,
317
- k8sEntities: k8sObj,
318
- replicas: replicas
319
- };
320
- // Build command string
321
- let cmd = ["cod", "asset", "view"];
322
- cmd.push("--silent");
323
- cmd.push("-e", candidate.context.enterprise);
324
- cmd.push("-a", candidate.context.asset);
325
- cmd.push("-n", candidate.context.environment);
326
- cmd.push("-c", candidate.context.cabinet);
327
- if (candidate.context.replica)
328
- cmd.push("-r", candidate.context.replica);
329
- cmd.push("-t", candidate.contentType);
330
- cmd.push(...optionsArgs);
331
- return [candidate, cmd];
332
- });
333
- }
334
- promptForContentOptions(contentType, context, defaults) {
335
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
336
- let cmdArgs = [];
337
- try {
338
- switch (contentType) {
339
- case AssetContentType.logs:
340
- let logArgs = yield this.promptForLogOptions(defaults);
341
- if (logArgs.follow)
342
- cmdArgs.push("-f");
343
- if (logArgs.tailLines)
344
- cmdArgs.push(...["-l", "" + logArgs.tailLines]);
345
- return [logArgs, cmdArgs];
346
- case AssetContentType.exec:
347
- let execArgs = yield this.promptForExecOptions(defaults);
348
- cmdArgs.push(...execArgs.command);
349
- return [execArgs, cmdArgs];
350
- case AssetContentType.config:
351
- this.enterpriseContextor.takeDefaults = this.takeDefaults;
352
- let rootPathName = (yield this.enterpriseContextor.promptForTargetFile(context.enterprise, context.asset, defaults === null || defaults === void 0 ? void 0 : defaults.rootPathName));
353
- let cfgArgs = { rootPathName: rootPathName };
354
- cmdArgs.push("-F", rootPathName);
355
- return [cfgArgs, cmdArgs];
356
- case AssetContentType.term:
357
- let termArgs = yield this.promptForTerminalOptions(defaults);
358
- if (termArgs.terminalStartup)
359
- cmdArgs.push(...["--terminal", termArgs.terminalStartup]);
360
- return [termArgs, cmdArgs];
361
- default:
362
- return [{}, []];
363
- }
364
- }
365
- catch (err) {
366
- throw err;
367
- }
368
- });
369
- }
370
- promptForLogOptions(defaults) {
371
- var _a, _b;
372
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
373
- let options = (defaults !== null && defaults !== void 0 ? defaults : {});
374
- options.follow = (_a = options.follow) !== null && _a !== void 0 ? _a : true;
375
- if (!this.takeDefaults) {
376
- options.follow = yield this._ui.promptConfirm("follow", "Stream logs? ", options.follow);
377
- }
378
- options.tailLines = (_b = options.tailLines) !== null && _b !== void 0 ? _b : DEFAULT_LOG_TAIL;
379
- if (!this.takeDefaults) {
380
- options.tailLines = yield this._ui.prompt("tail", "Lines of backlog (-1 for all):", true, options.tailLines);
381
- }
382
- return options;
383
- });
384
- }
385
- promptForExecOptions(defaults) {
386
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
387
- let options = (defaults !== null && defaults !== void 0 ? defaults : {});
388
- // Command
389
- let cmdStr;
390
- let keep = this.takeDefaults;
391
- if (!_.isEmpty(options.command) && !this.takeDefaults) {
392
- cmdStr = (typeof options.command === 'string') ? options.command : options.command.join(" ");
393
- keep = yield this._ui.promptConfirm("keepCommand", `Command: ${this._styler.hilite(cmdStr)} `);
394
- }
395
- if (keep && !_.isEmpty(options.command)) {
396
- // do nothing
397
- }
398
- else {
399
- options.command = (yield this._ui.prompt("command", "Command: ", true, cmdStr));
400
- options.command = SplitCmd.split(options.command); // no types declarations - f#$&*ing script kiddie.
401
- // the one above trips on the --output flag in this: kubectl get pods -n cod-zombie-v1 -l assetNamme=codiac-api --output=jsonpath="{.items[*]['metadata.name', 'status.capacity']}"
402
- // something safer than: options.command = options.command.split(" ");
403
- }
404
- return options;
405
- });
406
- }
407
- promptForTerminalOptions(defaults) {
408
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
409
- let options = (defaults !== null && defaults !== void 0 ? defaults : {});
410
- // Command
411
- let keep = this.takeDefaults;
412
- if (!_.isEmpty(options.terminalStartup) && !this.takeDefaults) {
413
- keep = yield this._ui.promptConfirm("keepStartup", `Terminal Startup: ${this._styler.hilite(options.terminalStartup)} `);
414
- }
415
- if (keep && !_.isEmpty(options.terminalStartup)) {
416
- // do nothing
417
- }
418
- else {
419
- options.terminalStartup = (yield this._ui.prompt("startup", "Terminal Startup: ", true, options.terminalStartup));
420
- }
421
- return options;
422
- });
423
- }
424
- promptForContentType(defaultValue) {
425
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
426
- try {
427
- let output;
428
- let choices = Object.keys(AssetContentType);
429
- let keep = this.takeDefaults;
430
- if (defaultValue && choices.find(x => x == defaultValue) && !this.takeDefaults) {
431
- keep = yield this._ui.promptConfirm("keepType", `Type of content: ${this._styler.hilite(defaultValue)} `);
432
- }
433
- if (keep && defaultValue !== undefined) {
434
- output = defaultValue;
435
- }
436
- else {
437
- output = (yield this._ui.promptSelect("type", "Type of content: ", choices));
438
- }
439
- return output;
440
- }
441
- catch (err) {
442
- throw err;
443
- }
444
- });
445
- }
446
- promptForAsset(assets, defaultValue) {
447
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
448
- try {
449
- let output;
450
- let choices = assets.map(a => { return { name: a.name, value: a.name }; });
451
- choices = _.orderBy(choices, c => c.name);
452
- /** If we changed the input they provided, we need their confirmation (whether or not they said takeDefaults) */
453
- let changedUserInput = false;
454
- if (choices.length === 1) {
455
- if (defaultValue != choices[0].value) {
456
- changedUserInput = !_.isEmpty(defaultValue);
457
- defaultValue = choices[0].value;
458
- }
459
- }
460
- let keep = this.takeDefaults;
461
- if (defaultValue && choices.find(x => x.value == defaultValue) && (changedUserInput || !this.takeDefaults)) {
462
- keep = yield this._ui.promptConfirm("keepAsset", `Asset: ${this._styler.hilite(defaultValue)} `);
463
- }
464
- if (keep && defaultValue !== undefined) {
465
- output = defaultValue;
466
- }
467
- else {
468
- output = (yield this._ui.promptSelect("asset", "Asset: ", choices));
469
- }
470
- return output;
471
- }
472
- catch (err) {
473
- throw err;
474
- }
475
- });
476
- }
477
- promptForCabinet(enterprise, rootMap, defaultValue) {
478
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
479
- try {
480
- let output;
481
- // render cab tree with all lines selectable
482
- let cabTree = this.buildCabinetTree(rootMap);
483
- let choices = this.buildSelectChoicesFrom(cabTree);
484
- // ISSUES:
485
- // 0. Remove the freaking lines from the selected value.
486
- // 1. Remember the last cabinet (user's enterprise context).
487
- // 2. We should only render the cabinets that actually contain a deployment of the asset (or dim the others and loop back if selected)
488
- // 3. The picklist should render the cluster (provider, name, location)
489
- // 4. PERHAPS? The version of the asset running in the selected cabinet should get rendered (either in the picklist or after the cab is selected)
490
- /** If we changed the input they provided, we need their confirmation (whether or not they said takeDefaults) */
491
- const CAB_PREFIX = "cabinet|";
492
- let cabChoices = choices.filter(c => c.value.startsWith(CAB_PREFIX));
493
- let changedUserInput = false;
494
- if (cabChoices.length === 1) {
495
- if (defaultValue != cabChoices[0].value.slice(CAB_PREFIX.length)) {
496
- changedUserInput = !_.isEmpty(defaultValue);
497
- defaultValue = cabChoices[0].value.slice(CAB_PREFIX.length);
498
- }
499
- }
500
- let keep = this.takeDefaults;
501
- if (defaultValue && Boolean(choices.find(x => x.value === `${CAB_PREFIX}${defaultValue}`)) && (changedUserInput || !this.takeDefaults)) {
502
- keep = yield this._ui.promptConfirm("keepCabinet", `Cabinet: ${this._styler.hilite(defaultValue)} `);
503
- }
504
- if (keep && defaultValue !== undefined) {
505
- output = defaultValue;
506
- }
507
- else {
508
- let scope;
509
- let target;
510
- do {
511
- if (scope === "environment") {
512
- // we could just filter it down from here...
513
- }
514
- let selection = (yield this._ui.promptSelect("cabinet", "Cabinet: ", choices, false, false));
515
- let parts = selection.split("|");
516
- scope = parts[0];
517
- target = parts[1];
518
- } while (scope !== "cabinet"); // ensure they select a cabinet
519
- output = target;
520
- }
521
- let env = this.deriveEnvironmentFrom(enterprise, output, rootMap); // this is fkng stupid. Put this value into the cab value
522
- let cabObj = this.getCabinetInfrx(enterprise, env.name, output, rootMap);
523
- // return output;
524
- return cabObj;
525
- }
526
- catch (err) {
527
- throw (err);
528
- }
529
- });
530
- }
531
- deriveEnvironmentFrom(enterprise, cabinet, rootMap) {
532
- try {
533
- let ent = rootMap.enterprises.find(e => e.name === enterprise);
534
- if (ent === undefined)
535
- throw new Error(`Cannot find environment: did not recognize enterprise [${enterprise}]`);
536
- let enviro = ent.environments.find(x => x.cabinets.find(c => c.name === cabinet));
537
- if (enviro === undefined)
538
- throw new Error(`Cannot find environment: did not recognize cabinet [${cabinet}]`);
539
- return enviro;
540
- }
541
- catch (err) {
542
- throw err;
543
- }
544
- }
545
- deriveClusterFrom(enterprise, environment, cabinet, rootMap) {
546
- try {
547
- let ent = rootMap.enterprises.find(e => e.name === enterprise);
548
- if (ent === undefined)
549
- throw new Error(`Cannot find cluster: did not recognize enterprise [${enterprise}]`);
550
- let enviro = ent.environments.find(x => x.cabinets.find(c => c.name === cabinet));
551
- if (enviro === undefined)
552
- throw new Error(`Cannot find cluster: did not recognize cabinet [${cabinet}]`);
553
- let cabObj = enviro.cabinets.find(c => c.name === cabinet);
554
- if (cabObj == undefined)
555
- throw new Error(`Cannot find cluster: did not recognize cabinet [${cabinet}]`);
556
- if (cabObj.cluster == undefined)
557
- throw new Error(`Cannot find cluster: cabinet [${cabinet}] does not have a cluster specified.`);
558
- let cluster = rootMap.clusters.find(c => c.name == cabObj.cluster);
559
- if (cluster == undefined)
560
- throw new Error(`Did not recognize cluster [${cabObj.cluster}]`);
561
- return cluster;
562
- }
563
- catch (err) {
564
- throw err;
565
- }
566
- }
567
- buildSelectChoicesFrom(tree) {
568
- try {
569
- let choices = [];
570
- // the value is no good here - need scope and target both available
571
- render.renderStringTree(tree, (txt, item) => choices.push({ name: txt, value: item.value }));
572
- // // This is one way to do it
573
- // for (let item of tree) {
574
- //
575
- // let thisChoice: PromptChoice = { name: item.text, value: item.text };
576
- // choices.push(thisChoice);
577
- //
578
- // if (item.children && item.children.length > 0) {
579
- // let children = this.buildSelectChoicesFrom(item.children);
580
- // choices.push(...children);
581
- // }
582
- // }
583
- return choices;
584
- }
585
- catch (err) {
586
- throw err;
587
- }
588
- }
589
- /** sets each value to "scope|target".
590
- *
591
- * This is MOSTLY a COPY-PASTE from the CabinetList command!!! This view is prob gonna be pretty common - consider promoting it to a shared utility. */
592
- buildCabinetTree(rootMap, existings) {
593
- var _a, _b, _c, _d;
594
- let tree = [];
595
- for (let ent of rootMap.enterprises) {
596
- let entBranch = { text: `${ent.name} enterprise:`, value: `${codiac_relay_contracts_1.ScopeLevel.enterprise}|${ent.name}` };
597
- let entSetting = existings === null || existings === void 0 ? void 0 : existings.find(s => s.scope === codiac_relay_contracts_1.ScopeLevel.enterprise && s.target === ent.name);
598
- if (entSetting !== undefined) {
599
- let valueSuffix = this.ellipsis(35, (_a = entSetting.value) !== null && _a !== void 0 ? _a : "[set to undefined]");
600
- valueSuffix = `(${valueSuffix})`;
601
- entBranch.text = entBranch.text.concat(" ", this._styler.dim(valueSuffix));
602
- }
603
- for (let env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
604
- let envBranch = { text: `${env.name}`, value: `${codiac_relay_contracts_1.ScopeLevel.environment}|${env.name}` };
605
- let envSetting = existings === null || existings === void 0 ? void 0 : existings.find(s => s.scope === codiac_relay_contracts_1.ScopeLevel.environment && s.target === env.name);
606
- if (envSetting !== undefined) {
607
- let valueSuffix = this.ellipsis(35, (_b = envSetting.value) !== null && _b !== void 0 ? _b : "[set to undefined]");
608
- valueSuffix = `(${valueSuffix})`;
609
- envBranch.text = envBranch.text.concat(" ", this._styler.dim(valueSuffix));
610
- }
611
- for (let cab of env.cabinets) {
612
- // let cwg = rootMap.clusters.find(c => c.name === cab.cluster);
613
- // let clusterDesc = cwg ? ` (${cab.cluster}, ${cwg.provider} ${cwg.locationName})` : "";
614
- let cabBranch = {
615
- text: `${cab.name}`,
616
- value: `${codiac_relay_contracts_1.ScopeLevel.cabinet}|${cab.name}`
617
- };
618
- let cabSetting = existings === null || existings === void 0 ? void 0 : existings.find(s => s.scope === codiac_relay_contracts_1.ScopeLevel.cabinet && s.target === cab.name);
619
- if (cabSetting !== undefined) {
620
- let valueSuffix = this.ellipsis(35, (_c = cabSetting.value) !== null && _c !== void 0 ? _c : "[set to undefined]");
621
- valueSuffix = `(${valueSuffix})`;
622
- cabBranch.text = cabBranch.text.concat(" ", this._styler.dim(valueSuffix));
623
- }
624
- if (envBranch.children === undefined)
625
- envBranch.children = [];
626
- (_d = envBranch.children) === null || _d === void 0 ? void 0 : _d.push(cabBranch);
627
- }
628
- if (entBranch.children === undefined)
629
- entBranch.children = [];
630
- entBranch.children.push(envBranch);
631
- }
632
- tree.push(entBranch);
633
- }
634
- return tree;
635
- }
636
- /** Truncates the string to the given length with an ellipses as suffix */
637
- ellipsis(maxLength, value) {
638
- let output = value;
639
- if (output.length > maxLength) {
640
- let ellipsis = "..."; // Rather use the ellipsis character but String.fromCharCode(133) is returning a problematic character.
641
- output = output.slice(0, maxLength - 1 - ellipsis.length).concat(ellipsis);
642
- }
643
- return output;
644
- }
645
- /**
646
- *
647
- * @param enterprise
648
- * @param environment
649
- * @param cabinet
650
- * @param asset
651
- * @param ctrInPod (Optional, defaults to the first one in the spec) The name of the running container (not the image) inside the pod (relevant only when there's more than one).
652
- * @param defaultValue
653
- * @returns
654
- */
655
- promptForReplica(replicas, ctrInPod, defaultValue) {
656
- var _a, _b, _c, _d, _e;
657
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
658
- try {
659
- let podName;
660
- // params: enterprise: string, environment: string, cabinet: string, asset: string
661
- // // Retrieve replicas
662
- // this._ui.startSpinner(`Fetching ${asset} replicas in ${environment}/${cabinet}...`)
663
- // let reps = await this.genRelayClient.Call.assetStatus({ assetName: asset, cabinetName: cabinet, enterpriseCode: enterprise, environment: environment });
664
- // this._ui.stopSpinner((reps.successes) ? `${reps.successes.length} found.` : "failed.")
665
- // if (reps.error) throw reps.error;
666
- // if (reps.successes == undefined || reps.successes.length === 0) throw new Error(`No ${asset} replicas exist in cabinet ${environment}/${cabinet}. ${reps.message ?? ""}`);
667
- //
668
- // let replicas = reps.successes[0].currentVersion.pods; // <--- HEY!!! Relay shouldnt be exposing raw k8s contracts here - this shd be a codiac contract
669
- let choices = replicas.filter(r => { var _a; return ((_a = r.metadata) === null || _a === void 0 ? void 0 : _a.name) !== undefined; })
670
- .map(r => { var _a, _b, _c; return ({ name: `${(_a = r.metadata.name) !== null && _a !== void 0 ? _a : ""} (${(_b = r.status) === null || _b === void 0 ? void 0 : _b.phase})`, value: (_c = r.metadata.name) !== null && _c !== void 0 ? _c : "" }); });
671
- // Select a replica...
672
- if (choices.length === 0) {
673
- this._ui.userMessage(`No replicas found.`);
674
- podName = "unknown";
675
- // return undefined; // <--- this is what we should do here.
676
- }
677
- else if (choices.length === 1) {
678
- podName = choices[0].value;
679
- this._ui.userMessage(`1 replica found: ${this._styler.hilite(podName)}`);
680
- }
681
- else {
682
- let keep = this.takeDefaults;
683
- if (defaultValue && Boolean(choices.find(x => x.value === defaultValue)) && !this.takeDefaults) {
684
- keep = yield this._ui.promptConfirm("keepReplica", `Replica: ${this._styler.hilite(defaultValue)} `);
685
- }
686
- if (keep && defaultValue !== undefined) {
687
- podName = defaultValue;
688
- }
689
- else {
690
- podName = (yield this._ui.promptSelect("replica", "Replica...", choices, false, false)); // Assertion operator ok here - we're not allowing undefined options.
691
- }
692
- }
693
- let replica = (replicas.find(r => { var _a; return ((_a = r.metadata) === null || _a === void 0 ? void 0 : _a.name) === podName; })); // Assertion ok: selection was already limited to this list.
694
- // Select the container inside...
695
- let containerName;
696
- if ((((_a = replica.spec) === null || _a === void 0 ? void 0 : _a.containers) == undefined) || (((_b = replica.spec) === null || _b === void 0 ? void 0 : _b.containers.length) === 0))
697
- throw new Error("No containers are specified in that replica");
698
- if (!_.isEmpty(ctrInPod)) {
699
- let found = replica.spec.containers.find(c => c.name === ctrInPod);
700
- if (!found)
701
- throw new Error(`Container [${ctrInPod}] not found in that replica`);
702
- containerName = found.name;
703
- }
704
- else {
705
- containerName = replica.spec.containers[0].name;
706
- if (((_c = replica.spec) === null || _c === void 0 ? void 0 : _c.containers.length) > 1) {
707
- // TODO: promptSelect from the list of containers
708
- this._ui.userMessage(`${(_d = replica.spec) === null || _d === void 0 ? void 0 : _d.containers.length} containers in that replica; selected ${containerName}`);
709
- }
710
- }
711
- let k8sCtr = {
712
- namespace: (_e = replica.metadata) === null || _e === void 0 ? void 0 : _e.namespace,
713
- pod: podName,
714
- container: containerName
715
- };
716
- return k8sCtr;
717
- }
718
- catch (err) {
719
- throw err;
720
- }
721
- });
722
- }
723
- renderSelectedContent(context, contentType, k8sEntities, contentOptions, replicas) {
724
- var _a;
725
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
726
- try {
727
- switch (contentType) {
728
- case (AssetContentType.logs):
729
- if (context.replica == undefined)
730
- throw new Error("No replica selected.");
731
- if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
732
- throw new Error("No replica selected.");
733
- yield this.showLogs(context, contentOptions);
734
- break;
735
- case (AssetContentType.term):
736
- if (context.replica == undefined)
737
- throw new Error("No replica selected.");
738
- if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
739
- throw new Error("No replica selected.");
740
- let termArgs = { tty: true, command: (_a = contentOptions === null || contentOptions === void 0 ? void 0 : contentOptions.terminalStartup) !== null && _a !== void 0 ? _a : DEFAULT_TERMINAL_STARTER };
741
- yield this.runExec(context, termArgs, k8sEntities);
742
- break;
743
- case (AssetContentType.exec):
744
- if (context.replica == undefined)
745
- throw new Error("No replica selected.");
746
- if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
747
- throw new Error("No replica selected.");
748
- let execArgs = contentOptions;
749
- execArgs.tty = false; // and we want a run-once behavior so the ws closes after the command completes.
750
- yield this.runExec(context, execArgs, k8sEntities);
751
- break;
752
- case (AssetContentType.config):
753
- if (context.replica == undefined)
754
- throw new Error("No replica selected.");
755
- if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
756
- throw new Error("No replica selected.");
757
- let cfgInput = contentOptions;
758
- if (!cfgInput.rootPathName.startsWith("/"))
759
- cfgInput.rootPathName = "/".concat(cfgInput.rootPathName);
760
- let cfgExec = { tty: false, command: ["cat", cfgInput.rootPathName] };
761
- yield this.runExec(context, cfgExec, k8sEntities);
762
- break;
763
- case (AssetContentType.env):
764
- if (context.replica == undefined)
765
- throw new Error("No replica selected.");
766
- if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
767
- throw new Error("No replica selected.");
768
- let envArgs = { tty: false, command: "env" };
769
- yield this.runExec(context, envArgs, k8sEntities);
770
- break;
771
- case (AssetContentType.status):
772
- // await this.watchEvents(context, k8sEntities.namespace, replicas);
773
- yield this.watchStatus_NEW(context, k8sEntities.namespace, replicas);
774
- // await this.watchStatus(context, k8sEntities.namespace, replicas);
775
- // await this.watchReplicaSet(context, k8sEntities.namespace);
776
- // await this.showStatus(context, k8sEntities.namespace, replicas);
777
- break;
778
- default:
779
- this.logger.debug(`Content type ${contentType} is not yet supported.`, [context, contentType, contentOptions]);
780
- this._ui.userMessage(`Content type ${contentType} is not yet supported.`);
781
- }
782
- return;
783
- }
784
- catch (err) {
785
- throw (err);
786
- }
787
- });
788
- }
789
- getKubeConfig(context) {
790
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
791
- // Retrieve cluster connection specs
792
- let res = yield this.genRelayClient.Call.getClusterConnectionSpecs({
793
- enterprise: context.enterprise,
794
- environment: context.environment,
795
- cabinet: context.cabinet
796
- });
797
- if (res.error)
798
- throw res.error;
799
- if (res.output == undefined || _.isEmpty(res.output)) {
800
- this.log(`Failed loading cluster spec: ${res.message}.`);
801
- throw new Error(`Failed loading cluster spec: ${res.message}.`);
802
- }
803
- // Create the k8s client
804
- let k8sConfig = new client_node_1.KubeConfig();
805
- k8sConfig.loadFromString(res.output);
806
- return k8sConfig;
807
- });
808
- }
809
- getK8sClient(context, kube) {
810
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
811
- let k8sConfig = kube !== null && kube !== void 0 ? kube : (yield this.getKubeConfig(context));
812
- let theirApi = k8sConfig.makeApiClient(k8s.CoreV1Api);
813
- return theirApi;
814
- });
815
- }
816
- /** Gets the cluster cnxn specs from the relay, then makes the k8s call from the cli.
817
- *
818
- * Throws any errors. */
819
- fetchReplicas(context, namespace, k8sClient) {
820
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
821
- try {
822
- let theirApi = k8sClient !== null && k8sClient !== void 0 ? k8sClient : yield this.getK8sClient(context);
823
- // Fetch from the cluster
824
- let podResult = yield theirApi.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, `${codiac_constants_1.CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`);
825
- let replicas = podResult.body.items;
826
- // let replicas = _.orderBy(podResult.body.items, p => p.metadata?.labels?.assetVersion, 'desc'); // NOTE: this isnt a semantic version sort
827
- try {
828
- // Might need a semver.coerce() in here...
829
- replicas = replicas.sort((a, b) => { var _a, _b, _c, _d, _e, _f; return semver.rcompare((_c = (_b = (_a = a.metadata) === null || _a === void 0 ? void 0 : _a.labels) === null || _b === void 0 ? void 0 : _b.assetVersion) !== null && _c !== void 0 ? _c : "", (_f = (_e = (_d = b.metadata) === null || _d === void 0 ? void 0 : _d.labels) === null || _e === void 0 ? void 0 : _e.assetVersion) !== null && _f !== void 0 ? _f : ""); }); // removes semvers so they can be sorted uniquely
830
- }
831
- catch (err) {
832
- replicas = _.orderBy(replicas, p => { var _a, _b, _c; return (_c = (_b = (_a = p.metadata) === null || _a === void 0 ? void 0 : _a.labels) === null || _b === void 0 ? void 0 : _b.assetVersion) !== null && _c !== void 0 ? _c : ""; }); // TODO: we need this ALSO sorted by replica set (ie: name or labels["pod-template-hash"])
833
- }
834
- return replicas;
835
- }
836
- catch (err) {
837
- throw err;
838
- }
839
- });
840
- }
841
- // protected async watchEvents(context: AssetReplicaContext, namespace: string, replicas?: k8s.V1Pod[] | undefined): Promise<void> {
842
- // // let selector = `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`;
843
- // let selector = `app=${context.asset}`;
844
- // let creds = await this.getKubeConfig(context);
845
- // let k8sClient = creds.makeApiClient(k8s.EventsV1Api);
846
- // let watcher = new Watch(creds);
847
- // watcher.watch(
848
- // '/apis/events.k8s.io/v1/namespaces/{namespace}/events',
849
- // )
850
- // let res = await k8sClient.listNamespacedEvent(namespace, undefined, undefined, undefined, undefined, selector,
851
- // undefined, undefined, undefined, undefined, true, undefined);
852
- // }
853
- watchStatus_NEW(context, namespace, replicas) {
854
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
855
- // let selector = `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`;
856
- let selector = `app=${context.asset}`;
857
- let kube = yield this.getKubeConfig(context);
858
- let k8sClient = yield this.getK8sClient(context);
859
- (0, log_update_wrapper_1.logUpdate)(`Watching ${this._styler.hilite(context.asset)} in ${context.environment}/${context.cabinet}... (ctrl-c to quit)`);
860
- log_update_wrapper_1.logUpdate.done();
861
- (0, log_update_wrapper_1.logUpdate)(`...empty...`);
862
- // This approach DOES return what's different in the cached list,
863
- // but doesnt stream updates from the cluster - it only runs a first request,
864
- // meaning you need to call this repeatedly - this looks not fully-baked...?
865
- let informer = (0, client_node_1.makeInformer)(kube, `/api/v1/namespaces/${namespace}/pods`, () => k8sClient.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, selector)
866
- // () => k8sClient.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, selector, undefined, undefined, undefined, undefined, true),
867
- // selector
868
- );
869
- // informer.on('add', (obj: k8s.V1Pod) => { console.log(`Added: ${obj.metadata!.name}`); });
870
- // informer.on('update', (obj: k8s.V1Pod) => { console.log(`Updated: ${obj.metadata!.name}`); });
871
- informer.on('change', (obj) => {
872
- // console.log(`Changed: ${obj.metadata!.name}`);
873
- let canvas = { table: "", curver: "" };
874
- let replicas = informer.list(namespace);
875
- if (replicas.length > 0) {
876
- for (let pod of replicas) {
877
- this.renderReplicaStatusRow(pod, canvas);
878
- }
879
- }
880
- else {
881
- canvas.table = "(no instances found)";
882
- }
883
- log_update_wrapper_1.logUpdate.clear();
884
- (0, log_update_wrapper_1.logUpdate)(canvas.table);
885
- });
886
- // informer.on('delete', (obj: k8s.V1Pod) => { console.log(`Deleted: ${obj.metadata!.name}`); });
887
- informer.on('error', (err) => {
888
- if (err.statusCode === 401) {
889
- // TODO: reach out to the relay to refresh the user token in the kubeconfig.
890
- log_update_wrapper_1.logUpdate.clear();
891
- (0, log_update_wrapper_1.logUpdate)(`Authentication error; please refresh your credentials.`);
892
- }
893
- else {
894
- log_update_wrapper_1.logUpdate.clear();
895
- console.error(err);
896
- }
897
- // Restart informer after 5sec
898
- setTimeout(() => {
899
- informer.start();
900
- }, 5000);
901
- });
902
- informer.start();
903
- // let watch: boolean = true;
904
- // listNamespacedPod() with "watch" just floats out into space with no return
905
- // let podResult = await k8sClient.listNamespacedPod(namespace, undefined, undefined, undefined, undefined,
906
- // `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`, undefined, undefined, undefined, undefined, watch);
907
- // while (podResult) {
908
- // logUpdate(`${podResult.body.items.length} pods returned`); // Thanks, nice and ambiguous; lets give them something actionable here instead.
909
- // }
910
- });
911
- }
912
- watchReplicaSet(context, namespace, replicaSets) {
913
- var _a, _b, _c, _d, _e, _f, _g;
914
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
915
- let k8sConfig = (yield this.getKubeConfig(context));
916
- let k8sClient = k8sConfig.makeApiClient(k8s.AppsV1Api);
917
- // let selector = `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`;
918
- let selector = `app=${context.asset}`;
919
- let watch = true;
920
- do {
921
- let content = "";
922
- log_update_wrapper_1.logUpdate.clear();
923
- try {
924
- let podResult = yield k8sClient.listNamespacedReplicaSet(namespace, undefined, undefined, undefined, undefined, selector);
925
- let output = podResult.body.items;
926
- for (let item of output) {
927
- if (item.status) {
928
- content = content.concat(`${(_b = (_a = item.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed"} ${(_c = item.status.availableReplicas) !== null && _c !== void 0 ? _c : 0}/${item.status.replicas}`, "\n");
929
- }
930
- else {
931
- content = content.concat(`no status for ${(_e = (_d = item.metadata) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : "unnamed"}`, "\n");
932
- }
933
- }
934
- }
935
- catch (err) {
936
- content = content.concat(`Error ${(_f = err.name) !== null && _f !== void 0 ? _f : ""} ${(_g = err.message) !== null && _g !== void 0 ? _g : ""}`, "\n");
937
- }
938
- (0, log_update_wrapper_1.logUpdate)(content);
939
- yield this.unblockAndSleep(0.5);
940
- } while (watch);
941
- });
942
- }
943
- watchStatus(context, namespace, replicas) {
944
- var _a, _b, _c, _d, _e, _f, _g;
945
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
946
- let watch = true;
947
- let k8sClient = yield this.getK8sClient(context);
948
- let pods = replicas;
949
- let spinChars = ["|", "/", "-", "\\"];
950
- let spinIndex = -1;
951
- (0, log_update_wrapper_1.logUpdate)(`Status for ${context.asset} in ${context.environment}/${context.cabinet}... (ctrl-c to quit)`);
952
- log_update_wrapper_1.logUpdate.done();
953
- do {
954
- // await this.showStatus(context, namespace, pods, k8sClient);
955
- spinIndex++;
956
- if (spinIndex >= spinChars.length)
957
- spinIndex = 0;
958
- let spinner = spinChars[spinIndex];
959
- // TODO: trap failures here and if status currently exists, render the error and leave the existing
960
- let table = "";
961
- try {
962
- pods = pods !== null && pods !== void 0 ? pods : yield this.fetchReplicas(context, namespace, k8sClient);
963
- if (pods && pods.length > 0) {
964
- log_update_wrapper_1.logUpdate.clear();
965
- let curver = ""; // current asset version being listed
966
- // let deployed = res.successes[0].currentVersion.deployed;
967
- for (let replica of pods) {
968
- let replicaName = (_b = (_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
969
- let podHash = ((_c = replica.metadata) === null || _c === void 0 ? void 0 : _c.labels) ? (_d = replica.metadata) === null || _d === void 0 ? void 0 : _d.labels["pod-template-hash"] : undefined;
970
- let replicaId = podHash ? replicaName.slice(replicaName.indexOf(podHash)) : replicaName;
971
- let assetVersion = ((_e = replica.metadata) === null || _e === void 0 ? void 0 : _e.labels) ? (_f = replica.metadata) === null || _f === void 0 ? void 0 : _f.labels[codiac_constants_1.CodiacLabels.LABEL_ASSET_VERSION] : undefined;
972
- // Version separator
973
- if (assetVersion !== undefined && assetVersion !== curver) {
974
- curver = assetVersion;
975
- table = table.concat(`${spinner} ${assetVersion}`, "\n");
976
- }
977
- // Each replica
978
- if (replica.status) {
979
- let state = this.renderPodState(replica);
980
- let condition = this.renderCondition(replica);
981
- let restarts = (replica.status.containerStatuses && replica.status.containerStatuses.length > 0) ? replica.status.containerStatuses[0].restartCount : 0;
982
- table = table.concat(` ${replicaId}) ${state} ${condition} started (${replica.status.startTime}) ${restarts} restarts\n`); // , deployed (${deployed})`)
983
- }
984
- }
985
- }
986
- else {
987
- table = table.concat(`No running instances found.`);
988
- }
989
- }
990
- catch (err) {
991
- table = table.concat(`Error refreshing... ${(_g = err.message) !== null && _g !== void 0 ? _g : err.name}\n`);
992
- }
993
- (0, log_update_wrapper_1.logUpdate)(table);
994
- pods = undefined;
995
- yield this.unblockAndSleep(0.5);
996
- } while (watch);
997
- });
998
- }
999
- /** Mutates canvas */
1000
- renderReplicaStatusRow(replica, canvas) {
1001
- var _a, _b, _c, _d, _e, _f;
1002
- let replicaName = (_b = (_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
1003
- let podHash = ((_c = replica.metadata) === null || _c === void 0 ? void 0 : _c.labels) ? (_d = replica.metadata) === null || _d === void 0 ? void 0 : _d.labels["pod-template-hash"] : undefined;
1004
- let replicaId = podHash ? replicaName.slice(replicaName.indexOf(podHash)) : replicaName;
1005
- let assetVersion = ((_e = replica.metadata) === null || _e === void 0 ? void 0 : _e.labels) ? (_f = replica.metadata) === null || _f === void 0 ? void 0 : _f.labels[codiac_constants_1.CodiacLabels.LABEL_ASSET_VERSION] : undefined;
1006
- // Version separator
1007
- if (assetVersion !== undefined && assetVersion !== canvas.curver) {
1008
- canvas.curver = assetVersion;
1009
- canvas.table = canvas.table.concat(`${assetVersion}`, "\n");
1010
- }
1011
- // Each replica
1012
- if (replica.status) {
1013
- let state = this.renderPodState(replica);
1014
- let condition = this.renderCondition(replica);
1015
- let restarts = (replica.status.containerStatuses && replica.status.containerStatuses.length > 0) ? replica.status.containerStatuses[0].restartCount : 0;
1016
- canvas.table = canvas.table.concat(` ${replicaId}) ${state} ${condition} started (${replica.status.startTime}) ${restarts} restarts\n`); // , deployed (${deployed})`)
1017
- }
1018
- }
1019
- renderCondition(replica) {
1020
- var _a;
1021
- let cond = "";
1022
- if (replica.status) {
1023
- if (((_a = replica.status) === null || _a === void 0 ? void 0 : _a.conditions) && replica.status.conditions.length > 0) {
1024
- let latestCond = _.orderBy(replica.status.conditions, x => x.lastTransitionTime, "desc")[0];
1025
- cond = latestCond.type;
1026
- if (latestCond.reason) {
1027
- cond = cond.concat(" (", latestCond.reason, ")");
1028
- }
1029
- if (latestCond.message) {
1030
- // TODO: Revisit; message is prob too much info to jam into a cli output line.
1031
- cond = cond.concat(" ('", latestCond.message, "')");
1032
- }
1033
- cond = cond.concat(` since (${latestCond.lastTransitionTime})`);
1034
- }
1035
- }
1036
- return cond;
1037
- }
1038
- renderPodState(replica) {
1039
- var _a, _b, _c, _d;
1040
- let state = "[no status found]";
1041
- if ((_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.deletionTimestamp) {
1042
- state = "Terminating";
1043
- }
1044
- else if (replica.status) {
1045
- state = "";
1046
- // Pod phase
1047
- if (replica.status.phase) {
1048
- state = replica.status.phase;
1049
- }
1050
- if (replica.status.reason) {
1051
- state = state.concat(" (", replica.status.reason, ")");
1052
- }
1053
- if (replica.status.message) {
1054
- state = state.concat(" ('", replica.status.message, "')");
1055
- }
1056
- // container state
1057
- if (replica.status.containerStatuses && replica.status.containerStatuses.length > 0) {
1058
- let ctrStatus = replica.status.containerStatuses[0];
1059
- // state = state.concat(" ", JSON.stringify(ctrStatus.state), "\n");
1060
- if ((_b = ctrStatus.state) === null || _b === void 0 ? void 0 : _b.waiting) {
1061
- if (ctrStatus.state.waiting.reason) {
1062
- state = state.concat(" (", ctrStatus.state.waiting.reason, ")");
1063
- }
1064
- if (ctrStatus.state.waiting.message) {
1065
- state = state.concat(" ('", ctrStatus.state.waiting.message, "')");
1066
- }
1067
- }
1068
- else if ((_c = ctrStatus.state) === null || _c === void 0 ? void 0 : _c.terminated) {
1069
- if (ctrStatus.state.terminated.reason) {
1070
- state = state.concat(" (", ctrStatus.state.terminated.reason, ")");
1071
- }
1072
- if (ctrStatus.state.terminated.message) {
1073
- state = state.concat(" (", ctrStatus.state.terminated.message, ")");
1074
- }
1075
- }
1076
- else if ((_d = ctrStatus.state) === null || _d === void 0 ? void 0 : _d.running) {
1077
- }
1078
- }
1079
- }
1080
- return state;
1081
- }
1082
- unblockAndSleep(durationInSecs) {
1083
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1084
- return new Promise(resolve => {
1085
- setTimeout(() => resolve(), durationInSecs * 1000);
1086
- });
1087
- });
1088
- }
1089
- /** Fetches pods if not already provided. */
1090
- showStatus(context, namespace, replicas, k8sApi) {
1091
- var _a, _b, _c;
1092
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1093
- try {
1094
- let k8sClient = k8sApi !== null && k8sApi !== void 0 ? k8sApi : yield this.getK8sClient(context);
1095
- let pods = replicas !== null && replicas !== void 0 ? replicas : yield this.fetchReplicas(context, namespace, k8sClient);
1096
- if (pods && pods.length > 0) {
1097
- // let deployed = res.successes[0].currentVersion.deployed;
1098
- console.log(`Status for ${context.asset} ${(pods.length > 0) ? " instances" : ""} running in ${context.environment}/${context.cabinet}`);
1099
- for (let replica of pods) {
1100
- let replicaName = (_b = (_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
1101
- if (((_c = replica.status) === null || _c === void 0 ? void 0 : _c.conditions) && replica.status.conditions.length > 0) {
1102
- let latestCond = _.orderBy(replica.status.conditions, x => x.lastTransitionTime, "desc")[0];
1103
- console.log(`${replicaName} ${latestCond.type} since (${latestCond.lastTransitionTime}) started (${replica.status.startTime}) ${replica.status.containerStatuses[0].restartCount} restarts`); // , deployed (${deployed})`)
1104
- }
1105
- else {
1106
- console.log("Condition not available"); // Thanks, nice and ambiguous; lets give them something actionable here instead.
1107
- }
1108
- }
1109
- }
1110
- else {
1111
- this._ui.userMessage(`No running instances found.`);
1112
- }
1113
- return;
1114
- }
1115
- catch (err) {
1116
- throw err;
1117
- }
1118
- });
1119
- }
1120
- showLogs(context, logOptions) {
1121
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1122
- try {
1123
- // SHOW LOGS
1124
- let req = Object.assign(Object.assign({}, context), { logOptions: logOptions });
1125
- let cnxnResult = yield this.genRelayClient.Call.getLogStreamSpecs(req);
1126
- if (cnxnResult.error)
1127
- throw cnxnResult.error;
1128
- if (cnxnResult.output == undefined)
1129
- throw new Error(`Failed without error getting log stream connection specs.`);
1130
- const logStream = new stream.PassThrough();
1131
- logStream.on("data", (chunk) => {
1132
- // use write rather than console.log to prevent double line feed
1133
- process.stdout.write(chunk);
1134
- });
1135
- let streamer = new LogStreamer(this.logger);
1136
- let requestOptions = cnxnResult.output;
1137
- // Deserialize from strings into Buffers after their trip over the wire
1138
- if (cnxnResult.output.ca)
1139
- requestOptions.ca = Buffer.from(cnxnResult.output.ca);
1140
- else
1141
- this.logger.warn(`Cluster connection specs retrieved for log streaming did not have a ca.`);
1142
- if (cnxnResult.output.cert)
1143
- requestOptions.cert = Buffer.from(cnxnResult.output.cert);
1144
- else
1145
- this.logger.warn(`Cluster connection specs retrieved for log streaming did not have a cert.`);
1146
- if (cnxnResult.output.key)
1147
- requestOptions.key = Buffer.from(cnxnResult.output.key);
1148
- else
1149
- this.logger.warn(`Cluster connection specs retrieved for log streaming did not have a key.`);
1150
- streamer.go(requestOptions, logStream); // shouldn't we be awaiting this?
1151
- }
1152
- catch (err) {
1153
- throw err;
1154
- }
1155
- });
1156
- }
1157
- /**
1158
- * @param context Fully qualified path, in terms of Codiac entities, to identify a single replica of an asset in a cabinet.
1159
- * @param execArgs Parameters identifying the ultimate command to run and the console behavior.
1160
- * @param K8sEntities The identifying names of the relevant kubernetes objects, corresponding to the asset replica context, that fully qualify the desired container. */
1161
- runExec(context, execArgs, k8sEntities) {
1162
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1163
- try {
1164
- let k8sCnxnResult = yield this.genRelayClient.Call.getClusterConnectionSpecs(context);
1165
- if (k8sCnxnResult.error)
1166
- throw k8sCnxnResult.error;
1167
- if (k8sCnxnResult.output === undefined || _.isEmpty(k8sCnxnResult.output))
1168
- throw new Error(`Retrieval of cluster connection spec failed without error.`);
1169
- let spec = k8sCnxnResult.output;
1170
- let kc = new k8s.KubeConfig();
1171
- kc.loadFromString(spec);
1172
- // ======================================================================================================
1173
- // We have to resume here because the console keystrokes are not getting through,
1174
- // even though a POC running just the exec (without all the other ui code we're running)
1175
- // doesnt have the input problem.
1176
- //
1177
- // TODO: Find out why we need this stdin resumed.
1178
- // Most likely because it was piped into an spawned child process that has since ended.
1179
- //
1180
- process.stdin.resume(); // Somehwere we probably lost track of a stdin
1181
- //
1182
- //
1183
- // ======================================================================================================
1184
- const exec = new k8s.Exec(kc);
1185
- const ws = yield exec.exec(k8sEntities.namespace, k8sEntities.pod, k8sEntities.container, execArgs.command, process.stdout, process.stderr, process.stdin, execArgs.tty, (status) => {
1186
- // tslint:disable-next-line:no-console
1187
- // console.log("Exited with status:");
1188
- // // tslint:disable-next-line:no-console
1189
- this.logger.debug(`Executed terminal cmd. Status: ${status.status} ${status.reason}`, JSON.stringify(status, null, 2));
1190
- });
1191
- ws.onopen = function open() {
1192
- process.stdout.write("connected");
1193
- };
1194
- ws.onclose = function close(evt) {
1195
- // process.stdout.write("disconnected");
1196
- process.exit(evt.code);
1197
- return;
1198
- };
1199
- ws.onmessage = this.routeK8sWebSocketMessage;
1200
- // function incoming(msg: any) {
1201
- // let buf = Buffer.from(msg.data);
1202
- // // The k8s client prefixes the buffer with the stream number at position 0...
1203
- // let streamNumBuf = buf.readInt8();
1204
- // let payload = buf.toString('utf8', 1); // <-- start at pos 1 to skip the stream number.
1205
- // switch (streamNumBuf) {
1206
- // case WebSocketHandler.StdoutStream /* 1 */:
1207
- // process.stdout.write(payload);
1208
- // break;
1209
- // case WebSocketHandler.StderrStream /* 2 */:
1210
- // process.stderr.write(`ERROR: ` + payload);
1211
- // break;
1212
- // case WebSocketHandler.StatusStream /* 3 */:
1213
- // let k8sStatus = JSON.parse(payload) as V1Status;
1214
- // process.stdout.write(`STATUS: ${k8sStatus.status}: ${k8sStatus.message}`);
1215
- // break;
1216
- // default:
1217
- // process.stderr.write(`feedback on ${streamNumBuf}`)
1218
- // }
1219
- // return;
1220
- // };
1221
- // This never gets hit. Instead, onmessage gets hit with a message designated for stderr stream.
1222
- ws.onerror = function error(err) {
1223
- process.stdout.write(`Error: ${err.message}`);
1224
- ws.close();
1225
- };
1226
- // Gotta do a process.exit(code) to give the control back.
1227
- // THese dont fire
1228
- // ws.once('exit', (code) => process.exit(code));
1229
- // ws.once('end', (code) => process.stdout.write("end event fired"));
1230
- return;
1231
- }
1232
- catch (err) {
1233
- throw err;
1234
- }
1235
- });
1236
- }
1237
- /** Parses the stream number from the incoming message,
1238
- * and writes the data to the designated target stream.
1239
- *
1240
- * (The k8s client prefixes the buffer with the stream number at position 0)
1241
- */
1242
- routeK8sWebSocketMessage(msg) {
1243
- var _a;
1244
- let buf = Buffer.from(msg.data);
1245
- // The k8s client prefixes the buffer with the stream number at position 0...
1246
- let streamNumBuf = buf.readInt8();
1247
- let payload = buf.toString('utf8', 1); // <-- start at pos 1 to skip the stream number.
1248
- switch (streamNumBuf) {
1249
- case web_socket_handler_1.WebSocketHandler.StdoutStream /* 1 */:
1250
- process.stdout.write(payload);
1251
- break;
1252
- case web_socket_handler_1.WebSocketHandler.StderrStream /* 2 */:
1253
- process.stderr.write(`ERROR: ` + payload);
1254
- break;
1255
- case web_socket_handler_1.WebSocketHandler.StatusStream /* 3 */:
1256
- let k8sStatus = JSON.parse(payload);
1257
- if (((_a = k8sStatus.status) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "failure") {
1258
- if (k8sStatus.reason !== "NonZeroExitCode") {
1259
- process.stdout.write(`STATUS: ${k8sStatus.status}: ${k8sStatus.message}`);
1260
- }
1261
- }
1262
- break;
1263
- default:
1264
- process.stderr.write(`feedback on ${streamNumBuf}`);
1265
- }
1266
- return;
1267
- }
1268
- }
1269
- exports.default = AssetView;
1270
- AssetView.description = 'Renders a selected type of content for an asset';
1271
- AssetView.aliases = ['asset:monitor', "asset:mon", "asset:get"];
1272
- AssetView.flags = {
1273
- help: core_1.Flags.help({ char: 'h' }),
1274
- enterprise: core_1.Flags.string({ char: 'e', description: 'The name of the enterprise containing the asset being viewed.' }),
1275
- asset: core_1.Flags.string({ char: 'a', description: 'The name of the asset to view.' }),
1276
- environment: core_1.Flags.string({ char: 'n', description: 'The name of the environment in which the cabinet resides.' }),
1277
- cabinet: core_1.Flags.string({ char: 'c', description: 'The name of the cabinet from which the content is to be drawn.' }),
1278
- replica: core_1.Flags.string({ char: 'r', description: 'The name of one of the asset instances currently running in the cabinet.' }),
1279
- type: core_1.Flags.enum({ char: 't', options: [...Object.keys(AssetContentType)], description: 'The type of content to retrieve.' }),
1280
- terminal: core_1.Flags.enum({ options: ["bash", "sh"], description: 'Command used to start the terminal (defaults to "bash")' }),
1281
- logsFollow: core_1.Flags.boolean({ char: 'f', default: false, description: '(requires type=logs) Follow (aka watch, tail, stream) the output.' }),
1282
- logsTail: core_1.Flags.integer({ char: 'l', default: 10, description: '(requires type=logs) Lines of recent logs to include in the output. Enter -1 to include the entire log history stored in the container.' }),
1283
- configFile: core_1.Flags.string({ char: 'F', description: '(requires type=config) The root pathname to the config file to fetch.' }),
1284
- silent: core_1.Flags.boolean({ exclusive: ["echo", "toscript"], description: 'Non-Interactive mode; executes without any user interaction and fails on any missing or invalid arguments.' }),
1285
- echo: core_1.Flags.boolean({ exclusive: ["toscript", "silent"], description: 'Echo interaction mode; renders the equivalent non-interactive cli command for future use before final execution.' }),
1286
- toscript: core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Toscript interaction mode; renders the equivalent non-interactive cli command WITHOUT any execution.' }),
1287
- takeDefaults: core_1.Flags.boolean({ exclusive: ["silent"], description: "Prevents prompting for confirmation on parameters that were passed in or were set to default values." })
1288
- // tty: Flags.boolean({ char: 'i', default: false, description: '(requires type=exec) Specifies an interactive console session.' })
1289
- };
1290
- AssetView.strict = false; // disables argument validation so we can support variable-length arguments.
1291
- AssetView.args = [{ name: "cmd", description: '(requires type=exec) command and its space-separated arguments to run in the target replica.' }];
1292
- class ExecArgs {
1293
- constructor(command, tty = true) {
1294
- this.command = command;
1295
- this.tty = tty;
1296
- }
1297
- }
1298
- exports.ExecArgs = ExecArgs;
1299
- class ConfigFileArgs {
1300
- constructor(rootPathName) {
1301
- this.rootPathName = rootPathName;
1302
- }
1303
- }
1304
- exports.ConfigFileArgs = ConfigFileArgs;
1305
- class TermArgs {
1306
- /**
1307
- *
1308
- * @param terminalStartup The type of terminal to open. This command may change depending on what terminal or command shell types are available in the image.
1309
- */
1310
- constructor(terminalStartup) {
1311
- this.terminalStartup = terminalStartup;
1312
- }
1313
- }
1314
- exports.TermArgs = TermArgs;
1315
- /** Idnetifies a container, in a pod, in a namespace, in a cluster. */
1316
- class K8sContainerRef {
1317
- constructor(namespace, podName,
1318
- /** This should be optional. When there's only one container in a pod,
1319
- * we should be able to derive this from the pod spec. */
1320
- containerName) {
1321
- this.namespace = namespace;
1322
- this.podName = podName;
1323
- this.containerName = containerName;
1324
- }
1325
- }
1326
- exports.K8sContainerRef = K8sContainerRef;
1327
- class LogStreamer {
1328
- constructor(logger) {
1329
- this.logger = logger;
1330
- }
1331
- go(requestOptions, stream) {
1332
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1333
- return new Promise((resolve, reject) => {
1334
- const req = request(requestOptions, (error, response, body) => {
1335
- if (error) {
1336
- reject(error);
1337
- }
1338
- else if (response.statusCode !== 200) {
1339
- this.logger.detail(`Error connecting to log stream`, body);
1340
- let details;
1341
- try {
1342
- const k8sStatus = client_node_1.ObjectSerializer.deserialize(JSON.parse(body), 'V1Status');
1343
- details = `${k8sStatus.status}${k8sStatus.reason ? " (" + k8sStatus.reason + ")" : ""} ${k8sStatus.message}`;
1344
- }
1345
- catch (_a) {
1346
- details = "See cli log for details.";
1347
- }
1348
- reject(new Error(`Error connecting to log stream. ${details}`));
1349
- }
1350
- }).on('response', (response) => {
1351
- if (response.statusCode === 200) {
1352
- req.pipe(stream);
1353
- resolve(req);
1354
- }
1355
- });
1356
- });
1357
- });
1358
- }
1359
- }
1360
- exports.LogStreamer = LogStreamer;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogStreamer = exports.K8sContainerRef = exports.TermArgs = exports.ConfigFileArgs = exports.ExecArgs = exports.K8S_POD_PHASES = exports.InteractionModes = exports.AssetContentType = exports.PROMPT_ME_DESIGNATOR = void 0;
4
+ const tslib_1 = require("tslib");
5
+ //import * as path from 'path';
6
+ const stream = require("stream");
7
+ const core_1 = require("@oclif/core");
8
+ const _ = require("lodash");
9
+ const SplitCmd = require('split-cmd');
10
+ const request = require("request");
11
+ const semver = require("semver");
12
+ const k8s = require("@kubernetes/client-node");
13
+ const codiac_relay_contracts_1 = require("@codiac.io/codiac-relay-contracts");
14
+ const command_base_enterprise_1 = require("../../command-base-enterprise");
15
+ const render = require("../../uilogic/render-methods");
16
+ const cloud_provider_contextualizer_1 = require("../../uilogic/cloud-provider-contextualizer");
17
+ const client_node_1 = require("@kubernetes/client-node");
18
+ const web_socket_handler_1 = require("@kubernetes/client-node/dist/web-socket-handler");
19
+ const codiac_ops_common_1 = require("@codiac.io/codiac-ops-common");
20
+ // let logUpdate: any;
21
+ // (async function () {
22
+ // logUpdate = (await import("log-update")).default;
23
+ // })()
24
+ // import * as logUpdate from "log-update";
25
+ // import logUpdate from "log-update";
26
+ // const logUpdate = (await import("log-update/index.js")).default
27
+ // import { logUpdate } from "log-update";
28
+ // const logUpdate = require("log-update");
29
+ const log_update_wrapper_1 = require("../../log-update-wrapper");
30
+ const codiac_constants_1 = require("../../codiac-constants");
31
+ // const { selectFiles, COMPLETED, CANCELLED } = require('select-files-cli'); // gd js wo ts...
32
+ // const { selectFiles, COMPLETED, CANCELLED } = require('../../uilogic/file-selector'); // gd js wo ts...
33
+ /** The value provided as input that indicates
34
+ * a user's desire to be prompted with a list from which choose the value(s),
35
+ * instead of entering them manually or taking a default. */
36
+ exports.PROMPT_ME_DESIGNATOR = "?";
37
+ var AssetContentType;
38
+ (function (AssetContentType) {
39
+ AssetContentType["logs"] = "logs";
40
+ AssetContentType["term"] = "term";
41
+ AssetContentType["exec"] = "exec";
42
+ AssetContentType["env"] = "env";
43
+ AssetContentType["config"] = "config";
44
+ AssetContentType["status"] = "status";
45
+ // | "footprint-usage" | "infrx"
46
+ // | "ingress-domains" | "ingress-nslookup" | "ingress-routes" | "ingress-logs" | "ssl-certs" | "ssl-logs" | "ssl-cert-history";
47
+ })(AssetContentType = exports.AssetContentType || (exports.AssetContentType = {}));
48
+ const DEFAULT_TERMINAL_STARTER = "bash";
49
+ /** The quantity of lines of backlog to include in the log output. */
50
+ const DEFAULT_LOG_TAIL = 10;
51
+ var InteractionModes;
52
+ (function (InteractionModes) {
53
+ InteractionModes["echo"] = "echo";
54
+ InteractionModes["toscript"] = "toscript";
55
+ InteractionModes["silent"] = "silent";
56
+ })(InteractionModes = exports.InteractionModes || (exports.InteractionModes = {}));
57
+ /** This belongs to k8s - not us, but @kubernetes/client-node has no enum or constants for these magic strings...
58
+ *
59
+ * @see https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
60
+ */
61
+ var K8S_POD_PHASES;
62
+ (function (K8S_POD_PHASES) {
63
+ K8S_POD_PHASES["Pending"] = "Pending";
64
+ K8S_POD_PHASES["Running"] = "Running";
65
+ K8S_POD_PHASES["Succeeded"] = "Succeeded";
66
+ K8S_POD_PHASES["Failed"] = "Failed";
67
+ K8S_POD_PHASES["Unknown"] = "Unknown";
68
+ })(K8S_POD_PHASES = exports.K8S_POD_PHASES || (exports.K8S_POD_PHASES = {}));
69
+ class AssetView extends command_base_enterprise_1.CommandBaseEnterprise {
70
+ constructor() {
71
+ super(...arguments);
72
+ this.takeDefaults = false;
73
+ }
74
+ get uiCloudPvd() {
75
+ if (this._uiCloudPvd_backer === undefined) {
76
+ this._uiCloudPvd_backer = this.ioc.get(cloud_provider_contextualizer_1.CloudProviderContextualizer);
77
+ }
78
+ return this._uiCloudPvd_backer;
79
+ }
80
+ bootstrap() {
81
+ super.bootstrap();
82
+ cloud_provider_contextualizer_1.CloudProviderContextualizer.bootstrap(this.ioc); // (idempotent) this is a dependency of the configurators
83
+ }
84
+ run() {
85
+ var _a, _b, _c;
86
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
87
+ try {
88
+ // ==================================================
89
+ // 1. Bootstrap
90
+ // ==================================================
91
+ this.bootstrap();
92
+ // this._relayContainer?.ready$
93
+ // .subscribe(async (ready: boolean) => {
94
+ // ==================================================
95
+ // 2. Gather cli input
96
+ // ==================================================
97
+ const { args, flags } = yield this.parse(AssetView);
98
+ const interactionMode = (_b = (_a = (flags.echo ? InteractionModes.echo : undefined)) !== null && _a !== void 0 ? _a : (flags.toscript ? InteractionModes.toscript : undefined)) !== null && _b !== void 0 ? _b : (flags.silent ? InteractionModes.silent : undefined);
99
+ this.takeDefaults = (_c = flags.takeDefaults) !== null && _c !== void 0 ? _c : false;
100
+ let partialReq = {};
101
+ partialReq.enterprise = flags.enterprise;
102
+ partialReq.asset = flags.asset;
103
+ partialReq.environment = flags.environment;
104
+ partialReq.cabinet = flags.cabinet;
105
+ partialReq.content = (flags.type) ? AssetContentType[flags.type] : undefined;
106
+ partialReq.replica = flags.replica;
107
+ let givenCmd;
108
+ if (args.cmd) {
109
+ givenCmd = args.cmd;
110
+ let isep = this.argv.indexOf("--");
111
+ if (isep >= 0) {
112
+ if (isep + 1 < this.argv.length) {
113
+ givenCmd = this.argv.slice(isep + 1);
114
+ }
115
+ else {
116
+ givenCmd = undefined;
117
+ }
118
+ }
119
+ }
120
+ let contentOptions = {
121
+ follow: flags.logsFollow,
122
+ tailLines: flags.logsTail,
123
+ /* tty: flags.tty, */
124
+ command: givenCmd,
125
+ terminalStartup: flags.terminal,
126
+ rootPathName: flags.configFile
127
+ };
128
+ // ==================================================
129
+ // 3. Assemble candidate
130
+ // ==================================================
131
+ let candidate;
132
+ let cmd;
133
+ if (interactionMode == InteractionModes.silent) {
134
+ candidate = yield this.buildCandidate_silently(partialReq, partialReq.content, contentOptions);
135
+ }
136
+ else {
137
+ [candidate, cmd] = yield this.buildCandidate_interactively(partialReq, contentOptions, partialReq.content);
138
+ }
139
+ // ==================================================
140
+ // 4. Render ultimate command string
141
+ // ==================================================
142
+ if (interactionMode == InteractionModes.echo || interactionMode == InteractionModes.toscript) {
143
+ if (cmd && cmd.length > 0) {
144
+ this._ui.userMessage(cmd.join(" "));
145
+ }
146
+ }
147
+ // ==================================================
148
+ // 5. Execute
149
+ // ==================================================
150
+ if (interactionMode != InteractionModes.toscript) {
151
+ yield this.renderSelectedContent(candidate.context, candidate.contentType, candidate.k8sEntities, candidate.contentOptions, candidate.replicas);
152
+ }
153
+ // return;
154
+ // });
155
+ return;
156
+ }
157
+ catch (err) {
158
+ this.handleError(err);
159
+ throw err;
160
+ }
161
+ });
162
+ }
163
+ buildCandidate_silently(partialReq, content, contentOptions) {
164
+ var _a, _b, _c, _d, _e, _f;
165
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
166
+ this.__ui = new codiac_ops_common_1.ThrowingUserInputProvider(this.logger);
167
+ if (content === undefined || _.isEmpty(partialReq.content))
168
+ throw new Error(`No content type specified.`);
169
+ if (partialReq.enterprise === undefined || _.isEmpty(partialReq.enterprise))
170
+ throw new Error(`No enterprise specified.`);
171
+ if (partialReq.asset === undefined || _.isEmpty(partialReq.asset))
172
+ throw new Error(`No asset specified.`);
173
+ if (partialReq.environment === undefined || _.isEmpty(partialReq.environment))
174
+ throw new Error(`No environment specified.`);
175
+ if (partialReq.cabinet === undefined || _.isEmpty(partialReq.cabinet))
176
+ throw new Error(`No cabinet specified.`);
177
+ // Replica should not be required
178
+ // (though this can be confusing when there's more than one;
179
+ // the user will have to know they're only getting a single replica of logs,
180
+ // and they need to know they might have to call out for one.
181
+ // if (partialReq.replica === undefined || _.isEmpty(partialReq.replica)) throw new Error(`No replica specified.`);
182
+ let options;
183
+ switch (partialReq.content) {
184
+ case AssetContentType.logs:
185
+ options = (contentOptions !== null && contentOptions !== void 0 ? contentOptions : {});
186
+ // defaults?
187
+ break;
188
+ case AssetContentType.exec:
189
+ if (_.isEmpty(contentOptions.command))
190
+ throw new Error(`No command specified.`);
191
+ options = {
192
+ command: contentOptions.command,
193
+ tty: (_a = contentOptions.tty) !== null && _a !== void 0 ? _a : false
194
+ };
195
+ break;
196
+ case AssetContentType.config:
197
+ if (_.isEmpty(contentOptions.rootPathName))
198
+ throw new Error(`No file specified.`);
199
+ options = {
200
+ rootPathName: contentOptions.rootPathName
201
+ };
202
+ break;
203
+ case AssetContentType.term:
204
+ options = {
205
+ terminalStartup: (_b = contentOptions.terminalStartup) !== null && _b !== void 0 ? _b : DEFAULT_TERMINAL_STARTER
206
+ };
207
+ break;
208
+ case AssetContentType.env: /* env has no user input */
209
+ default:
210
+ options = {};
211
+ break;
212
+ }
213
+ // Retrieve the list of replicas for the given cabinet.
214
+ let rootMap = yield this.getRootMap(partialReq.enterprise);
215
+ let env = this.deriveEnvironmentFrom(partialReq.enterprise, partialReq.cabinet, rootMap); // this is fkng stupid. Put this value into the cab value
216
+ let cabObj = this.getCabinetInfrx(partialReq.enterprise, env.name, partialReq.cabinet, rootMap);
217
+ if (cabObj.infrx == undefined || _.isEmpty(cabObj.infrx))
218
+ throw new Error(`Cannot connect to cabinet ${cabObj.name}: it has no infrastructure record.`);
219
+ let k8sObj = { namespace: cabObj.infrx.namespace };
220
+ let replicas = yield this.fetchReplicas(partialReq, cabObj.infrx.namespace);
221
+ if (replicas.length > 0) {
222
+ // Set first as default
223
+ partialReq.replica = (_d = (_c = replicas[0].metadata) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : "unnamed";
224
+ k8sObj = {
225
+ namespace: cabObj.infrx.namespace,
226
+ pod: partialReq.replica,
227
+ container: (_f = (_e = replicas[0].spec) === null || _e === void 0 ? void 0 : _e.containers[0].name) !== null && _f !== void 0 ? _f : "unnamed"
228
+ };
229
+ // Select a replica unless it's an asset-level operation
230
+ if (content !== AssetContentType.status) {
231
+ // This method falls back to first found as default, throws if not enough info is provided
232
+ k8sObj = yield this.promptForReplica(replicas, undefined, partialReq.replica);
233
+ partialReq.replica = k8sObj.pod;
234
+ }
235
+ }
236
+ // Assemble
237
+ let candidate = {
238
+ context: {
239
+ enterprise: partialReq.enterprise,
240
+ environment: partialReq.environment,
241
+ asset: partialReq.asset,
242
+ cabinet: partialReq.cabinet,
243
+ replica: partialReq.replica
244
+ },
245
+ contentType: content,
246
+ contentOptions: options,
247
+ k8sEntities: k8sObj,
248
+ replicas: replicas
249
+ };
250
+ return candidate;
251
+ });
252
+ }
253
+ buildCandidate_interactively(partialReq, contentOptions, content) {
254
+ var _a, _b, _c, _d;
255
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
256
+ this._userCntx = yield this.establishTenantContext(this._userCntx);
257
+ let enterprise = (yield this.establishEnterpriseContext()).enterprise;
258
+ partialReq.enterprise = enterprise.code;
259
+ let rootMap = yield this.getRootMap(enterprise.code);
260
+ let replicas;
261
+ let k8sObj;
262
+ let confirmed = false;
263
+ let optionsArgs = [];
264
+ do {
265
+ // 1. Select Asset
266
+ partialReq.asset = yield this.promptForAsset(enterprise.assets, partialReq.asset);
267
+ // 2. Cabinet
268
+ let cabObj = yield this.promptForCabinet(partialReq.enterprise, rootMap, partialReq.cabinet);
269
+ partialReq.cabinet = cabObj.name;
270
+ partialReq.environment = this.deriveEnvironmentFrom(partialReq.enterprise, partialReq.cabinet, rootMap).name;
271
+ let cluster = this.deriveClusterFrom(partialReq.enterprise, partialReq.environment, partialReq.cabinet, rootMap);
272
+ // partialReq.cabinet = await this.establishCabinetContext(partialReq.cabinet);
273
+ if (cabObj.infrx == undefined || _.isEmpty(cabObj.infrx))
274
+ throw new Error(`Cannot connect to cabinet ${cabObj.name}: it has no infrastructure record.`);
275
+ k8sObj = { namespace: cabObj.infrx.namespace };
276
+ // 3. Content type
277
+ content = yield this.promptForContentType(content);
278
+ // 4. Content-specific arguments
279
+ // MarkStartHere("implement prompt-me designator.")
280
+ // MarkStartHere("Support the current logger or ioc ctr inside the ws event handlers");
281
+ // MarkStartHere("Need UI to operate a different stream than stdout (so piping stdout wont include the ui content");
282
+ [contentOptions, optionsArgs] = yield this.promptForContentOptions(content, partialReq, contentOptions);
283
+ // 5. Authenticate with CSP
284
+ this.uiCloudPvd.takeDefaults = this.takeDefaults;
285
+ yield this.uiCloudPvd.promptForCloudProviderCreds(this.ioc, cluster.provider);
286
+ // 6. Replica (Pod)
287
+ if (cabObj.infrx == undefined || _.isEmpty(cabObj.infrx))
288
+ throw new Error(`Cannot connect to cabinet ${cabObj.name}: it has no infrastructure record.`);
289
+ replicas = yield this.fetchReplicas(partialReq, cabObj.infrx.namespace);
290
+ if (replicas.length > 0) {
291
+ // Set first as default
292
+ partialReq.replica = (_b = (_a = replicas[0].metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
293
+ k8sObj = {
294
+ namespace: cabObj.infrx.namespace,
295
+ pod: partialReq.replica,
296
+ container: (_d = (_c = replicas[0].spec) === null || _c === void 0 ? void 0 : _c.containers[0].name) !== null && _d !== void 0 ? _d : "unnamed"
297
+ };
298
+ // Select a replica unless it's an asset-level operation
299
+ if (content !== AssetContentType.status) {
300
+ k8sObj = yield this.promptForReplica(replicas, undefined, partialReq.replica);
301
+ partialReq.replica = k8sObj.pod;
302
+ }
303
+ }
304
+ // 7. Confirm or loop back around to enterprise
305
+ confirmed = true; // This is a readonly ui (no danger), and we want to enable fast switching among diff content types, so let's not waste time confirming. // await this._ui.promptConfirm("confirm", "Apply? ");
306
+ } while (!confirmed);
307
+ // We're hard-coding instead of casting here to validate at build-time that each partial property is fully-hydrated.
308
+ // Assemble
309
+ let candidate = {
310
+ context: {
311
+ enterprise: partialReq.enterprise,
312
+ environment: partialReq.environment,
313
+ asset: partialReq.asset,
314
+ cabinet: partialReq.cabinet,
315
+ replica: partialReq.replica
316
+ },
317
+ contentType: content,
318
+ contentOptions: contentOptions,
319
+ k8sEntities: k8sObj,
320
+ replicas: replicas
321
+ };
322
+ // Build command string
323
+ let cmd = ["cod", "asset", "view"];
324
+ cmd.push("--silent");
325
+ cmd.push("-e", candidate.context.enterprise);
326
+ cmd.push("-a", candidate.context.asset);
327
+ cmd.push("-n", candidate.context.environment);
328
+ cmd.push("-c", candidate.context.cabinet);
329
+ if (candidate.context.replica)
330
+ cmd.push("-r", candidate.context.replica);
331
+ cmd.push("-t", candidate.contentType);
332
+ cmd.push(...optionsArgs);
333
+ return [candidate, cmd];
334
+ });
335
+ }
336
+ promptForContentOptions(contentType, context, defaults) {
337
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
338
+ let cmdArgs = [];
339
+ try {
340
+ switch (contentType) {
341
+ case AssetContentType.logs:
342
+ let logArgs = yield this.promptForLogOptions(defaults);
343
+ if (logArgs.follow)
344
+ cmdArgs.push("-f");
345
+ if (logArgs.tailLines)
346
+ cmdArgs.push(...["-l", "" + logArgs.tailLines]);
347
+ return [logArgs, cmdArgs];
348
+ case AssetContentType.exec:
349
+ let execArgs = yield this.promptForExecOptions(defaults);
350
+ cmdArgs.push(...execArgs.command);
351
+ return [execArgs, cmdArgs];
352
+ case AssetContentType.config:
353
+ this.enterpriseContextor.takeDefaults = this.takeDefaults;
354
+ let rootPathName = (yield this.enterpriseContextor.promptForTargetFile(context.enterprise, context.asset, defaults === null || defaults === void 0 ? void 0 : defaults.rootPathName));
355
+ let cfgArgs = { rootPathName: rootPathName };
356
+ cmdArgs.push("-F", rootPathName);
357
+ return [cfgArgs, cmdArgs];
358
+ case AssetContentType.term:
359
+ let termArgs = yield this.promptForTerminalOptions(defaults);
360
+ if (termArgs.terminalStartup)
361
+ cmdArgs.push(...["--terminal", termArgs.terminalStartup]);
362
+ return [termArgs, cmdArgs];
363
+ default:
364
+ return [{}, []];
365
+ }
366
+ }
367
+ catch (err) {
368
+ throw err;
369
+ }
370
+ });
371
+ }
372
+ promptForLogOptions(defaults) {
373
+ var _a, _b;
374
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
375
+ let options = (defaults !== null && defaults !== void 0 ? defaults : {});
376
+ options.follow = (_a = options.follow) !== null && _a !== void 0 ? _a : true;
377
+ if (!this.takeDefaults) {
378
+ options.follow = yield this._ui.promptConfirm("follow", "Stream logs? ", options.follow);
379
+ }
380
+ options.tailLines = (_b = options.tailLines) !== null && _b !== void 0 ? _b : DEFAULT_LOG_TAIL;
381
+ if (!this.takeDefaults) {
382
+ options.tailLines = yield this._ui.prompt("tail", "Lines of backlog (-1 for all):", true, options.tailLines);
383
+ }
384
+ return options;
385
+ });
386
+ }
387
+ promptForExecOptions(defaults) {
388
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
389
+ let options = (defaults !== null && defaults !== void 0 ? defaults : {});
390
+ // Command
391
+ let cmdStr;
392
+ let keep = this.takeDefaults;
393
+ if (!_.isEmpty(options.command) && !this.takeDefaults) {
394
+ cmdStr = (typeof options.command === 'string') ? options.command : options.command.join(" ");
395
+ keep = yield this._ui.promptConfirm("keepCommand", `Command: ${this._styler.hilite(cmdStr)} `);
396
+ }
397
+ if (keep && !_.isEmpty(options.command)) {
398
+ // do nothing
399
+ }
400
+ else {
401
+ options.command = (yield this._ui.prompt("command", "Command: ", true, cmdStr));
402
+ options.command = SplitCmd.split(options.command); // no types declarations - f#$&*ing script kiddie.
403
+ // the one above trips on the --output flag in this: kubectl get pods -n cod-zombie-v1 -l assetNamme=codiac-api --output=jsonpath="{.items[*]['metadata.name', 'status.capacity']}"
404
+ // something safer than: options.command = options.command.split(" ");
405
+ }
406
+ return options;
407
+ });
408
+ }
409
+ promptForTerminalOptions(defaults) {
410
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
411
+ let options = (defaults !== null && defaults !== void 0 ? defaults : {});
412
+ // Command
413
+ let keep = this.takeDefaults;
414
+ if (!_.isEmpty(options.terminalStartup) && !this.takeDefaults) {
415
+ keep = yield this._ui.promptConfirm("keepStartup", `Terminal Startup: ${this._styler.hilite(options.terminalStartup)} `);
416
+ }
417
+ if (keep && !_.isEmpty(options.terminalStartup)) {
418
+ // do nothing
419
+ }
420
+ else {
421
+ options.terminalStartup = (yield this._ui.prompt("startup", "Terminal Startup: ", true, options.terminalStartup));
422
+ }
423
+ return options;
424
+ });
425
+ }
426
+ promptForContentType(defaultValue) {
427
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
428
+ try {
429
+ let output;
430
+ let choices = Object.keys(AssetContentType);
431
+ let keep = this.takeDefaults;
432
+ if (defaultValue && choices.find(x => x == defaultValue) && !this.takeDefaults) {
433
+ keep = yield this._ui.promptConfirm("keepType", `Type of content: ${this._styler.hilite(defaultValue)} `);
434
+ }
435
+ if (keep && defaultValue !== undefined) {
436
+ output = defaultValue;
437
+ }
438
+ else {
439
+ output = (yield this._ui.promptSelect("type", "Type of content: ", choices));
440
+ }
441
+ return output;
442
+ }
443
+ catch (err) {
444
+ throw err;
445
+ }
446
+ });
447
+ }
448
+ promptForAsset(assets, defaultValue) {
449
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
450
+ try {
451
+ let output;
452
+ let choices = assets.map(a => { return { name: a.name, value: a.name }; });
453
+ choices = _.orderBy(choices, c => c.name);
454
+ /** If we changed the input they provided, we need their confirmation (whether or not they said takeDefaults) */
455
+ let changedUserInput = false;
456
+ if (choices.length === 1) {
457
+ if (defaultValue != choices[0].value) {
458
+ changedUserInput = !_.isEmpty(defaultValue);
459
+ defaultValue = choices[0].value;
460
+ }
461
+ }
462
+ let keep = this.takeDefaults;
463
+ if (defaultValue && choices.find(x => x.value == defaultValue) && (changedUserInput || !this.takeDefaults)) {
464
+ keep = yield this._ui.promptConfirm("keepAsset", `Asset: ${this._styler.hilite(defaultValue)} `);
465
+ }
466
+ if (keep && defaultValue !== undefined) {
467
+ output = defaultValue;
468
+ }
469
+ else {
470
+ output = (yield this._ui.promptSelect("asset", "Asset: ", choices));
471
+ }
472
+ return output;
473
+ }
474
+ catch (err) {
475
+ throw err;
476
+ }
477
+ });
478
+ }
479
+ promptForCabinet(enterprise, rootMap, defaultValue) {
480
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
481
+ try {
482
+ let output;
483
+ // render cab tree with all lines selectable
484
+ let cabTree = this.buildCabinetTree(rootMap);
485
+ let choices = this.buildSelectChoicesFrom(cabTree);
486
+ // ISSUES:
487
+ // 0. Remove the freaking lines from the selected value.
488
+ // 1. Remember the last cabinet (user's enterprise context).
489
+ // 2. We should only render the cabinets that actually contain a deployment of the asset (or dim the others and loop back if selected)
490
+ // 3. The picklist should render the cluster (provider, name, location)
491
+ // 4. PERHAPS? The version of the asset running in the selected cabinet should get rendered (either in the picklist or after the cab is selected)
492
+ /** If we changed the input they provided, we need their confirmation (whether or not they said takeDefaults) */
493
+ const CAB_PREFIX = "cabinet|";
494
+ let cabChoices = choices.filter(c => c.value.startsWith(CAB_PREFIX));
495
+ let changedUserInput = false;
496
+ if (cabChoices.length === 1) {
497
+ if (defaultValue != cabChoices[0].value.slice(CAB_PREFIX.length)) {
498
+ changedUserInput = !_.isEmpty(defaultValue);
499
+ defaultValue = cabChoices[0].value.slice(CAB_PREFIX.length);
500
+ }
501
+ }
502
+ let keep = this.takeDefaults;
503
+ if (defaultValue && Boolean(choices.find(x => x.value === `${CAB_PREFIX}${defaultValue}`)) && (changedUserInput || !this.takeDefaults)) {
504
+ keep = yield this._ui.promptConfirm("keepCabinet", `Cabinet: ${this._styler.hilite(defaultValue)} `);
505
+ }
506
+ if (keep && defaultValue !== undefined) {
507
+ output = defaultValue;
508
+ }
509
+ else {
510
+ let scope;
511
+ let target;
512
+ do {
513
+ if (scope === "environment") {
514
+ // we could just filter it down from here...
515
+ }
516
+ let selection = (yield this._ui.promptSelect("cabinet", "Cabinet: ", choices, false, false));
517
+ let parts = selection.split("|");
518
+ scope = parts[0];
519
+ target = parts[1];
520
+ } while (scope !== "cabinet"); // ensure they select a cabinet
521
+ output = target;
522
+ }
523
+ let env = this.deriveEnvironmentFrom(enterprise, output, rootMap); // this is fkng stupid. Put this value into the cab value
524
+ let cabObj = this.getCabinetInfrx(enterprise, env.name, output, rootMap);
525
+ // return output;
526
+ return cabObj;
527
+ }
528
+ catch (err) {
529
+ throw (err);
530
+ }
531
+ });
532
+ }
533
+ deriveEnvironmentFrom(enterprise, cabinet, rootMap) {
534
+ try {
535
+ let ent = rootMap.enterprises.find(e => e.name === enterprise);
536
+ if (ent === undefined)
537
+ throw new Error(`Cannot find environment: did not recognize enterprise [${enterprise}]`);
538
+ let enviro = ent.environments.find(x => x.cabinets.find(c => c.name === cabinet));
539
+ if (enviro === undefined)
540
+ throw new Error(`Cannot find environment: did not recognize cabinet [${cabinet}]`);
541
+ return enviro;
542
+ }
543
+ catch (err) {
544
+ throw err;
545
+ }
546
+ }
547
+ deriveClusterFrom(enterprise, environment, cabinet, rootMap) {
548
+ try {
549
+ let ent = rootMap.enterprises.find(e => e.name === enterprise);
550
+ if (ent === undefined)
551
+ throw new Error(`Cannot find cluster: did not recognize enterprise [${enterprise}]`);
552
+ let enviro = ent.environments.find(x => x.cabinets.find(c => c.name === cabinet));
553
+ if (enviro === undefined)
554
+ throw new Error(`Cannot find cluster: did not recognize cabinet [${cabinet}]`);
555
+ let cabObj = enviro.cabinets.find(c => c.name === cabinet);
556
+ if (cabObj == undefined)
557
+ throw new Error(`Cannot find cluster: did not recognize cabinet [${cabinet}]`);
558
+ if (cabObj.cluster == undefined)
559
+ throw new Error(`Cannot find cluster: cabinet [${cabinet}] does not have a cluster specified.`);
560
+ let cluster = rootMap.clusters.find(c => c.name == cabObj.cluster);
561
+ if (cluster == undefined)
562
+ throw new Error(`Did not recognize cluster [${cabObj.cluster}]`);
563
+ return cluster;
564
+ }
565
+ catch (err) {
566
+ throw err;
567
+ }
568
+ }
569
+ buildSelectChoicesFrom(tree) {
570
+ try {
571
+ let choices = [];
572
+ // the value is no good here - need scope and target both available
573
+ render.renderStringTree(tree, (txt, item) => choices.push({ name: txt, value: item.value }));
574
+ // // This is one way to do it
575
+ // for (let item of tree) {
576
+ //
577
+ // let thisChoice: PromptChoice = { name: item.text, value: item.text };
578
+ // choices.push(thisChoice);
579
+ //
580
+ // if (item.children && item.children.length > 0) {
581
+ // let children = this.buildSelectChoicesFrom(item.children);
582
+ // choices.push(...children);
583
+ // }
584
+ // }
585
+ return choices;
586
+ }
587
+ catch (err) {
588
+ throw err;
589
+ }
590
+ }
591
+ /** sets each value to "scope|target".
592
+ *
593
+ * This is MOSTLY a COPY-PASTE from the CabinetList command!!! This view is prob gonna be pretty common - consider promoting it to a shared utility. */
594
+ buildCabinetTree(rootMap, existings) {
595
+ var _a, _b, _c, _d;
596
+ let tree = [];
597
+ for (let ent of rootMap.enterprises) {
598
+ let entBranch = { text: `${ent.name} enterprise:`, value: `${codiac_relay_contracts_1.ScopeLevel.enterprise}|${ent.name}` };
599
+ let entSetting = existings === null || existings === void 0 ? void 0 : existings.find(s => s.scope === codiac_relay_contracts_1.ScopeLevel.enterprise && s.target === ent.name);
600
+ if (entSetting !== undefined) {
601
+ let valueSuffix = this.ellipsis(35, (_a = entSetting.value) !== null && _a !== void 0 ? _a : "[set to undefined]");
602
+ valueSuffix = `(${valueSuffix})`;
603
+ entBranch.text = entBranch.text.concat(" ", this._styler.dim(valueSuffix));
604
+ }
605
+ for (let env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
606
+ let envBranch = { text: `${env.name}`, value: `${codiac_relay_contracts_1.ScopeLevel.environment}|${env.name}` };
607
+ let envSetting = existings === null || existings === void 0 ? void 0 : existings.find(s => s.scope === codiac_relay_contracts_1.ScopeLevel.environment && s.target === env.name);
608
+ if (envSetting !== undefined) {
609
+ let valueSuffix = this.ellipsis(35, (_b = envSetting.value) !== null && _b !== void 0 ? _b : "[set to undefined]");
610
+ valueSuffix = `(${valueSuffix})`;
611
+ envBranch.text = envBranch.text.concat(" ", this._styler.dim(valueSuffix));
612
+ }
613
+ for (let cab of env.cabinets) {
614
+ // let cwg = rootMap.clusters.find(c => c.name === cab.cluster);
615
+ // let clusterDesc = cwg ? ` (${cab.cluster}, ${cwg.provider} ${cwg.locationName})` : "";
616
+ let cabBranch = {
617
+ text: `${cab.name}`,
618
+ value: `${codiac_relay_contracts_1.ScopeLevel.cabinet}|${cab.name}`
619
+ };
620
+ let cabSetting = existings === null || existings === void 0 ? void 0 : existings.find(s => s.scope === codiac_relay_contracts_1.ScopeLevel.cabinet && s.target === cab.name);
621
+ if (cabSetting !== undefined) {
622
+ let valueSuffix = this.ellipsis(35, (_c = cabSetting.value) !== null && _c !== void 0 ? _c : "[set to undefined]");
623
+ valueSuffix = `(${valueSuffix})`;
624
+ cabBranch.text = cabBranch.text.concat(" ", this._styler.dim(valueSuffix));
625
+ }
626
+ if (envBranch.children === undefined)
627
+ envBranch.children = [];
628
+ (_d = envBranch.children) === null || _d === void 0 ? void 0 : _d.push(cabBranch);
629
+ }
630
+ if (entBranch.children === undefined)
631
+ entBranch.children = [];
632
+ entBranch.children.push(envBranch);
633
+ }
634
+ tree.push(entBranch);
635
+ }
636
+ return tree;
637
+ }
638
+ /** Truncates the string to the given length with an ellipses as suffix */
639
+ ellipsis(maxLength, value) {
640
+ let output = value;
641
+ if (output.length > maxLength) {
642
+ let ellipsis = "..."; // Rather use the ellipsis character but String.fromCharCode(133) is returning a problematic character.
643
+ output = output.slice(0, maxLength - 1 - ellipsis.length).concat(ellipsis);
644
+ }
645
+ return output;
646
+ }
647
+ /**
648
+ *
649
+ * @param enterprise
650
+ * @param environment
651
+ * @param cabinet
652
+ * @param asset
653
+ * @param ctrInPod (Optional, defaults to the first one in the spec) The name of the running container (not the image) inside the pod (relevant only when there's more than one).
654
+ * @param defaultValue
655
+ * @returns
656
+ */
657
+ promptForReplica(replicas, ctrInPod, defaultValue) {
658
+ var _a, _b, _c, _d, _e;
659
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
660
+ try {
661
+ let podName;
662
+ // params: enterprise: string, environment: string, cabinet: string, asset: string
663
+ // // Retrieve replicas
664
+ // this._ui.startSpinner(`Fetching ${asset} replicas in ${environment}/${cabinet}...`)
665
+ // let reps = await this.genRelayClient.Call.assetStatus({ assetName: asset, cabinetName: cabinet, enterpriseCode: enterprise, environment: environment });
666
+ // this._ui.stopSpinner((reps.successes) ? `${reps.successes.length} found.` : "failed.")
667
+ // if (reps.error) throw reps.error;
668
+ // if (reps.successes == undefined || reps.successes.length === 0) throw new Error(`No ${asset} replicas exist in cabinet ${environment}/${cabinet}. ${reps.message ?? ""}`);
669
+ //
670
+ // let replicas = reps.successes[0].currentVersion.pods; // <--- HEY!!! Relay shouldnt be exposing raw k8s contracts here - this shd be a codiac contract
671
+ let choices = replicas.filter(r => { var _a; return ((_a = r.metadata) === null || _a === void 0 ? void 0 : _a.name) !== undefined; })
672
+ .map(r => { var _a, _b, _c; return ({ name: `${(_a = r.metadata.name) !== null && _a !== void 0 ? _a : ""} (${(_b = r.status) === null || _b === void 0 ? void 0 : _b.phase})`, value: (_c = r.metadata.name) !== null && _c !== void 0 ? _c : "" }); });
673
+ // Select a replica...
674
+ if (choices.length === 0) {
675
+ this._ui.userMessage(`No replicas found.`);
676
+ podName = "unknown";
677
+ // return undefined; // <--- this is what we should do here.
678
+ }
679
+ else if (choices.length === 1) {
680
+ podName = choices[0].value;
681
+ this._ui.userMessage(`1 replica found: ${this._styler.hilite(podName)}`);
682
+ }
683
+ else {
684
+ let keep = this.takeDefaults;
685
+ if (defaultValue && Boolean(choices.find(x => x.value === defaultValue)) && !this.takeDefaults) {
686
+ keep = yield this._ui.promptConfirm("keepReplica", `Replica: ${this._styler.hilite(defaultValue)} `);
687
+ }
688
+ if (keep && defaultValue !== undefined) {
689
+ podName = defaultValue;
690
+ }
691
+ else {
692
+ podName = (yield this._ui.promptSelect("replica", "Replica...", choices, false, false)); // Assertion operator ok here - we're not allowing undefined options.
693
+ }
694
+ }
695
+ let replica = (replicas.find(r => { var _a; return ((_a = r.metadata) === null || _a === void 0 ? void 0 : _a.name) === podName; })); // Assertion ok: selection was already limited to this list.
696
+ // Select the container inside...
697
+ let containerName;
698
+ if ((((_a = replica.spec) === null || _a === void 0 ? void 0 : _a.containers) == undefined) || (((_b = replica.spec) === null || _b === void 0 ? void 0 : _b.containers.length) === 0))
699
+ throw new Error("No containers are specified in that replica");
700
+ if (!_.isEmpty(ctrInPod)) {
701
+ let found = replica.spec.containers.find(c => c.name === ctrInPod);
702
+ if (!found)
703
+ throw new Error(`Container [${ctrInPod}] not found in that replica`);
704
+ containerName = found.name;
705
+ }
706
+ else {
707
+ containerName = replica.spec.containers[0].name;
708
+ if (((_c = replica.spec) === null || _c === void 0 ? void 0 : _c.containers.length) > 1) {
709
+ // TODO: promptSelect from the list of containers
710
+ this._ui.userMessage(`${(_d = replica.spec) === null || _d === void 0 ? void 0 : _d.containers.length} containers in that replica; selected ${containerName}`);
711
+ }
712
+ }
713
+ let k8sCtr = {
714
+ namespace: (_e = replica.metadata) === null || _e === void 0 ? void 0 : _e.namespace,
715
+ pod: podName,
716
+ container: containerName
717
+ };
718
+ return k8sCtr;
719
+ }
720
+ catch (err) {
721
+ throw err;
722
+ }
723
+ });
724
+ }
725
+ renderSelectedContent(context, contentType, k8sEntities, contentOptions, replicas) {
726
+ var _a;
727
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
728
+ try {
729
+ switch (contentType) {
730
+ case (AssetContentType.logs):
731
+ if (context.replica == undefined)
732
+ throw new Error("No replica selected.");
733
+ if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
734
+ throw new Error("No replica selected.");
735
+ yield this.showLogs(context, contentOptions);
736
+ break;
737
+ case (AssetContentType.term):
738
+ if (context.replica == undefined)
739
+ throw new Error("No replica selected.");
740
+ if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
741
+ throw new Error("No replica selected.");
742
+ let termArgs = { tty: true, command: (_a = contentOptions === null || contentOptions === void 0 ? void 0 : contentOptions.terminalStartup) !== null && _a !== void 0 ? _a : DEFAULT_TERMINAL_STARTER };
743
+ yield this.runExec(context, termArgs, k8sEntities);
744
+ break;
745
+ case (AssetContentType.exec):
746
+ if (context.replica == undefined)
747
+ throw new Error("No replica selected.");
748
+ if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
749
+ throw new Error("No replica selected.");
750
+ let execArgs = contentOptions;
751
+ execArgs.tty = false; // and we want a run-once behavior so the ws closes after the command completes.
752
+ yield this.runExec(context, execArgs, k8sEntities);
753
+ break;
754
+ case (AssetContentType.config):
755
+ if (context.replica == undefined)
756
+ throw new Error("No replica selected.");
757
+ if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
758
+ throw new Error("No replica selected.");
759
+ let cfgInput = contentOptions;
760
+ if (!cfgInput.rootPathName.startsWith("/"))
761
+ cfgInput.rootPathName = "/".concat(cfgInput.rootPathName);
762
+ let cfgExec = { tty: false, command: ["cat", cfgInput.rootPathName] };
763
+ yield this.runExec(context, cfgExec, k8sEntities);
764
+ break;
765
+ case (AssetContentType.env):
766
+ if (context.replica == undefined)
767
+ throw new Error("No replica selected.");
768
+ if (k8sEntities.pod == undefined || k8sEntities.container == undefined)
769
+ throw new Error("No replica selected.");
770
+ let envArgs = { tty: false, command: "env" };
771
+ yield this.runExec(context, envArgs, k8sEntities);
772
+ break;
773
+ case (AssetContentType.status):
774
+ // await this.watchEvents(context, k8sEntities.namespace, replicas);
775
+ yield this.watchStatus_NEW(context, k8sEntities.namespace, replicas);
776
+ // await this.watchStatus(context, k8sEntities.namespace, replicas);
777
+ // await this.watchReplicaSet(context, k8sEntities.namespace);
778
+ // await this.showStatus(context, k8sEntities.namespace, replicas);
779
+ break;
780
+ default:
781
+ this.logger.debug(`Content type ${contentType} is not yet supported.`, [context, contentType, contentOptions]);
782
+ this._ui.userMessage(`Content type ${contentType} is not yet supported.`);
783
+ }
784
+ return;
785
+ }
786
+ catch (err) {
787
+ throw (err);
788
+ }
789
+ });
790
+ }
791
+ getKubeConfig(context) {
792
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
793
+ // Retrieve cluster connection specs
794
+ let res = yield this.genRelayClient.Call.getClusterConnectionSpecs({
795
+ enterprise: context.enterprise,
796
+ environment: context.environment,
797
+ cabinet: context.cabinet
798
+ });
799
+ if (res.error)
800
+ throw res.error;
801
+ if (res.output == undefined || _.isEmpty(res.output)) {
802
+ this.log(`Failed loading cluster spec: ${res.message}.`);
803
+ throw new Error(`Failed loading cluster spec: ${res.message}.`);
804
+ }
805
+ // Create the k8s client
806
+ let k8sConfig = new client_node_1.KubeConfig();
807
+ k8sConfig.loadFromString(res.output);
808
+ return k8sConfig;
809
+ });
810
+ }
811
+ getK8sClient(context, kube) {
812
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
813
+ let k8sConfig = kube !== null && kube !== void 0 ? kube : (yield this.getKubeConfig(context));
814
+ let theirApi = k8sConfig.makeApiClient(k8s.CoreV1Api);
815
+ return theirApi;
816
+ });
817
+ }
818
+ /** Gets the cluster cnxn specs from the relay, then makes the k8s call from the cli.
819
+ *
820
+ * Throws any errors. */
821
+ fetchReplicas(context, namespace, k8sClient) {
822
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
823
+ try {
824
+ let theirApi = k8sClient !== null && k8sClient !== void 0 ? k8sClient : yield this.getK8sClient(context);
825
+ // Fetch from the cluster
826
+ let podResult = yield theirApi.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, `${codiac_constants_1.CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`);
827
+ let replicas = podResult.body.items;
828
+ // let replicas = _.orderBy(podResult.body.items, p => p.metadata?.labels?.assetVersion, 'desc'); // NOTE: this isnt a semantic version sort
829
+ try {
830
+ // Might need a semver.coerce() in here...
831
+ replicas = replicas.sort((a, b) => { var _a, _b, _c, _d, _e, _f; return semver.rcompare((_c = (_b = (_a = a.metadata) === null || _a === void 0 ? void 0 : _a.labels) === null || _b === void 0 ? void 0 : _b.assetVersion) !== null && _c !== void 0 ? _c : "", (_f = (_e = (_d = b.metadata) === null || _d === void 0 ? void 0 : _d.labels) === null || _e === void 0 ? void 0 : _e.assetVersion) !== null && _f !== void 0 ? _f : ""); }); // removes semvers so they can be sorted uniquely
832
+ }
833
+ catch (err) {
834
+ replicas = _.orderBy(replicas, p => { var _a, _b, _c; return (_c = (_b = (_a = p.metadata) === null || _a === void 0 ? void 0 : _a.labels) === null || _b === void 0 ? void 0 : _b.assetVersion) !== null && _c !== void 0 ? _c : ""; }); // TODO: we need this ALSO sorted by replica set (ie: name or labels["pod-template-hash"])
835
+ }
836
+ return replicas;
837
+ }
838
+ catch (err) {
839
+ throw err;
840
+ }
841
+ });
842
+ }
843
+ // protected async watchEvents(context: AssetReplicaContext, namespace: string, replicas?: k8s.V1Pod[] | undefined): Promise<void> {
844
+ // // let selector = `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`;
845
+ // let selector = `app=${context.asset}`;
846
+ // let creds = await this.getKubeConfig(context);
847
+ // let k8sClient = creds.makeApiClient(k8s.EventsV1Api);
848
+ // let watcher = new Watch(creds);
849
+ // watcher.watch(
850
+ // '/apis/events.k8s.io/v1/namespaces/{namespace}/events',
851
+ // )
852
+ // let res = await k8sClient.listNamespacedEvent(namespace, undefined, undefined, undefined, undefined, selector,
853
+ // undefined, undefined, undefined, undefined, true, undefined);
854
+ // }
855
+ watchStatus_NEW(context, namespace, replicas) {
856
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
857
+ // let selector = `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`;
858
+ let selector = `app=${context.asset}`;
859
+ let kube = yield this.getKubeConfig(context);
860
+ let k8sClient = yield this.getK8sClient(context);
861
+ (0, log_update_wrapper_1.logUpdate)(`Watching ${this._styler.hilite(context.asset)} in ${context.environment}/${context.cabinet}... (ctrl-c to quit)`);
862
+ log_update_wrapper_1.logUpdate.done();
863
+ (0, log_update_wrapper_1.logUpdate)(`...empty...`);
864
+ // This approach DOES return what's different in the cached list,
865
+ // but doesnt stream updates from the cluster - it only runs a first request,
866
+ // meaning you need to call this repeatedly - this looks not fully-baked...?
867
+ let informer = (0, client_node_1.makeInformer)(kube, `/api/v1/namespaces/${namespace}/pods`, () => k8sClient.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, selector)
868
+ // () => k8sClient.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, selector, undefined, undefined, undefined, undefined, true),
869
+ // selector
870
+ );
871
+ // informer.on('add', (obj: k8s.V1Pod) => { console.log(`Added: ${obj.metadata!.name}`); });
872
+ // informer.on('update', (obj: k8s.V1Pod) => { console.log(`Updated: ${obj.metadata!.name}`); });
873
+ informer.on('change', (obj) => {
874
+ // console.log(`Changed: ${obj.metadata!.name}`);
875
+ let canvas = { table: "", curver: "" };
876
+ let replicas = informer.list(namespace);
877
+ if (replicas.length > 0) {
878
+ for (let pod of replicas) {
879
+ this.renderReplicaStatusRow(pod, canvas);
880
+ }
881
+ }
882
+ else {
883
+ canvas.table = "(no instances found)";
884
+ }
885
+ log_update_wrapper_1.logUpdate.clear();
886
+ (0, log_update_wrapper_1.logUpdate)(canvas.table);
887
+ });
888
+ // informer.on('delete', (obj: k8s.V1Pod) => { console.log(`Deleted: ${obj.metadata!.name}`); });
889
+ informer.on('error', (err) => {
890
+ if (err.statusCode === 401) {
891
+ // TODO: reach out to the relay to refresh the user token in the kubeconfig.
892
+ log_update_wrapper_1.logUpdate.clear();
893
+ (0, log_update_wrapper_1.logUpdate)(`Authentication error; please refresh your credentials.`);
894
+ }
895
+ else {
896
+ log_update_wrapper_1.logUpdate.clear();
897
+ console.error(err);
898
+ }
899
+ // Restart informer after 5sec
900
+ setTimeout(() => {
901
+ informer.start();
902
+ }, 5000);
903
+ });
904
+ informer.start();
905
+ // let watch: boolean = true;
906
+ // listNamespacedPod() with "watch" just floats out into space with no return
907
+ // let podResult = await k8sClient.listNamespacedPod(namespace, undefined, undefined, undefined, undefined,
908
+ // `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`, undefined, undefined, undefined, undefined, watch);
909
+ // while (podResult) {
910
+ // logUpdate(`${podResult.body.items.length} pods returned`); // Thanks, nice and ambiguous; lets give them something actionable here instead.
911
+ // }
912
+ });
913
+ }
914
+ watchReplicaSet(context, namespace, replicaSets) {
915
+ var _a, _b, _c, _d, _e, _f, _g;
916
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
917
+ let k8sConfig = (yield this.getKubeConfig(context));
918
+ let k8sClient = k8sConfig.makeApiClient(k8s.AppsV1Api);
919
+ // let selector = `${CodiacLabels.LABEL_ASSET_NAME}=${context.asset}`;
920
+ let selector = `app=${context.asset}`;
921
+ let watch = true;
922
+ do {
923
+ let content = "";
924
+ log_update_wrapper_1.logUpdate.clear();
925
+ try {
926
+ let podResult = yield k8sClient.listNamespacedReplicaSet(namespace, undefined, undefined, undefined, undefined, selector);
927
+ let output = podResult.body.items;
928
+ for (let item of output) {
929
+ if (item.status) {
930
+ content = content.concat(`${(_b = (_a = item.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed"} ${(_c = item.status.availableReplicas) !== null && _c !== void 0 ? _c : 0}/${item.status.replicas}`, "\n");
931
+ }
932
+ else {
933
+ content = content.concat(`no status for ${(_e = (_d = item.metadata) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : "unnamed"}`, "\n");
934
+ }
935
+ }
936
+ }
937
+ catch (err) {
938
+ content = content.concat(`Error ${(_f = err.name) !== null && _f !== void 0 ? _f : ""} ${(_g = err.message) !== null && _g !== void 0 ? _g : ""}`, "\n");
939
+ }
940
+ (0, log_update_wrapper_1.logUpdate)(content);
941
+ yield this.unblockAndSleep(0.5);
942
+ } while (watch);
943
+ });
944
+ }
945
+ watchStatus(context, namespace, replicas) {
946
+ var _a, _b, _c, _d, _e, _f, _g;
947
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
948
+ let watch = true;
949
+ let k8sClient = yield this.getK8sClient(context);
950
+ let pods = replicas;
951
+ let spinChars = ["|", "/", "-", "\\"];
952
+ let spinIndex = -1;
953
+ (0, log_update_wrapper_1.logUpdate)(`Status for ${context.asset} in ${context.environment}/${context.cabinet}... (ctrl-c to quit)`);
954
+ log_update_wrapper_1.logUpdate.done();
955
+ do {
956
+ // await this.showStatus(context, namespace, pods, k8sClient);
957
+ spinIndex++;
958
+ if (spinIndex >= spinChars.length)
959
+ spinIndex = 0;
960
+ let spinner = spinChars[spinIndex];
961
+ // TODO: trap failures here and if status currently exists, render the error and leave the existing
962
+ let table = "";
963
+ try {
964
+ pods = pods !== null && pods !== void 0 ? pods : yield this.fetchReplicas(context, namespace, k8sClient);
965
+ if (pods && pods.length > 0) {
966
+ log_update_wrapper_1.logUpdate.clear();
967
+ let curver = ""; // current asset version being listed
968
+ // let deployed = res.successes[0].currentVersion.deployed;
969
+ for (let replica of pods) {
970
+ let replicaName = (_b = (_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
971
+ let podHash = ((_c = replica.metadata) === null || _c === void 0 ? void 0 : _c.labels) ? (_d = replica.metadata) === null || _d === void 0 ? void 0 : _d.labels["pod-template-hash"] : undefined;
972
+ let replicaId = podHash ? replicaName.slice(replicaName.indexOf(podHash)) : replicaName;
973
+ let assetVersion = ((_e = replica.metadata) === null || _e === void 0 ? void 0 : _e.labels) ? (_f = replica.metadata) === null || _f === void 0 ? void 0 : _f.labels[codiac_constants_1.CodiacLabels.LABEL_ASSET_VERSION] : undefined;
974
+ // Version separator
975
+ if (assetVersion !== undefined && assetVersion !== curver) {
976
+ curver = assetVersion;
977
+ table = table.concat(`${spinner} ${assetVersion}`, "\n");
978
+ }
979
+ // Each replica
980
+ if (replica.status) {
981
+ let state = this.renderPodState(replica);
982
+ let condition = this.renderCondition(replica);
983
+ let restarts = (replica.status.containerStatuses && replica.status.containerStatuses.length > 0) ? replica.status.containerStatuses[0].restartCount : 0;
984
+ table = table.concat(` ${replicaId}) ${state} ${condition} started (${replica.status.startTime}) ${restarts} restarts\n`); // , deployed (${deployed})`)
985
+ }
986
+ }
987
+ }
988
+ else {
989
+ table = table.concat(`No running instances found.`);
990
+ }
991
+ }
992
+ catch (err) {
993
+ table = table.concat(`Error refreshing... ${(_g = err.message) !== null && _g !== void 0 ? _g : err.name}\n`);
994
+ }
995
+ (0, log_update_wrapper_1.logUpdate)(table);
996
+ pods = undefined;
997
+ yield this.unblockAndSleep(0.5);
998
+ } while (watch);
999
+ });
1000
+ }
1001
+ /** Mutates canvas */
1002
+ renderReplicaStatusRow(replica, canvas) {
1003
+ var _a, _b, _c, _d, _e, _f;
1004
+ let replicaName = (_b = (_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
1005
+ let podHash = ((_c = replica.metadata) === null || _c === void 0 ? void 0 : _c.labels) ? (_d = replica.metadata) === null || _d === void 0 ? void 0 : _d.labels["pod-template-hash"] : undefined;
1006
+ let replicaId = podHash ? replicaName.slice(replicaName.indexOf(podHash)) : replicaName;
1007
+ let assetVersion = ((_e = replica.metadata) === null || _e === void 0 ? void 0 : _e.labels) ? (_f = replica.metadata) === null || _f === void 0 ? void 0 : _f.labels[codiac_constants_1.CodiacLabels.LABEL_ASSET_VERSION] : undefined;
1008
+ // Version separator
1009
+ if (assetVersion !== undefined && assetVersion !== canvas.curver) {
1010
+ canvas.curver = assetVersion;
1011
+ canvas.table = canvas.table.concat(`${assetVersion}`, "\n");
1012
+ }
1013
+ // Each replica
1014
+ if (replica.status) {
1015
+ let state = this.renderPodState(replica);
1016
+ let condition = this.renderCondition(replica);
1017
+ let restarts = (replica.status.containerStatuses && replica.status.containerStatuses.length > 0) ? replica.status.containerStatuses[0].restartCount : 0;
1018
+ canvas.table = canvas.table.concat(` ${replicaId}) ${state} ${condition} started (${replica.status.startTime}) ${restarts} restarts\n`); // , deployed (${deployed})`)
1019
+ }
1020
+ }
1021
+ renderCondition(replica) {
1022
+ var _a;
1023
+ let cond = "";
1024
+ if (replica.status) {
1025
+ if (((_a = replica.status) === null || _a === void 0 ? void 0 : _a.conditions) && replica.status.conditions.length > 0) {
1026
+ let latestCond = _.orderBy(replica.status.conditions, x => x.lastTransitionTime, "desc")[0];
1027
+ cond = latestCond.type;
1028
+ if (latestCond.reason) {
1029
+ cond = cond.concat(" (", latestCond.reason, ")");
1030
+ }
1031
+ if (latestCond.message) {
1032
+ // TODO: Revisit; message is prob too much info to jam into a cli output line.
1033
+ cond = cond.concat(" ('", latestCond.message, "')");
1034
+ }
1035
+ cond = cond.concat(` since (${latestCond.lastTransitionTime})`);
1036
+ }
1037
+ }
1038
+ return cond;
1039
+ }
1040
+ renderPodState(replica) {
1041
+ var _a, _b, _c, _d;
1042
+ let state = "[no status found]";
1043
+ if ((_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.deletionTimestamp) {
1044
+ state = "Terminating";
1045
+ }
1046
+ else if (replica.status) {
1047
+ state = "";
1048
+ // Pod phase
1049
+ if (replica.status.phase) {
1050
+ state = replica.status.phase;
1051
+ }
1052
+ if (replica.status.reason) {
1053
+ state = state.concat(" (", replica.status.reason, ")");
1054
+ }
1055
+ if (replica.status.message) {
1056
+ state = state.concat(" ('", replica.status.message, "')");
1057
+ }
1058
+ // container state
1059
+ if (replica.status.containerStatuses && replica.status.containerStatuses.length > 0) {
1060
+ let ctrStatus = replica.status.containerStatuses[0];
1061
+ // state = state.concat(" ", JSON.stringify(ctrStatus.state), "\n");
1062
+ if ((_b = ctrStatus.state) === null || _b === void 0 ? void 0 : _b.waiting) {
1063
+ if (ctrStatus.state.waiting.reason) {
1064
+ state = state.concat(" (", ctrStatus.state.waiting.reason, ")");
1065
+ }
1066
+ if (ctrStatus.state.waiting.message) {
1067
+ state = state.concat(" ('", ctrStatus.state.waiting.message, "')");
1068
+ }
1069
+ }
1070
+ else if ((_c = ctrStatus.state) === null || _c === void 0 ? void 0 : _c.terminated) {
1071
+ if (ctrStatus.state.terminated.reason) {
1072
+ state = state.concat(" (", ctrStatus.state.terminated.reason, ")");
1073
+ }
1074
+ if (ctrStatus.state.terminated.message) {
1075
+ state = state.concat(" (", ctrStatus.state.terminated.message, ")");
1076
+ }
1077
+ }
1078
+ else if ((_d = ctrStatus.state) === null || _d === void 0 ? void 0 : _d.running) {
1079
+ }
1080
+ }
1081
+ }
1082
+ return state;
1083
+ }
1084
+ unblockAndSleep(durationInSecs) {
1085
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
1086
+ return new Promise(resolve => {
1087
+ setTimeout(() => resolve(), durationInSecs * 1000);
1088
+ });
1089
+ });
1090
+ }
1091
+ /** Fetches pods if not already provided. */
1092
+ showStatus(context, namespace, replicas, k8sApi) {
1093
+ var _a, _b, _c;
1094
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
1095
+ try {
1096
+ let k8sClient = k8sApi !== null && k8sApi !== void 0 ? k8sApi : yield this.getK8sClient(context);
1097
+ let pods = replicas !== null && replicas !== void 0 ? replicas : yield this.fetchReplicas(context, namespace, k8sClient);
1098
+ if (pods && pods.length > 0) {
1099
+ // let deployed = res.successes[0].currentVersion.deployed;
1100
+ console.log(`Status for ${context.asset} ${(pods.length > 0) ? " instances" : ""} running in ${context.environment}/${context.cabinet}`);
1101
+ for (let replica of pods) {
1102
+ let replicaName = (_b = (_a = replica.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "unnamed";
1103
+ if (((_c = replica.status) === null || _c === void 0 ? void 0 : _c.conditions) && replica.status.conditions.length > 0) {
1104
+ let latestCond = _.orderBy(replica.status.conditions, x => x.lastTransitionTime, "desc")[0];
1105
+ console.log(`${replicaName} ${latestCond.type} since (${latestCond.lastTransitionTime}) started (${replica.status.startTime}) ${replica.status.containerStatuses[0].restartCount} restarts`); // , deployed (${deployed})`)
1106
+ }
1107
+ else {
1108
+ console.log("Condition not available"); // Thanks, nice and ambiguous; lets give them something actionable here instead.
1109
+ }
1110
+ }
1111
+ }
1112
+ else {
1113
+ this._ui.userMessage(`No running instances found.`);
1114
+ }
1115
+ return;
1116
+ }
1117
+ catch (err) {
1118
+ throw err;
1119
+ }
1120
+ });
1121
+ }
1122
+ showLogs(context, logOptions) {
1123
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
1124
+ try {
1125
+ // SHOW LOGS
1126
+ let req = Object.assign(Object.assign({}, context), { logOptions: logOptions });
1127
+ let cnxnResult = yield this.genRelayClient.Call.getLogStreamSpecs(req);
1128
+ if (cnxnResult.error)
1129
+ throw cnxnResult.error;
1130
+ if (cnxnResult.output == undefined)
1131
+ throw new Error(`Failed without error getting log stream connection specs.`);
1132
+ const logStream = new stream.PassThrough();
1133
+ logStream.on("data", (chunk) => {
1134
+ // use write rather than console.log to prevent double line feed
1135
+ process.stdout.write(chunk);
1136
+ });
1137
+ let streamer = new LogStreamer(this.logger);
1138
+ let requestOptions = cnxnResult.output;
1139
+ // Deserialize from strings into Buffers after their trip over the wire
1140
+ if (cnxnResult.output.ca)
1141
+ requestOptions.ca = Buffer.from(cnxnResult.output.ca);
1142
+ else
1143
+ this.logger.warn(`Cluster connection specs retrieved for log streaming did not have a ca.`);
1144
+ if (cnxnResult.output.cert)
1145
+ requestOptions.cert = Buffer.from(cnxnResult.output.cert);
1146
+ else
1147
+ this.logger.warn(`Cluster connection specs retrieved for log streaming did not have a cert.`);
1148
+ if (cnxnResult.output.key)
1149
+ requestOptions.key = Buffer.from(cnxnResult.output.key);
1150
+ else
1151
+ this.logger.warn(`Cluster connection specs retrieved for log streaming did not have a key.`);
1152
+ streamer.go(requestOptions, logStream); // shouldn't we be awaiting this?
1153
+ }
1154
+ catch (err) {
1155
+ throw err;
1156
+ }
1157
+ });
1158
+ }
1159
+ /**
1160
+ * @param context Fully qualified path, in terms of Codiac entities, to identify a single replica of an asset in a cabinet.
1161
+ * @param execArgs Parameters identifying the ultimate command to run and the console behavior.
1162
+ * @param K8sEntities The identifying names of the relevant kubernetes objects, corresponding to the asset replica context, that fully qualify the desired container. */
1163
+ runExec(context, execArgs, k8sEntities) {
1164
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
1165
+ try {
1166
+ let k8sCnxnResult = yield this.genRelayClient.Call.getClusterConnectionSpecs(context);
1167
+ if (k8sCnxnResult.error)
1168
+ throw k8sCnxnResult.error;
1169
+ if (k8sCnxnResult.output === undefined || _.isEmpty(k8sCnxnResult.output))
1170
+ throw new Error(`Retrieval of cluster connection spec failed without error.`);
1171
+ let spec = k8sCnxnResult.output;
1172
+ let kc = new k8s.KubeConfig();
1173
+ kc.loadFromString(spec);
1174
+ // ======================================================================================================
1175
+ // We have to resume here because the console keystrokes are not getting through,
1176
+ // even though a POC running just the exec (without all the other ui code we're running)
1177
+ // doesnt have the input problem.
1178
+ //
1179
+ // TODO: Find out why we need this stdin resumed.
1180
+ // Most likely because it was piped into an spawned child process that has since ended.
1181
+ //
1182
+ process.stdin.resume(); // Somehwere we probably lost track of a stdin
1183
+ //
1184
+ //
1185
+ // ======================================================================================================
1186
+ const exec = new k8s.Exec(kc);
1187
+ const ws = yield exec.exec(k8sEntities.namespace, k8sEntities.pod, k8sEntities.container, execArgs.command, process.stdout, process.stderr, process.stdin, execArgs.tty, (status) => {
1188
+ // tslint:disable-next-line:no-console
1189
+ // console.log("Exited with status:");
1190
+ // // tslint:disable-next-line:no-console
1191
+ this.logger.debug(`Executed terminal cmd. Status: ${status.status} ${status.reason}`, JSON.stringify(status, null, 2));
1192
+ });
1193
+ ws.onopen = function open() {
1194
+ process.stdout.write("connected");
1195
+ };
1196
+ ws.onclose = function close(evt) {
1197
+ // process.stdout.write("disconnected");
1198
+ process.exit(evt.code);
1199
+ return;
1200
+ };
1201
+ ws.onmessage = this.routeK8sWebSocketMessage;
1202
+ // function incoming(msg: any) {
1203
+ // let buf = Buffer.from(msg.data);
1204
+ // // The k8s client prefixes the buffer with the stream number at position 0...
1205
+ // let streamNumBuf = buf.readInt8();
1206
+ // let payload = buf.toString('utf8', 1); // <-- start at pos 1 to skip the stream number.
1207
+ // switch (streamNumBuf) {
1208
+ // case WebSocketHandler.StdoutStream /* 1 */:
1209
+ // process.stdout.write(payload);
1210
+ // break;
1211
+ // case WebSocketHandler.StderrStream /* 2 */:
1212
+ // process.stderr.write(`ERROR: ` + payload);
1213
+ // break;
1214
+ // case WebSocketHandler.StatusStream /* 3 */:
1215
+ // let k8sStatus = JSON.parse(payload) as V1Status;
1216
+ // process.stdout.write(`STATUS: ${k8sStatus.status}: ${k8sStatus.message}`);
1217
+ // break;
1218
+ // default:
1219
+ // process.stderr.write(`feedback on ${streamNumBuf}`)
1220
+ // }
1221
+ // return;
1222
+ // };
1223
+ // This never gets hit. Instead, onmessage gets hit with a message designated for stderr stream.
1224
+ ws.onerror = function error(err) {
1225
+ process.stdout.write(`Error: ${err.message}`);
1226
+ ws.close();
1227
+ };
1228
+ // Gotta do a process.exit(code) to give the control back.
1229
+ // THese dont fire
1230
+ // ws.once('exit', (code) => process.exit(code));
1231
+ // ws.once('end', (code) => process.stdout.write("end event fired"));
1232
+ return;
1233
+ }
1234
+ catch (err) {
1235
+ throw err;
1236
+ }
1237
+ });
1238
+ }
1239
+ /** Parses the stream number from the incoming message,
1240
+ * and writes the data to the designated target stream.
1241
+ *
1242
+ * (The k8s client prefixes the buffer with the stream number at position 0)
1243
+ */
1244
+ routeK8sWebSocketMessage(msg) {
1245
+ var _a;
1246
+ let buf = Buffer.from(msg.data);
1247
+ // The k8s client prefixes the buffer with the stream number at position 0...
1248
+ let streamNumBuf = buf.readInt8();
1249
+ let payload = buf.toString('utf8', 1); // <-- start at pos 1 to skip the stream number.
1250
+ switch (streamNumBuf) {
1251
+ case web_socket_handler_1.WebSocketHandler.StdoutStream /* 1 */:
1252
+ process.stdout.write(payload);
1253
+ break;
1254
+ case web_socket_handler_1.WebSocketHandler.StderrStream /* 2 */:
1255
+ process.stderr.write(`ERROR: ` + payload);
1256
+ break;
1257
+ case web_socket_handler_1.WebSocketHandler.StatusStream /* 3 */:
1258
+ let k8sStatus = JSON.parse(payload);
1259
+ if (((_a = k8sStatus.status) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "failure") {
1260
+ if (k8sStatus.reason !== "NonZeroExitCode") {
1261
+ process.stdout.write(`STATUS: ${k8sStatus.status}: ${k8sStatus.message}`);
1262
+ }
1263
+ }
1264
+ break;
1265
+ default:
1266
+ process.stderr.write(`feedback on ${streamNumBuf}`);
1267
+ }
1268
+ return;
1269
+ }
1270
+ }
1271
+ exports.default = AssetView;
1272
+ AssetView.description = 'Renders a selected type of content for an asset';
1273
+ AssetView.aliases = ['asset:monitor', "asset:mon", "asset:get"];
1274
+ AssetView.flags = {
1275
+ help: core_1.Flags.help({ char: 'h' }),
1276
+ enterprise: core_1.Flags.string({ char: 'e', description: 'The name of the enterprise containing the asset being viewed.' }),
1277
+ asset: core_1.Flags.string({ char: 'a', description: 'The name of the asset to view.' }),
1278
+ environment: core_1.Flags.string({ char: 'n', description: 'The name of the environment in which the cabinet resides.' }),
1279
+ cabinet: core_1.Flags.string({ char: 'c', description: 'The name of the cabinet from which the content is to be drawn.' }),
1280
+ replica: core_1.Flags.string({ char: 'r', description: 'The name of one of the asset instances currently running in the cabinet.' }),
1281
+ type: core_1.Flags.string({ char: 't', options: [...Object.keys(AssetContentType)], description: 'The type of content to retrieve.' }),
1282
+ terminal: core_1.Flags.string({ options: ["bash", "sh"], description: 'Command used to start the terminal (defaults to "bash")' }),
1283
+ logsFollow: core_1.Flags.boolean({ char: 'f', default: false, description: '(requires type=logs) Follow (aka watch, tail, stream) the output.' }),
1284
+ logsTail: core_1.Flags.integer({ char: 'l', default: 10, description: '(requires type=logs) Lines of recent logs to include in the output. Enter -1 to include the entire log history stored in the container.' }),
1285
+ configFile: core_1.Flags.string({ char: 'F', description: '(requires type=config) The root pathname to the config file to fetch.' }),
1286
+ silent: core_1.Flags.boolean({ exclusive: ["echo", "toscript"], description: 'Non-Interactive mode; executes without any user interaction and fails on any missing or invalid arguments.' }),
1287
+ echo: core_1.Flags.boolean({ exclusive: ["toscript", "silent"], description: 'Echo interaction mode; renders the equivalent non-interactive cli command for future use before final execution.' }),
1288
+ toscript: core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Toscript interaction mode; renders the equivalent non-interactive cli command WITHOUT any execution.' }),
1289
+ takeDefaults: core_1.Flags.boolean({ exclusive: ["silent"], description: "Prevents prompting for confirmation on parameters that were passed in or were set to default values." })
1290
+ // tty: Flags.boolean({ char: 'i', default: false, description: '(requires type=exec) Specifies an interactive console session.' })
1291
+ };
1292
+ AssetView.strict = false; // disables argument validation so we can support variable-length arguments.
1293
+ AssetView.args = {
1294
+ cmd: core_1.Args.string({ description: '(requires type=exec) command and its space-separated arguments to run in the target replica.' })
1295
+ };
1296
+ class ExecArgs {
1297
+ constructor(command, tty = true) {
1298
+ this.command = command;
1299
+ this.tty = tty;
1300
+ }
1301
+ }
1302
+ exports.ExecArgs = ExecArgs;
1303
+ class ConfigFileArgs {
1304
+ constructor(rootPathName) {
1305
+ this.rootPathName = rootPathName;
1306
+ }
1307
+ }
1308
+ exports.ConfigFileArgs = ConfigFileArgs;
1309
+ class TermArgs {
1310
+ /**
1311
+ *
1312
+ * @param terminalStartup The type of terminal to open. This command may change depending on what terminal or command shell types are available in the image.
1313
+ */
1314
+ constructor(terminalStartup) {
1315
+ this.terminalStartup = terminalStartup;
1316
+ }
1317
+ }
1318
+ exports.TermArgs = TermArgs;
1319
+ /** Idnetifies a container, in a pod, in a namespace, in a cluster. */
1320
+ class K8sContainerRef {
1321
+ constructor(namespace, podName,
1322
+ /** This should be optional. When there's only one container in a pod,
1323
+ * we should be able to derive this from the pod spec. */
1324
+ containerName) {
1325
+ this.namespace = namespace;
1326
+ this.podName = podName;
1327
+ this.containerName = containerName;
1328
+ }
1329
+ }
1330
+ exports.K8sContainerRef = K8sContainerRef;
1331
+ class LogStreamer {
1332
+ constructor(logger) {
1333
+ this.logger = logger;
1334
+ }
1335
+ go(requestOptions, stream) {
1336
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
1337
+ return new Promise((resolve, reject) => {
1338
+ const req = request(requestOptions, (error, response, body) => {
1339
+ if (error) {
1340
+ reject(error);
1341
+ }
1342
+ else if (response.statusCode !== 200) {
1343
+ this.logger.detail(`Error connecting to log stream`, body);
1344
+ let details;
1345
+ try {
1346
+ const k8sStatus = client_node_1.ObjectSerializer.deserialize(JSON.parse(body), 'V1Status');
1347
+ details = `${k8sStatus.status}${k8sStatus.reason ? " (" + k8sStatus.reason + ")" : ""} ${k8sStatus.message}`;
1348
+ }
1349
+ catch (_a) {
1350
+ details = "See cli log for details.";
1351
+ }
1352
+ reject(new Error(`Error connecting to log stream. ${details}`));
1353
+ }
1354
+ }).on('response', (response) => {
1355
+ if (response.statusCode === 200) {
1356
+ req.pipe(stream);
1357
+ resolve(req);
1358
+ }
1359
+ });
1360
+ });
1361
+ });
1362
+ }
1363
+ }
1364
+ exports.LogStreamer = LogStreamer;
1361
1365
  //# sourceMappingURL=view.js.map