@microsoft/terraform-cdk-constructs 1.0.0 → 1.2.0

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 (385) hide show
  1. package/.jsii +60999 -15780
  2. package/API.md +54947 -10610
  3. package/README.md +72 -36
  4. package/docs/monitoring-guide.md +206 -0
  5. package/docs/testing.md +84 -1
  6. package/lib/azure-actiongroup/index.d.ts +11 -0
  7. package/lib/azure-actiongroup/index.js +28 -0
  8. package/lib/azure-actiongroup/lib/action-group-schemas.d.ts +24 -0
  9. package/lib/azure-actiongroup/lib/action-group-schemas.js +201 -0
  10. package/lib/azure-actiongroup/lib/action-group.d.ts +312 -0
  11. package/lib/azure-actiongroup/lib/action-group.js +201 -0
  12. package/lib/azure-actiongroup/lib/index.d.ts +5 -0
  13. package/lib/azure-actiongroup/lib/index.js +22 -0
  14. package/lib/azure-actiongroup/test/action-group.integ.d.ts +9 -0
  15. package/lib/azure-actiongroup/test/action-group.integ.js +79 -0
  16. package/lib/azure-actiongroup/test/action-group.spec.d.ts +8 -0
  17. package/lib/azure-actiongroup/test/action-group.spec.js +602 -0
  18. package/lib/azure-activitylogalert/index.d.ts +11 -0
  19. package/lib/azure-activitylogalert/index.js +28 -0
  20. package/lib/azure-activitylogalert/lib/activity-log-alert-schemas.d.ts +24 -0
  21. package/lib/azure-activitylogalert/lib/activity-log-alert-schemas.js +182 -0
  22. package/lib/azure-activitylogalert/lib/activity-log-alert.d.ts +236 -0
  23. package/lib/azure-activitylogalert/lib/activity-log-alert.js +212 -0
  24. package/lib/azure-activitylogalert/lib/index.d.ts +5 -0
  25. package/lib/azure-activitylogalert/lib/index.js +22 -0
  26. package/lib/azure-activitylogalert/test/activity-log-alert.integ.d.ts +9 -0
  27. package/lib/azure-activitylogalert/test/activity-log-alert.integ.js +98 -0
  28. package/lib/azure-activitylogalert/test/activity-log-alert.spec.d.ts +9 -0
  29. package/lib/azure-activitylogalert/test/activity-log-alert.spec.js +1101 -0
  30. package/lib/azure-aks/index.d.ts +9 -0
  31. package/lib/azure-aks/index.js +28 -0
  32. package/lib/azure-aks/lib/aks-cluster-schemas.d.ts +505 -0
  33. package/lib/azure-aks/lib/aks-cluster-schemas.js +572 -0
  34. package/lib/azure-aks/lib/aks-cluster.d.ts +395 -0
  35. package/lib/azure-aks/lib/aks-cluster.js +489 -0
  36. package/lib/azure-aks/lib/index.d.ts +11 -0
  37. package/lib/azure-aks/lib/index.js +38 -0
  38. package/lib/azure-aks/test/aks-cluster.integ.d.ts +9 -0
  39. package/lib/azure-aks/test/aks-cluster.integ.js +260 -0
  40. package/lib/azure-aks/test/aks-cluster.spec.d.ts +8 -0
  41. package/lib/azure-aks/test/aks-cluster.spec.js +1396 -0
  42. package/lib/azure-diagnosticsettings/index.d.ts +7 -0
  43. package/lib/azure-diagnosticsettings/index.js +24 -0
  44. package/lib/azure-diagnosticsettings/lib/diagnostic-settings-schemas.d.ts +50 -0
  45. package/lib/azure-diagnosticsettings/lib/diagnostic-settings-schemas.js +207 -0
  46. package/lib/azure-diagnosticsettings/lib/diagnostic-settings.d.ts +193 -0
  47. package/lib/azure-diagnosticsettings/lib/diagnostic-settings.js +200 -0
  48. package/lib/azure-diagnosticsettings/lib/index.d.ts +8 -0
  49. package/lib/azure-diagnosticsettings/lib/index.js +25 -0
  50. package/lib/azure-diagnosticsettings/test/diagnostic-settings.spec.d.ts +8 -0
  51. package/lib/azure-diagnosticsettings/test/diagnostic-settings.spec.js +432 -0
  52. package/lib/azure-metricalert/index.d.ts +11 -0
  53. package/lib/azure-metricalert/index.js +28 -0
  54. package/lib/azure-metricalert/lib/index.d.ts +5 -0
  55. package/lib/azure-metricalert/lib/index.js +22 -0
  56. package/lib/azure-metricalert/lib/metric-alert-schemas.d.ts +24 -0
  57. package/lib/azure-metricalert/lib/metric-alert-schemas.js +242 -0
  58. package/lib/azure-metricalert/lib/metric-alert.d.ts +344 -0
  59. package/lib/azure-metricalert/lib/metric-alert.js +252 -0
  60. package/lib/azure-metricalert/test/metric-alert.integ.d.ts +9 -0
  61. package/lib/azure-metricalert/test/metric-alert.integ.js +123 -0
  62. package/lib/azure-metricalert/test/metric-alert.spec.d.ts +9 -0
  63. package/lib/azure-metricalert/test/metric-alert.spec.js +1266 -0
  64. package/lib/azure-networkinterface/index.d.ts +4 -0
  65. package/lib/azure-networkinterface/index.js +21 -0
  66. package/lib/azure-networkinterface/lib/index.d.ts +6 -0
  67. package/lib/azure-networkinterface/lib/index.js +22 -0
  68. package/lib/azure-networkinterface/lib/network-interface-schemas.d.ts +32 -0
  69. package/lib/azure-networkinterface/lib/network-interface-schemas.js +222 -0
  70. package/lib/azure-networkinterface/lib/network-interface.d.ts +265 -0
  71. package/lib/azure-networkinterface/lib/network-interface.js +228 -0
  72. package/lib/azure-networkinterface/test/network-interface.integ.d.ts +9 -0
  73. package/lib/azure-networkinterface/test/network-interface.integ.js +102 -0
  74. package/lib/azure-networkinterface/test/network-interface.spec.d.ts +8 -0
  75. package/lib/azure-networkinterface/test/network-interface.spec.js +655 -0
  76. package/lib/azure-networksecuritygroup/index.d.ts +6 -0
  77. package/lib/azure-networksecuritygroup/index.js +23 -0
  78. package/lib/azure-networksecuritygroup/lib/index.d.ts +5 -0
  79. package/lib/azure-networksecuritygroup/lib/index.js +16 -0
  80. package/lib/azure-networksecuritygroup/lib/network-security-group-schemas.d.ts +32 -0
  81. package/lib/azure-networksecuritygroup/lib/network-security-group-schemas.js +198 -0
  82. package/lib/azure-networksecuritygroup/lib/network-security-group.d.ts +268 -0
  83. package/lib/azure-networksecuritygroup/lib/network-security-group.js +248 -0
  84. package/lib/azure-networksecuritygroup/test/network-security-group.integ.d.ts +9 -0
  85. package/lib/azure-networksecuritygroup/test/network-security-group.integ.js +151 -0
  86. package/lib/azure-networksecuritygroup/test/network-security-group.spec.d.ts +8 -0
  87. package/lib/azure-networksecuritygroup/test/network-security-group.spec.js +652 -0
  88. package/lib/azure-publicipaddress/index.d.ts +6 -0
  89. package/lib/azure-publicipaddress/index.js +23 -0
  90. package/lib/azure-publicipaddress/lib/index.d.ts +9 -0
  91. package/lib/azure-publicipaddress/lib/index.js +19 -0
  92. package/lib/azure-publicipaddress/lib/public-ip-address-schemas.d.ts +32 -0
  93. package/lib/azure-publicipaddress/lib/public-ip-address-schemas.js +227 -0
  94. package/lib/azure-publicipaddress/lib/public-ip-address.d.ts +256 -0
  95. package/lib/azure-publicipaddress/lib/public-ip-address.js +267 -0
  96. package/lib/azure-publicipaddress/test/public-ip-address.integ.d.ts +9 -0
  97. package/lib/azure-publicipaddress/test/public-ip-address.integ.js +75 -0
  98. package/lib/azure-publicipaddress/test/public-ip-address.spec.d.ts +15 -0
  99. package/lib/azure-publicipaddress/test/public-ip-address.spec.js +498 -0
  100. package/lib/azure-resourcegroup/lib/resource-group.js +1 -1
  101. package/lib/azure-resourcegroup/test/resource-group.integ.js +23 -11
  102. package/lib/azure-storageaccount/lib/storage-account-schemas.d.ts +98 -0
  103. package/lib/azure-storageaccount/lib/storage-account-schemas.js +1 -1
  104. package/lib/azure-storageaccount/lib/storage-account.d.ts +38 -1
  105. package/lib/azure-storageaccount/lib/storage-account.js +138 -2
  106. package/lib/azure-storageaccount/test/storage-account.integ.js +91 -12
  107. package/lib/azure-subnet/index.d.ts +4 -0
  108. package/lib/azure-subnet/index.js +21 -0
  109. package/lib/azure-subnet/lib/index.d.ts +5 -0
  110. package/lib/azure-subnet/lib/index.js +22 -0
  111. package/lib/azure-subnet/lib/subnet-schemas.d.ts +32 -0
  112. package/lib/azure-subnet/lib/subnet-schemas.js +237 -0
  113. package/lib/azure-subnet/lib/subnet.d.ts +285 -0
  114. package/lib/azure-subnet/lib/subnet.js +254 -0
  115. package/lib/azure-subnet/test/subnet.integ.d.ts +11 -0
  116. package/lib/azure-subnet/test/subnet.integ.js +80 -0
  117. package/lib/azure-subnet/test/subnet.spec.d.ts +8 -0
  118. package/lib/azure-subnet/test/subnet.spec.js +396 -0
  119. package/lib/azure-virtualmachine/index.d.ts +7 -0
  120. package/lib/azure-virtualmachine/index.js +24 -0
  121. package/lib/azure-virtualmachine/lib/index.d.ts +11 -0
  122. package/lib/azure-virtualmachine/lib/index.js +38 -0
  123. package/lib/azure-virtualmachine/lib/virtual-machine-schemas.d.ts +327 -0
  124. package/lib/azure-virtualmachine/lib/virtual-machine-schemas.js +544 -0
  125. package/lib/azure-virtualmachine/lib/virtual-machine.d.ts +377 -0
  126. package/lib/azure-virtualmachine/lib/virtual-machine.js +462 -0
  127. package/lib/azure-virtualmachine/test/virtual-machine.integ.d.ts +9 -0
  128. package/lib/azure-virtualmachine/test/virtual-machine.integ.js +220 -0
  129. package/lib/azure-virtualmachine/test/virtual-machine.spec.d.ts +9 -0
  130. package/lib/azure-virtualmachine/test/virtual-machine.spec.js +1032 -0
  131. package/lib/azure-virtualnetwork/index.d.ts +10 -0
  132. package/lib/azure-virtualnetwork/index.js +28 -0
  133. package/lib/azure-virtualnetwork/lib/index.d.ts +9 -0
  134. package/lib/azure-virtualnetwork/lib/index.js +22 -0
  135. package/lib/azure-virtualnetwork/lib/virtual-network-schemas.d.ts +32 -0
  136. package/lib/azure-virtualnetwork/lib/virtual-network-schemas.js +236 -0
  137. package/lib/azure-virtualnetwork/lib/virtual-network.d.ts +213 -0
  138. package/lib/azure-virtualnetwork/lib/virtual-network.js +245 -0
  139. package/lib/azure-virtualnetwork/test/virtual-network.integ.d.ts +9 -0
  140. package/lib/azure-virtualnetwork/test/virtual-network.integ.js +91 -0
  141. package/lib/azure-virtualnetwork/test/virtual-network.spec.d.ts +8 -0
  142. package/lib/azure-virtualnetwork/test/virtual-network.spec.js +398 -0
  143. package/lib/azure-vmss/index.d.ts +6 -0
  144. package/lib/azure-vmss/index.js +23 -0
  145. package/lib/azure-vmss/lib/index.d.ts +9 -0
  146. package/lib/azure-vmss/lib/index.js +39 -0
  147. package/lib/azure-vmss/lib/virtual-machine-scale-set.d.ts +258 -0
  148. package/lib/azure-vmss/lib/virtual-machine-scale-set.js +503 -0
  149. package/lib/azure-vmss/lib/vmss-schemas.d.ts +472 -0
  150. package/lib/azure-vmss/lib/vmss-schemas.js +444 -0
  151. package/lib/azure-vmss/test/virtual-machine-scale-set.integ.d.ts +15 -0
  152. package/lib/azure-vmss/test/virtual-machine-scale-set.integ.js +261 -0
  153. package/lib/azure-vmss/test/virtual-machine-scale-set.spec.d.ts +8 -0
  154. package/lib/azure-vmss/test/virtual-machine-scale-set.spec.js +997 -0
  155. package/lib/core-azure/lib/azapi/azapi-resource.d.ts +95 -27
  156. package/lib/core-azure/lib/azapi/azapi-resource.js +95 -58
  157. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-client-config/index.d.ts +33 -21
  158. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-client-config/index.js +69 -27
  159. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource/index.d.ts +134 -120
  160. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource/index.js +209 -59
  161. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-action/index.d.ts +141 -128
  162. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-action/index.js +183 -36
  163. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-id/index.d.ts +55 -43
  164. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-id/index.js +94 -26
  165. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-list/index.d.ts +129 -116
  166. package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-list/index.js +155 -32
  167. package/lib/core-azure/lib/azapi/providers-azapi/data-plane-resource/index.d.ts +187 -174
  168. package/lib/core-azure/lib/azapi/providers-azapi/data-plane-resource/index.js +267 -48
  169. package/lib/core-azure/lib/azapi/providers-azapi/index.d.ts +10 -10
  170. package/lib/core-azure/lib/azapi/providers-azapi/index.js +1 -1
  171. package/lib/core-azure/lib/azapi/providers-azapi/lazy-index.d.ts +0 -0
  172. package/lib/core-azure/lib/azapi/providers-azapi/lazy-index.js +13 -0
  173. package/lib/core-azure/lib/azapi/providers-azapi/provider/index.d.ts +174 -162
  174. package/lib/core-azure/lib/azapi/providers-azapi/provider/index.js +274 -14
  175. package/lib/core-azure/lib/azapi/providers-azapi/resource/index.d.ts +239 -225
  176. package/lib/core-azure/lib/azapi/providers-azapi/resource/index.js +360 -76
  177. package/lib/core-azure/lib/azapi/providers-azapi/resource-action/index.d.ts +163 -150
  178. package/lib/core-azure/lib/azapi/providers-azapi/resource-action/index.js +221 -46
  179. package/lib/core-azure/lib/azapi/providers-azapi/update-resource/index.d.ts +162 -149
  180. package/lib/core-azure/lib/azapi/providers-azapi/update-resource/index.js +249 -50
  181. package/lib/core-azure/lib/azapi/schema-mapper/schema-mapper.js +4 -2
  182. package/lib/core-azure/lib/version-manager/api-version-manager.js +1 -1
  183. package/lib/core-azure/lib/version-manager/interfaces/version-interfaces.js +7 -7
  184. package/lib/index.d.ts +37 -0
  185. package/lib/index.js +40 -2
  186. package/lib/testing/index.d.ts +92 -2
  187. package/lib/testing/index.js +258 -18
  188. package/lib/testing/lib/cleanup.d.ts +229 -0
  189. package/lib/testing/lib/cleanup.js +331 -0
  190. package/lib/testing/lib/metadata.d.ts +151 -0
  191. package/lib/testing/lib/metadata.js +180 -0
  192. package/lib/testing/lib/naming.d.ts +96 -0
  193. package/lib/testing/lib/naming.js +336 -0
  194. package/node_modules/uuid/LICENSE.md +9 -0
  195. package/node_modules/uuid/README.md +510 -0
  196. package/node_modules/uuid/dist/cjs/index.d.ts +15 -0
  197. package/node_modules/uuid/dist/cjs/index.js +31 -0
  198. package/node_modules/uuid/dist/cjs/max.d.ts +2 -0
  199. package/node_modules/uuid/dist/cjs/max.js +3 -0
  200. package/node_modules/uuid/dist/cjs/md5.d.ts +4 -0
  201. package/node_modules/uuid/dist/cjs/md5.js +13 -0
  202. package/node_modules/uuid/dist/cjs/native.d.ts +6 -0
  203. package/node_modules/uuid/dist/cjs/native.js +4 -0
  204. package/node_modules/uuid/dist/cjs/nil.d.ts +2 -0
  205. package/node_modules/uuid/dist/cjs/nil.js +3 -0
  206. package/node_modules/uuid/dist/cjs/package.json +1 -0
  207. package/node_modules/uuid/dist/cjs/parse.d.ts +2 -0
  208. package/node_modules/uuid/dist/cjs/parse.js +11 -0
  209. package/node_modules/uuid/dist/cjs/regex.d.ts +2 -0
  210. package/node_modules/uuid/dist/cjs/regex.js +3 -0
  211. package/node_modules/uuid/dist/cjs/rng.d.ts +1 -0
  212. package/node_modules/uuid/dist/cjs/rng.js +13 -0
  213. package/node_modules/uuid/dist/cjs/sha1.d.ts +4 -0
  214. package/node_modules/uuid/dist/cjs/sha1.js +13 -0
  215. package/node_modules/uuid/dist/cjs/stringify.d.ts +3 -0
  216. package/node_modules/uuid/dist/cjs/stringify.js +39 -0
  217. package/node_modules/uuid/dist/cjs/types.d.ts +21 -0
  218. package/node_modules/uuid/dist/cjs/types.js +2 -0
  219. package/node_modules/uuid/dist/cjs/uuid-bin.d.ts +1 -0
  220. package/node_modules/uuid/dist/cjs/uuid-bin.js +72 -0
  221. package/node_modules/uuid/dist/cjs/v1.d.ts +11 -0
  222. package/node_modules/uuid/dist/cjs/v1.js +87 -0
  223. package/node_modules/uuid/dist/cjs/v1ToV6.d.ts +2 -0
  224. package/node_modules/uuid/dist/cjs/v1ToV6.js +13 -0
  225. package/node_modules/uuid/dist/cjs/v3.d.ts +9 -0
  226. package/node_modules/uuid/dist/cjs/v3.js +14 -0
  227. package/node_modules/uuid/dist/cjs/v35.d.ts +7 -0
  228. package/node_modules/uuid/dist/cjs/v35.js +41 -0
  229. package/node_modules/uuid/dist/cjs/v4.d.ts +4 -0
  230. package/node_modules/uuid/dist/cjs/v4.js +29 -0
  231. package/node_modules/uuid/dist/cjs/v5.d.ts +9 -0
  232. package/node_modules/uuid/dist/cjs/v5.js +14 -0
  233. package/node_modules/uuid/dist/cjs/v6.d.ts +4 -0
  234. package/node_modules/uuid/dist/cjs/v6.js +19 -0
  235. package/node_modules/uuid/dist/cjs/v6ToV1.d.ts +2 -0
  236. package/node_modules/uuid/dist/cjs/v6ToV1.js +13 -0
  237. package/node_modules/uuid/dist/cjs/v7.d.ts +9 -0
  238. package/node_modules/uuid/dist/cjs/v7.js +69 -0
  239. package/node_modules/uuid/dist/cjs/validate.d.ts +2 -0
  240. package/node_modules/uuid/dist/cjs/validate.js +7 -0
  241. package/node_modules/uuid/dist/cjs/version.d.ts +2 -0
  242. package/node_modules/uuid/dist/cjs/version.js +10 -0
  243. package/node_modules/uuid/dist/cjs-browser/index.d.ts +15 -0
  244. package/node_modules/uuid/dist/cjs-browser/index.js +31 -0
  245. package/node_modules/uuid/dist/cjs-browser/max.d.ts +2 -0
  246. package/node_modules/uuid/dist/cjs-browser/max.js +3 -0
  247. package/node_modules/uuid/dist/cjs-browser/md5.d.ts +2 -0
  248. package/node_modules/uuid/dist/cjs-browser/md5.js +137 -0
  249. package/node_modules/uuid/dist/cjs-browser/native.d.ts +4 -0
  250. package/node_modules/uuid/dist/cjs-browser/native.js +4 -0
  251. package/node_modules/uuid/dist/cjs-browser/nil.d.ts +2 -0
  252. package/node_modules/uuid/dist/cjs-browser/nil.js +3 -0
  253. package/node_modules/uuid/dist/cjs-browser/package.json +1 -0
  254. package/node_modules/uuid/dist/cjs-browser/parse.d.ts +2 -0
  255. package/node_modules/uuid/dist/cjs-browser/parse.js +11 -0
  256. package/node_modules/uuid/dist/cjs-browser/regex.d.ts +2 -0
  257. package/node_modules/uuid/dist/cjs-browser/regex.js +3 -0
  258. package/node_modules/uuid/dist/cjs-browser/rng.d.ts +1 -0
  259. package/node_modules/uuid/dist/cjs-browser/rng.js +14 -0
  260. package/node_modules/uuid/dist/cjs-browser/sha1.d.ts +2 -0
  261. package/node_modules/uuid/dist/cjs-browser/sha1.js +72 -0
  262. package/node_modules/uuid/dist/cjs-browser/stringify.d.ts +3 -0
  263. package/node_modules/uuid/dist/cjs-browser/stringify.js +39 -0
  264. package/node_modules/uuid/dist/cjs-browser/types.d.ts +21 -0
  265. package/node_modules/uuid/dist/cjs-browser/types.js +2 -0
  266. package/node_modules/uuid/dist/cjs-browser/uuid-bin.d.ts +1 -0
  267. package/node_modules/uuid/dist/cjs-browser/uuid-bin.js +72 -0
  268. package/node_modules/uuid/dist/cjs-browser/v1.d.ts +11 -0
  269. package/node_modules/uuid/dist/cjs-browser/v1.js +87 -0
  270. package/node_modules/uuid/dist/cjs-browser/v1ToV6.d.ts +2 -0
  271. package/node_modules/uuid/dist/cjs-browser/v1ToV6.js +13 -0
  272. package/node_modules/uuid/dist/cjs-browser/v3.d.ts +9 -0
  273. package/node_modules/uuid/dist/cjs-browser/v3.js +14 -0
  274. package/node_modules/uuid/dist/cjs-browser/v35.d.ts +7 -0
  275. package/node_modules/uuid/dist/cjs-browser/v35.js +41 -0
  276. package/node_modules/uuid/dist/cjs-browser/v4.d.ts +4 -0
  277. package/node_modules/uuid/dist/cjs-browser/v4.js +29 -0
  278. package/node_modules/uuid/dist/cjs-browser/v5.d.ts +9 -0
  279. package/node_modules/uuid/dist/cjs-browser/v5.js +14 -0
  280. package/node_modules/uuid/dist/cjs-browser/v6.d.ts +4 -0
  281. package/node_modules/uuid/dist/cjs-browser/v6.js +19 -0
  282. package/node_modules/uuid/dist/cjs-browser/v6ToV1.d.ts +2 -0
  283. package/node_modules/uuid/dist/cjs-browser/v6ToV1.js +13 -0
  284. package/node_modules/uuid/dist/cjs-browser/v7.d.ts +9 -0
  285. package/node_modules/uuid/dist/cjs-browser/v7.js +69 -0
  286. package/node_modules/uuid/dist/cjs-browser/validate.d.ts +2 -0
  287. package/node_modules/uuid/dist/cjs-browser/validate.js +7 -0
  288. package/node_modules/uuid/dist/cjs-browser/version.d.ts +2 -0
  289. package/node_modules/uuid/dist/cjs-browser/version.js +10 -0
  290. package/node_modules/uuid/dist/esm/bin/uuid +2 -0
  291. package/node_modules/uuid/dist/esm/index.d.ts +15 -0
  292. package/node_modules/uuid/dist/esm/index.js +14 -0
  293. package/node_modules/uuid/dist/esm/max.d.ts +2 -0
  294. package/node_modules/uuid/dist/esm/max.js +1 -0
  295. package/node_modules/uuid/dist/esm/md5.d.ts +4 -0
  296. package/node_modules/uuid/dist/esm/md5.js +11 -0
  297. package/node_modules/uuid/dist/esm/native.d.ts +6 -0
  298. package/node_modules/uuid/dist/esm/native.js +2 -0
  299. package/node_modules/uuid/dist/esm/nil.d.ts +2 -0
  300. package/node_modules/uuid/dist/esm/nil.js +1 -0
  301. package/node_modules/uuid/dist/esm/parse.d.ts +2 -0
  302. package/node_modules/uuid/dist/esm/parse.js +9 -0
  303. package/node_modules/uuid/dist/esm/regex.d.ts +2 -0
  304. package/node_modules/uuid/dist/esm/regex.js +1 -0
  305. package/node_modules/uuid/dist/esm/rng.d.ts +1 -0
  306. package/node_modules/uuid/dist/esm/rng.js +10 -0
  307. package/node_modules/uuid/dist/esm/sha1.d.ts +4 -0
  308. package/node_modules/uuid/dist/esm/sha1.js +11 -0
  309. package/node_modules/uuid/dist/esm/stringify.d.ts +3 -0
  310. package/node_modules/uuid/dist/esm/stringify.js +35 -0
  311. package/node_modules/uuid/dist/esm/types.d.ts +21 -0
  312. package/node_modules/uuid/dist/esm/types.js +1 -0
  313. package/node_modules/uuid/dist/esm/uuid-bin.d.ts +1 -0
  314. package/node_modules/uuid/dist/esm/uuid-bin.js +70 -0
  315. package/node_modules/uuid/dist/esm/v1.d.ts +11 -0
  316. package/node_modules/uuid/dist/esm/v1.js +83 -0
  317. package/node_modules/uuid/dist/esm/v1ToV6.d.ts +2 -0
  318. package/node_modules/uuid/dist/esm/v1ToV6.js +10 -0
  319. package/node_modules/uuid/dist/esm/v3.d.ts +9 -0
  320. package/node_modules/uuid/dist/esm/v3.js +9 -0
  321. package/node_modules/uuid/dist/esm/v35.d.ts +7 -0
  322. package/node_modules/uuid/dist/esm/v35.js +36 -0
  323. package/node_modules/uuid/dist/esm/v4.d.ts +4 -0
  324. package/node_modules/uuid/dist/esm/v4.js +27 -0
  325. package/node_modules/uuid/dist/esm/v5.d.ts +9 -0
  326. package/node_modules/uuid/dist/esm/v5.js +9 -0
  327. package/node_modules/uuid/dist/esm/v6.d.ts +4 -0
  328. package/node_modules/uuid/dist/esm/v6.js +17 -0
  329. package/node_modules/uuid/dist/esm/v6ToV1.d.ts +2 -0
  330. package/node_modules/uuid/dist/esm/v6ToV1.js +10 -0
  331. package/node_modules/uuid/dist/esm/v7.d.ts +9 -0
  332. package/node_modules/uuid/dist/esm/v7.js +65 -0
  333. package/node_modules/uuid/dist/esm/validate.d.ts +2 -0
  334. package/node_modules/uuid/dist/esm/validate.js +5 -0
  335. package/node_modules/uuid/dist/esm/version.d.ts +2 -0
  336. package/node_modules/uuid/dist/esm/version.js +8 -0
  337. package/node_modules/uuid/dist/esm-browser/index.d.ts +15 -0
  338. package/node_modules/uuid/dist/esm-browser/index.js +14 -0
  339. package/node_modules/uuid/dist/esm-browser/max.d.ts +2 -0
  340. package/node_modules/uuid/dist/esm-browser/max.js +1 -0
  341. package/node_modules/uuid/dist/esm-browser/md5.d.ts +2 -0
  342. package/node_modules/uuid/dist/esm-browser/md5.js +135 -0
  343. package/node_modules/uuid/dist/esm-browser/native.d.ts +4 -0
  344. package/node_modules/uuid/dist/esm-browser/native.js +2 -0
  345. package/node_modules/uuid/dist/esm-browser/nil.d.ts +2 -0
  346. package/node_modules/uuid/dist/esm-browser/nil.js +1 -0
  347. package/node_modules/uuid/dist/esm-browser/parse.d.ts +2 -0
  348. package/node_modules/uuid/dist/esm-browser/parse.js +9 -0
  349. package/node_modules/uuid/dist/esm-browser/regex.d.ts +2 -0
  350. package/node_modules/uuid/dist/esm-browser/regex.js +1 -0
  351. package/node_modules/uuid/dist/esm-browser/rng.d.ts +1 -0
  352. package/node_modules/uuid/dist/esm-browser/rng.js +11 -0
  353. package/node_modules/uuid/dist/esm-browser/sha1.d.ts +2 -0
  354. package/node_modules/uuid/dist/esm-browser/sha1.js +70 -0
  355. package/node_modules/uuid/dist/esm-browser/stringify.d.ts +3 -0
  356. package/node_modules/uuid/dist/esm-browser/stringify.js +35 -0
  357. package/node_modules/uuid/dist/esm-browser/types.d.ts +21 -0
  358. package/node_modules/uuid/dist/esm-browser/types.js +1 -0
  359. package/node_modules/uuid/dist/esm-browser/uuid-bin.d.ts +1 -0
  360. package/node_modules/uuid/dist/esm-browser/uuid-bin.js +70 -0
  361. package/node_modules/uuid/dist/esm-browser/v1.d.ts +11 -0
  362. package/node_modules/uuid/dist/esm-browser/v1.js +83 -0
  363. package/node_modules/uuid/dist/esm-browser/v1ToV6.d.ts +2 -0
  364. package/node_modules/uuid/dist/esm-browser/v1ToV6.js +10 -0
  365. package/node_modules/uuid/dist/esm-browser/v3.d.ts +9 -0
  366. package/node_modules/uuid/dist/esm-browser/v3.js +9 -0
  367. package/node_modules/uuid/dist/esm-browser/v35.d.ts +7 -0
  368. package/node_modules/uuid/dist/esm-browser/v35.js +36 -0
  369. package/node_modules/uuid/dist/esm-browser/v4.d.ts +4 -0
  370. package/node_modules/uuid/dist/esm-browser/v4.js +27 -0
  371. package/node_modules/uuid/dist/esm-browser/v5.d.ts +9 -0
  372. package/node_modules/uuid/dist/esm-browser/v5.js +9 -0
  373. package/node_modules/uuid/dist/esm-browser/v6.d.ts +4 -0
  374. package/node_modules/uuid/dist/esm-browser/v6.js +17 -0
  375. package/node_modules/uuid/dist/esm-browser/v6ToV1.d.ts +2 -0
  376. package/node_modules/uuid/dist/esm-browser/v6ToV1.js +10 -0
  377. package/node_modules/uuid/dist/esm-browser/v7.d.ts +9 -0
  378. package/node_modules/uuid/dist/esm-browser/v7.js +65 -0
  379. package/node_modules/uuid/dist/esm-browser/validate.d.ts +2 -0
  380. package/node_modules/uuid/dist/esm-browser/validate.js +5 -0
  381. package/node_modules/uuid/dist/esm-browser/version.d.ts +2 -0
  382. package/node_modules/uuid/dist/esm-browser/version.js +8 -0
  383. package/node_modules/uuid/package.json +132 -0
  384. package/package.json +17 -12
  385. package/scripts/cleanup-test-resources.ts +369 -0
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Cleanup and verification utilities for integration tests
3
+ *
4
+ * Provides functions for verifying resource deletion via Azure Resource Graph
5
+ * and finding/cleaning orphaned resources with comprehensive safety mechanisms.
6
+ */
7
+ /**
8
+ * Metadata for an individual resource created during testing
9
+ */
10
+ export interface ResourceMetadata {
11
+ /**
12
+ * Azure resource ID
13
+ */
14
+ readonly resourceId: string;
15
+ /**
16
+ * Azure resource type (e.g., 'Microsoft.Resources/resourceGroups')
17
+ */
18
+ readonly resourceType: string;
19
+ /**
20
+ * Resource name
21
+ */
22
+ readonly name: string;
23
+ /**
24
+ * Resource location (Azure region)
25
+ */
26
+ readonly location?: string;
27
+ /**
28
+ * Resource tags
29
+ */
30
+ readonly tags: Record<string, string>;
31
+ /**
32
+ * Test run ID that created this resource
33
+ */
34
+ readonly testRunId: string;
35
+ /**
36
+ * Timestamp when resource was created
37
+ */
38
+ readonly createdAt: Date;
39
+ /**
40
+ * Whether this resource was successfully destroyed
41
+ */
42
+ readonly destroyed?: boolean;
43
+ /**
44
+ * Timestamp when resource was destroyed
45
+ */
46
+ readonly destroyedAt?: Date;
47
+ }
48
+ /**
49
+ * Result of resource cleanup verification
50
+ */
51
+ export interface VerificationResult {
52
+ /**
53
+ * Whether verification succeeded (all resources deleted)
54
+ */
55
+ readonly success: boolean;
56
+ /**
57
+ * Human-readable message describing the result
58
+ */
59
+ readonly message: string;
60
+ /**
61
+ * List of orphaned resource IDs (if any)
62
+ */
63
+ readonly orphanedResources: string[];
64
+ /**
65
+ * Number of resources expected to be deleted
66
+ */
67
+ readonly expectedCount?: number;
68
+ /**
69
+ * Number of resources actually found
70
+ */
71
+ readonly foundCount?: number;
72
+ }
73
+ /**
74
+ * Options for cleanup operations
75
+ */
76
+ export interface CleanupOptions {
77
+ /**
78
+ * Whether to perform dry-run (no actual deletion)
79
+ */
80
+ readonly dryRun: boolean;
81
+ /**
82
+ * Minimum age in hours before resource can be cleaned up
83
+ */
84
+ readonly minAgeHours: number;
85
+ /**
86
+ * Azure subscription ID to target (optional)
87
+ */
88
+ readonly subscription?: string;
89
+ /**
90
+ * Specific resource groups to target (optional)
91
+ */
92
+ readonly resourceGroups?: string[];
93
+ /**
94
+ * Maximum number of resources to clean up in one operation
95
+ */
96
+ readonly maxResources?: number;
97
+ }
98
+ /**
99
+ * Orphaned resource information
100
+ */
101
+ export interface OrphanedResource {
102
+ /**
103
+ * Azure resource ID
104
+ */
105
+ readonly resourceId: string;
106
+ /**
107
+ * Azure resource type
108
+ */
109
+ readonly resourceType: string;
110
+ /**
111
+ * Resource name
112
+ */
113
+ readonly name: string;
114
+ /**
115
+ * Resource location
116
+ */
117
+ readonly location: string;
118
+ /**
119
+ * Resource group name
120
+ */
121
+ readonly resourceGroup: string;
122
+ /**
123
+ * Test run ID from tags
124
+ */
125
+ readonly testRunId: string;
126
+ /**
127
+ * Creation timestamp from tags
128
+ */
129
+ readonly createdAt: Date;
130
+ /**
131
+ * Cleanup after timestamp from tags
132
+ */
133
+ readonly cleanupAfter: Date;
134
+ /**
135
+ * Test name from tags
136
+ */
137
+ readonly testName: string;
138
+ /**
139
+ * Age in hours since creation
140
+ */
141
+ readonly ageHours: number;
142
+ }
143
+ /**
144
+ * Result of cleanup operation
145
+ */
146
+ export interface CleanupResult {
147
+ /**
148
+ * Number of resources successfully deleted
149
+ */
150
+ readonly deleted: number;
151
+ /**
152
+ * Number of resources that failed to delete
153
+ */
154
+ readonly failed: number;
155
+ /**
156
+ * Number of resources skipped (e.g., too young)
157
+ */
158
+ readonly skipped: number;
159
+ /**
160
+ * Detailed error messages for failures
161
+ */
162
+ readonly errors?: string[];
163
+ }
164
+ /**
165
+ * Main cleanup service class
166
+ */
167
+ export declare class ResourceCleanupService {
168
+ /**
169
+ * Checks if Azure CLI is available
170
+ */
171
+ checkAzureCliAvailable(): boolean;
172
+ /**
173
+ * Executes an Azure CLI command with error handling
174
+ */
175
+ private executeAzureCommand;
176
+ /**
177
+ * Queries Azure Resource Graph for resources by tags
178
+ *
179
+ * Returns empty array on errors for graceful degradation.
180
+ */
181
+ queryAzureResourcesByTags(tags: Record<string, string>, subscription?: string): any[];
182
+ }
183
+ /**
184
+ * Verifies that all resources with a specific test run ID are deleted
185
+ *
186
+ * Performs Azure Resource Graph query to check for remaining resources.
187
+ * Implements retry logic to handle Azure's eventual consistency.
188
+ *
189
+ * @param runId - Test run UUID to verify
190
+ * @param expectedResources - List of resources that should be deleted
191
+ * @param subscription - Optional subscription ID to query
192
+ * @returns Verification result with details
193
+ */
194
+ export declare function verifyResourcesDeleted(runId: string, expectedResources: ResourceMetadata[], subscription?: string): VerificationResult;
195
+ /**
196
+ * Finds orphaned test resources that are past their TTL
197
+ *
198
+ * Queries Azure for resources with test tags that are older than
199
+ * their cleanup-after timestamp.
200
+ *
201
+ * @param options - Cleanup options
202
+ * @returns List of orphaned resources
203
+ */
204
+ export declare function findOrphanedResources(options: CleanupOptions): Promise<OrphanedResource[]>;
205
+ /**
206
+ * Cleans up orphaned test resources
207
+ *
208
+ * Deletes resource groups containing orphaned test resources.
209
+ * Implements safety checks and dry-run mode.
210
+ *
211
+ * @param resources - List of orphaned resources to clean up
212
+ * @param options - Cleanup options
213
+ * @returns Cleanup result with statistics
214
+ */
215
+ export declare function cleanupOrphanedResources(resources: OrphanedResource[], options: CleanupOptions): Promise<CleanupResult>;
216
+ /**
217
+ * Verifies resource cleanup with retry logic for eventual consistency
218
+ *
219
+ * Wrapper around verifyResourcesDeleted that implements retry logic
220
+ * to handle Azure's eventual consistency delays.
221
+ *
222
+ * @param runId - Test run UUID to verify
223
+ * @param expectedResources - List of resources that should be deleted
224
+ * @param subscription - Optional subscription ID to query
225
+ * @param maxRetries - Maximum number of retry attempts
226
+ * @param retryWaitMs - Wait time between retries in milliseconds
227
+ * @returns Final verification result
228
+ */
229
+ export declare function verifyResourcesDeletedWithRetry(runId: string, expectedResources: ResourceMetadata[], subscription?: string, maxRetries?: number, retryWaitMs?: number): Promise<VerificationResult>;
@@ -0,0 +1,331 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ResourceCleanupService = void 0;
5
+ exports.verifyResourcesDeleted = verifyResourcesDeleted;
6
+ exports.findOrphanedResources = findOrphanedResources;
7
+ exports.cleanupOrphanedResources = cleanupOrphanedResources;
8
+ exports.verifyResourcesDeletedWithRetry = verifyResourcesDeletedWithRetry;
9
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
10
+ /**
11
+ * Cleanup and verification utilities for integration tests
12
+ *
13
+ * Provides functions for verifying resource deletion via Azure Resource Graph
14
+ * and finding/cleaning orphaned resources with comprehensive safety mechanisms.
15
+ */
16
+ const child_process_1 = require("child_process");
17
+ /**
18
+ * Minimum age threshold (hours) before cleanup is allowed
19
+ */
20
+ const MINIMUM_AGE_HOURS = 2;
21
+ /**
22
+ * Maximum retry attempts for eventual consistency
23
+ */
24
+ const MAX_RETRIES = 5;
25
+ /**
26
+ * Wait time between retries (milliseconds)
27
+ */
28
+ const RETRY_WAIT_MS = 30000; // 30 seconds
29
+ /**
30
+ * Main cleanup service class
31
+ */
32
+ class ResourceCleanupService {
33
+ /**
34
+ * Checks if Azure CLI is available
35
+ */
36
+ checkAzureCliAvailable() {
37
+ try {
38
+ (0, child_process_1.execSync)("az --version", { stdio: "pipe" });
39
+ return true;
40
+ }
41
+ catch (error) {
42
+ return false;
43
+ }
44
+ }
45
+ /**
46
+ * Executes an Azure CLI command with error handling
47
+ */
48
+ executeAzureCommand(command) {
49
+ try {
50
+ return (0, child_process_1.execSync)(command, {
51
+ encoding: "utf-8",
52
+ stdio: "pipe",
53
+ });
54
+ }
55
+ catch (error) {
56
+ throw new Error(`Azure CLI command failed: ${error.message}\n` +
57
+ `Command: ${command}\n` +
58
+ `Stderr: ${error.stderr?.toString() || "N/A"}`);
59
+ }
60
+ }
61
+ /**
62
+ * Queries Azure Resource Graph for resources by tags
63
+ *
64
+ * Returns empty array on errors for graceful degradation.
65
+ */
66
+ queryAzureResourcesByTags(tags, subscription) {
67
+ // Build tag filter conditions
68
+ const tagConditions = Object.entries(tags)
69
+ .map(([key, value]) => `tags['${key}'] == '${value}'`)
70
+ .join(" and ");
71
+ const query = `
72
+ Resources
73
+ | where ${tagConditions}
74
+ | project id, type, name, location, resourceGroup, tags
75
+ `;
76
+ const subscriptionArg = subscription
77
+ ? `--subscriptions "${subscription}"`
78
+ : "";
79
+ const command = `az graph query -q "${query.replace(/\n/g, " ")}" ${subscriptionArg} --output json`;
80
+ try {
81
+ const result = this.executeAzureCommand(command);
82
+ const parsed = JSON.parse(result);
83
+ return parsed.data || [];
84
+ }
85
+ catch (error) {
86
+ console.error("Failed to query Azure Resource Graph:", error.message);
87
+ return [];
88
+ }
89
+ }
90
+ }
91
+ exports.ResourceCleanupService = ResourceCleanupService;
92
+ _a = JSII_RTTI_SYMBOL_1;
93
+ ResourceCleanupService[_a] = { fqn: "@microsoft/terraform-cdk-constructs.ResourceCleanupService", version: "1.2.0" };
94
+ /**
95
+ * Verifies that all resources with a specific test run ID are deleted
96
+ *
97
+ * Performs Azure Resource Graph query to check for remaining resources.
98
+ * Implements retry logic to handle Azure's eventual consistency.
99
+ *
100
+ * @param runId - Test run UUID to verify
101
+ * @param expectedResources - List of resources that should be deleted
102
+ * @param subscription - Optional subscription ID to query
103
+ * @returns Verification result with details
104
+ */
105
+ function verifyResourcesDeleted(runId, expectedResources, subscription) {
106
+ const service = new ResourceCleanupService();
107
+ // Check if Azure CLI is available before attempting verification
108
+ if (!service.checkAzureCliAvailable()) {
109
+ return {
110
+ success: false,
111
+ message: "Verification failed: Azure CLI is not available",
112
+ orphanedResources: [],
113
+ expectedCount: expectedResources.length,
114
+ foundCount: -1,
115
+ };
116
+ }
117
+ try {
118
+ const orphanedResources = service.queryAzureResourcesByTags({ "test:run-id": runId }, subscription);
119
+ if (orphanedResources.length > 0) {
120
+ const resourceIds = orphanedResources.map((r) => r.id);
121
+ return {
122
+ success: false,
123
+ message: `Found ${orphanedResources.length} orphaned resources after destroy`,
124
+ orphanedResources: resourceIds,
125
+ expectedCount: expectedResources.length,
126
+ foundCount: orphanedResources.length,
127
+ };
128
+ }
129
+ return {
130
+ success: true,
131
+ message: "All resources successfully deleted",
132
+ orphanedResources: [],
133
+ expectedCount: expectedResources.length,
134
+ foundCount: 0,
135
+ };
136
+ }
137
+ catch (error) {
138
+ return {
139
+ success: false,
140
+ message: `Verification failed: ${error.message}`,
141
+ orphanedResources: [],
142
+ expectedCount: expectedResources.length,
143
+ foundCount: -1,
144
+ };
145
+ }
146
+ }
147
+ /**
148
+ * Finds orphaned test resources that are past their TTL
149
+ *
150
+ * Queries Azure for resources with test tags that are older than
151
+ * their cleanup-after timestamp.
152
+ *
153
+ * @param options - Cleanup options
154
+ * @returns List of orphaned resources
155
+ */
156
+ async function findOrphanedResources(options) {
157
+ const now = new Date();
158
+ console.log(`[Cleanup] Searching for orphaned test resources...`);
159
+ console.log(`[Cleanup] Minimum age: ${options.minAgeHours} hours`);
160
+ // Query for test resources
161
+ const query = `
162
+ Resources
163
+ | where tags['test:managed-by'] == 'terraform-cdk-constructs-tests'
164
+ | where tags['test:auto-cleanup'] == 'true'
165
+ | project id, type, name, location, resourceGroup,
166
+ testRunId = tags['test:run-id'],
167
+ createdAt = tags['test:created-at'],
168
+ cleanupAfter = tags['test:cleanup-after'],
169
+ testName = tags['test:name']
170
+ | order by tostring(createdAt) asc
171
+ `;
172
+ try {
173
+ const subscriptionArg = options.subscription
174
+ ? `--subscriptions "${options.subscription}"`
175
+ : "";
176
+ const command = `az graph query -q "${query.replace(/\n/g, " ")}" ${subscriptionArg} --output json`;
177
+ const result = (0, child_process_1.execSync)(command, {
178
+ encoding: "utf-8",
179
+ stdio: "pipe",
180
+ });
181
+ const parsed = JSON.parse(result);
182
+ const resources = parsed.data || [];
183
+ console.log(`[Cleanup] Found ${resources.length} test resources`);
184
+ // Filter by age and cleanup eligibility
185
+ const orphaned = [];
186
+ for (const resource of resources) {
187
+ const createdAt = new Date(resource.createdAt);
188
+ const cleanupAfter = new Date(resource.cleanupAfter);
189
+ const ageHours = (now.getTime() - createdAt.getTime()) / (60 * 60 * 1000);
190
+ // Apply safety checks
191
+ if (ageHours < MINIMUM_AGE_HOURS) {
192
+ console.log(`[Cleanup] Skipping ${resource.name}: too young (${ageHours.toFixed(1)}h < ${MINIMUM_AGE_HOURS}h)`);
193
+ continue;
194
+ }
195
+ if (now < cleanupAfter) {
196
+ console.log(`[Cleanup] Skipping ${resource.name}: not yet eligible for cleanup`);
197
+ continue;
198
+ }
199
+ if (ageHours < options.minAgeHours) {
200
+ console.log(`[Cleanup] Skipping ${resource.name}: younger than min age (${ageHours.toFixed(1)}h < ${options.minAgeHours}h)`);
201
+ continue;
202
+ }
203
+ orphaned.push({
204
+ resourceId: resource.id,
205
+ resourceType: resource.type,
206
+ name: resource.name,
207
+ location: resource.location,
208
+ resourceGroup: resource.resourceGroup,
209
+ testRunId: resource.testRunId,
210
+ createdAt,
211
+ cleanupAfter,
212
+ testName: resource.testName,
213
+ ageHours,
214
+ });
215
+ }
216
+ console.log(`[Cleanup] Found ${orphaned.length} orphaned resources eligible for cleanup`);
217
+ // Limit resources if specified
218
+ if (options.maxResources && orphaned.length > options.maxResources) {
219
+ console.log(`[Cleanup] Limiting to ${options.maxResources} resources`);
220
+ return orphaned.slice(0, options.maxResources);
221
+ }
222
+ return orphaned;
223
+ }
224
+ catch (error) {
225
+ console.error("[Cleanup] Failed to find orphaned resources:", error.message);
226
+ throw error;
227
+ }
228
+ }
229
+ /**
230
+ * Cleans up orphaned test resources
231
+ *
232
+ * Deletes resource groups containing orphaned test resources.
233
+ * Implements safety checks and dry-run mode.
234
+ *
235
+ * @param resources - List of orphaned resources to clean up
236
+ * @param options - Cleanup options
237
+ * @returns Cleanup result with statistics
238
+ */
239
+ async function cleanupOrphanedResources(resources, options) {
240
+ if (resources.length === 0) {
241
+ console.log("[Cleanup] No resources to clean up");
242
+ return { deleted: 0, failed: 0, skipped: 0 };
243
+ }
244
+ if (options.dryRun) {
245
+ console.log("[Cleanup] DRY RUN - Would delete the following resources:");
246
+ resources.forEach((r) => {
247
+ console.log(` - ${r.name} (${r.resourceType}) in ${r.resourceGroup} - Age: ${r.ageHours.toFixed(1)}h`);
248
+ });
249
+ return { deleted: 0, failed: 0, skipped: resources.length };
250
+ }
251
+ // Group resources by resource group for efficient deletion
252
+ const byResourceGroup = new Map();
253
+ for (const resource of resources) {
254
+ const group = byResourceGroup.get(resource.resourceGroup) || [];
255
+ group.push(resource);
256
+ byResourceGroup.set(resource.resourceGroup, group);
257
+ }
258
+ console.log(`[Cleanup] Deleting ${byResourceGroup.size} resource groups containing ${resources.length} resources`);
259
+ let deleted = 0;
260
+ let failed = 0;
261
+ const errors = [];
262
+ for (const [rgName, rgResources] of byResourceGroup) {
263
+ try {
264
+ console.log(`[Cleanup] Deleting resource group: ${rgName} (${rgResources.length} resources)`);
265
+ // Validate that all resources in the group are test resources
266
+ const allTestResources = rgResources.every((r) => r.testRunId && r.ageHours >= MINIMUM_AGE_HOURS);
267
+ if (!allTestResources) {
268
+ console.warn(`[Cleanup] Skipping ${rgName}: not all resources are valid test resources`);
269
+ failed += rgResources.length;
270
+ errors.push(`Resource group ${rgName} contains non-test resources`);
271
+ continue;
272
+ }
273
+ // Delete resource group (async, no-wait)
274
+ (0, child_process_1.execSync)(`az group delete --name "${rgName}" --yes --no-wait`, {
275
+ encoding: "utf-8",
276
+ stdio: "pipe",
277
+ });
278
+ deleted += rgResources.length;
279
+ console.log(`[Cleanup] ✓ Initiated deletion of ${rgName}`);
280
+ }
281
+ catch (error) {
282
+ console.error(`[Cleanup] ✗ Failed to delete ${rgName}:`, error.message);
283
+ failed += rgResources.length;
284
+ errors.push(`Failed to delete ${rgName}: ${error.message}`);
285
+ }
286
+ }
287
+ const result = {
288
+ deleted,
289
+ failed,
290
+ skipped: 0,
291
+ errors: errors.length > 0 ? errors : undefined,
292
+ };
293
+ console.log("[Cleanup] Summary:");
294
+ console.log(` - Deleted: ${result.deleted} resources`);
295
+ console.log(` - Failed: ${result.failed} resources`);
296
+ if (result.errors) {
297
+ console.log(` - Errors: ${result.errors.length}`);
298
+ }
299
+ return result;
300
+ }
301
+ /**
302
+ * Verifies resource cleanup with retry logic for eventual consistency
303
+ *
304
+ * Wrapper around verifyResourcesDeleted that implements retry logic
305
+ * to handle Azure's eventual consistency delays.
306
+ *
307
+ * @param runId - Test run UUID to verify
308
+ * @param expectedResources - List of resources that should be deleted
309
+ * @param subscription - Optional subscription ID to query
310
+ * @param maxRetries - Maximum number of retry attempts
311
+ * @param retryWaitMs - Wait time between retries in milliseconds
312
+ * @returns Final verification result
313
+ */
314
+ async function verifyResourcesDeletedWithRetry(runId, expectedResources, subscription, maxRetries = MAX_RETRIES, retryWaitMs = RETRY_WAIT_MS) {
315
+ let lastResult;
316
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
317
+ console.log(`[Verification] Attempt ${attempt}/${maxRetries}`);
318
+ lastResult = verifyResourcesDeleted(runId, expectedResources, subscription);
319
+ if (lastResult.success) {
320
+ console.log("[Verification] ✓ All resources confirmed deleted");
321
+ return lastResult;
322
+ }
323
+ if (attempt < maxRetries) {
324
+ console.log(`[Verification] Found ${lastResult.foundCount} resources, retrying in ${retryWaitMs / 1000}s...`);
325
+ await new Promise((resolve) => setTimeout(resolve, retryWaitMs));
326
+ }
327
+ }
328
+ console.error(`[Verification] ✗ Failed after ${maxRetries} attempts: ${lastResult.message}`);
329
+ return lastResult;
330
+ }
331
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xlYW51cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL2xpYi9jbGVhbnVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUF3U0Esd0RBbURDO0FBV0Qsc0RBb0dDO0FBWUQsNERBcUZDO0FBZUQsMEVBK0JDOztBQXpsQkQ7Ozs7O0dBS0c7QUFFSCxpREFBeUM7QUFnTXpDOztHQUVHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7QUFFNUI7O0dBRUc7QUFDSCxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7QUFFdEI7O0dBRUc7QUFDSCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsQ0FBQyxhQUFhO0FBRTFDOztHQUVHO0FBQ0gsTUFBYSxzQkFBc0I7SUFDakM7O09BRUc7SUFDSSxzQkFBc0I7UUFDM0IsSUFBSSxDQUFDO1lBQ0gsSUFBQSx3QkFBUSxFQUFDLGNBQWMsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzVDLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxtQkFBbUIsQ0FBQyxPQUFlO1FBQ3pDLElBQUksQ0FBQztZQUNILE9BQU8sSUFBQSx3QkFBUSxFQUFDLE9BQU8sRUFBRTtnQkFDdkIsUUFBUSxFQUFFLE9BQU87Z0JBQ2pCLEtBQUssRUFBRSxNQUFNO2FBQ2QsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7WUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FDYiw2QkFBNkIsS0FBSyxDQUFDLE9BQU8sSUFBSTtnQkFDNUMsWUFBWSxPQUFPLElBQUk7Z0JBQ3ZCLFdBQVcsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxLQUFLLEVBQUUsQ0FDakQsQ0FBQztRQUNK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LE9BQU8sR0FBRyxVQUFVLEVBQUUsQ0FBQztZQUN6QixPQUFPLENBQUMsR0FBRyxDQUNULHdCQUF3QixVQUFVLENBQUMsVUFBVSwyQkFBMkIsV0FBVyxHQUFHLElBQUksTUFBTSxDQUNqRyxDQUFDO1lBQ0YsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxDQUFDLEtBQUssQ0FDWCxpQ0FBaUMsVUFBVSxjQUFjLFVBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FDL0UsQ0FBQztJQUNGLE9BQU8sVUFBVyxDQUFDO0FBQ3JCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENsZWFudXAgYW5kIHZlcmlmaWNhdGlvbiB1dGlsaXRpZXMgZm9yIGludGVncmF0aW9uIHRlc3RzXG4gKlxuICogUHJvdmlkZXMgZnVuY3Rpb25zIGZvciB2ZXJpZnlpbmcgcmVzb3VyY2UgZGVsZXRpb24gdmlhIEF6dXJlIFJlc291cmNlIEdyYXBoXG4gKiBhbmQgZmluZGluZy9jbGVhbmluZyBvcnBoYW5lZCByZXNvdXJjZXMgd2l0aCBjb21wcmVoZW5zaXZlIHNhZmV0eSBtZWNoYW5pc21zLlxuICovXG5cbmltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcblxuLyoqXG4gKiBNZXRhZGF0YSBmb3IgYW4gaW5kaXZpZHVhbCByZXNvdXJjZSBjcmVhdGVkIGR1cmluZyB0ZXN0aW5nXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VNZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBBenVyZSByZXNvdXJjZSBJRFxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBenVyZSByZXNvdXJjZSB0eXBlIChlLmcuLCAnTWljcm9zb2Z0LlJlc291cmNlcy9yZXNvdXJjZUdyb3VwcycpXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZVR5cGU6IHN0cmluZztcblxuICAvKipcbiAgICogUmVzb3VyY2UgbmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZSBsb2NhdGlvbiAoQXp1cmUgcmVnaW9uKVxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIHRhZ3NcbiAgICovXG4gIHJlYWRvbmx5IHRhZ3M6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbiAgLyoqXG4gICAqIFRlc3QgcnVuIElEIHRoYXQgY3JlYXRlZCB0aGlzIHJlc291cmNlXG4gICAqL1xuICByZWFkb25seSB0ZXN0UnVuSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGltZXN0YW1wIHdoZW4gcmVzb3VyY2Ugd2FzIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IGNyZWF0ZWRBdDogRGF0ZTtcblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHJlc291cmNlIHdhcyBzdWNjZXNzZnVsbHkgZGVzdHJveWVkXG4gICAqL1xuICByZWFkb25seSBkZXN0cm95ZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaW1lc3RhbXAgd2hlbiByZXNvdXJjZSB3YXMgZGVzdHJveWVkXG4gICAqL1xuICByZWFkb25seSBkZXN0cm95ZWRBdD86IERhdGU7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIHJlc291cmNlIGNsZWFudXAgdmVyaWZpY2F0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVyaWZpY2F0aW9uUmVzdWx0IHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdmVyaWZpY2F0aW9uIHN1Y2NlZWRlZCAoYWxsIHJlc291cmNlcyBkZWxldGVkKVxuICAgKi9cbiAgcmVhZG9ubHkgc3VjY2VzczogYm9vbGVhbjtcblxuICAvKipcbiAgICogSHVtYW4tcmVhZGFibGUgbWVzc2FnZSBkZXNjcmliaW5nIHRoZSByZXN1bHRcbiAgICovXG4gIHJlYWRvbmx5IG1lc3NhZ2U6IHN0cmluZztcblxuICAvKipcbiAgICogTGlzdCBvZiBvcnBoYW5lZCByZXNvdXJjZSBJRHMgKGlmIGFueSlcbiAgICovXG4gIHJlYWRvbmx5IG9ycGhhbmVkUmVzb3VyY2VzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTnVtYmVyIG9mIHJlc291cmNlcyBleHBlY3RlZCB0byBiZSBkZWxldGVkXG4gICAqL1xuICByZWFkb25seSBleHBlY3RlZENvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgcmVzb3VyY2VzIGFjdHVhbGx5IGZvdW5kXG4gICAqL1xuICByZWFkb25seSBmb3VuZENvdW50PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGNsZWFudXAgb3BlcmF0aW9uc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIENsZWFudXBPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gcGVyZm9ybSBkcnktcnVuIChubyBhY3R1YWwgZGVsZXRpb24pXG4gICAqL1xuICByZWFkb25seSBkcnlSdW46IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE1pbmltdW0gYWdlIGluIGhvdXJzIGJlZm9yZSByZXNvdXJjZSBjYW4gYmUgY2xlYW5lZCB1cFxuICAgKi9cbiAgcmVhZG9ubHkgbWluQWdlSG91cnM6IG51bWJlcjtcblxuICAvKipcbiAgICogQXp1cmUgc3Vic2NyaXB0aW9uIElEIHRvIHRhcmdldCAob3B0aW9uYWwpXG4gICAqL1xuICByZWFkb25seSBzdWJzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmljIHJlc291cmNlIGdyb3VwcyB0byB0YXJnZXQgKG9wdGlvbmFsKVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VHcm91cHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2YgcmVzb3VyY2VzIHRvIGNsZWFuIHVwIGluIG9uZSBvcGVyYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IG1heFJlc291cmNlcz86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBPcnBoYW5lZCByZXNvdXJjZSBpbmZvcm1hdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9ycGhhbmVkUmVzb3VyY2Uge1xuICAvKipcbiAgICogQXp1cmUgcmVzb3VyY2UgSURcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogQXp1cmUgcmVzb3VyY2UgdHlwZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VUeXBlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogUmVzb3VyY2UgbG9jYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGxvY2F0aW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIGdyb3VwIG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlR3JvdXA6IHN0cmluZztcblxuICAvKipcbiAgICogVGVzdCBydW4gSUQgZnJvbSB0YWdzXG4gICAqL1xuICByZWFkb25seSB0ZXN0UnVuSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogQ3JlYXRpb24gdGltZXN0YW1wIGZyb20gdGFnc1xuICAgKi9cbiAgcmVhZG9ubHkgY3JlYXRlZEF0OiBEYXRlO1xuXG4gIC8qKlxuICAgKiBDbGVhbnVwIGFmdGVyIHRpbWVzdGFtcCBmcm9tIHRhZ3NcbiAgICovXG4gIHJlYWRvbmx5IGNsZWFudXBBZnRlcjogRGF0ZTtcblxuICAvKipcbiAgICogVGVzdCBuYW1lIGZyb20gdGFnc1xuICAgKi9cbiAgcmVhZG9ubHkgdGVzdE5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogQWdlIGluIGhvdXJzIHNpbmNlIGNyZWF0aW9uXG4gICAqL1xuICByZWFkb25seSBhZ2VIb3VyczogbnVtYmVyO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBjbGVhbnVwIG9wZXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsZWFudXBSZXN1bHQge1xuICAvKipcbiAgICogTnVtYmVyIG9mIHJlc291cmNlcyBzdWNjZXNzZnVsbHkgZGVsZXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgZGVsZXRlZDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgcmVzb3VyY2VzIHRoYXQgZmFpbGVkIHRvIGRlbGV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgZmFpbGVkOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiByZXNvdXJjZXMgc2tpcHBlZCAoZS5nLiwgdG9vIHlvdW5nKVxuICAgKi9cbiAgcmVhZG9ubHkgc2tpcHBlZDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBEZXRhaWxlZCBlcnJvciBtZXNzYWdlcyBmb3IgZmFpbHVyZXNcbiAgICovXG4gIHJlYWRvbmx5IGVycm9ycz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIE1pbmltdW0gYWdlIHRocmVzaG9sZCAoaG91cnMpIGJlZm9yZSBjbGVhbnVwIGlzIGFsbG93ZWRcbiAqL1xuY29uc3QgTUlOSU1VTV9BR0VfSE9VUlMgPSAyO1xuXG4vKipcbiAqIE1heGltdW0gcmV0cnkgYXR0ZW1wdHMgZm9yIGV2ZW50dWFsIGNvbnNpc3RlbmN5XG4gKi9cbmNvbnN0IE1BWF9SRVRSSUVTID0gNTtcblxuLyoqXG4gKiBXYWl0IHRpbWUgYmV0d2VlbiByZXRyaWVzIChtaWxsaXNlY29uZHMpXG4gKi9cbmNvbnN0IFJFVFJZX1dBSVRfTVMgPSAzMDAwMDsgLy8gMzAgc2Vjb25kc1xuXG4vKipcbiAqIE1haW4gY2xlYW51cCBzZXJ2aWNlIGNsYXNzXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXNvdXJjZUNsZWFudXBTZXJ2aWNlIHtcbiAgLyoqXG4gICAqIENoZWNrcyBpZiBBenVyZSBDTEkgaXMgYXZhaWxhYmxlXG4gICAqL1xuICBwdWJsaWMgY2hlY2tBenVyZUNsaUF2YWlsYWJsZSgpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZXhlY1N5bmMoXCJheiAtLXZlcnNpb25cIiwgeyBzdGRpbzogXCJwaXBlXCIgfSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyBhbiBBenVyZSBDTEkgY29tbWFuZCB3aXRoIGVycm9yIGhhbmRsaW5nXG4gICAqL1xuICBwcml2YXRlIGV4ZWN1dGVBenVyZUNvbW1hbmQoY29tbWFuZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGV4ZWNTeW5jKGNvbW1hbmQsIHtcbiAgICAgICAgZW5jb2Rpbmc6IFwidXRmLThcIixcbiAgICAgICAgc3RkaW86IFwicGlwZVwiLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQXp1cmUgQ0xJIGNvbW1hbmQgZmFpbGVkOiAke2Vycm9yLm1lc3NhZ2V9XFxuYCArXG4gICAgICAgICAgYENvbW1hbmQ6ICR7Y29tbWFuZH1cXG5gICtcbiAgICAgICAgICBgU3RkZXJyOiAke2Vycm9yLnN0ZGVycj8udG9TdHJpbmcoKSB8fCBcIk4vQVwifWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBRdWVyaWVzIEF6dXJlIFJlc291cmNlIEdyYXBoIGZvciByZXNvdXJjZXMgYnkgdGFnc1xuICAgKlxuICAgKiBSZXR1cm5zIGVtcHR5IGFycmF5IG9uIGVycm9ycyBmb3IgZ3JhY2VmdWwgZGVncmFkYXRpb24uXG4gICAqL1xuICBwdWJsaWMgcXVlcnlBenVyZVJlc291cmNlc0J5VGFncyhcbiAgICB0YWdzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgIHN1YnNjcmlwdGlvbj86IHN0cmluZyxcbiAgKTogYW55W10ge1xuICAgIC8vIEJ1aWxkIHRhZyBmaWx0ZXIgY29uZGl0aW9uc1xuICAgIGNvbnN0IHRhZ0NvbmRpdGlvbnMgPSBPYmplY3QuZW50cmllcyh0YWdzKVxuICAgICAgLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgdGFnc1snJHtrZXl9J10gPT0gJyR7dmFsdWV9J2ApXG4gICAgICAuam9pbihcIiBhbmQgXCIpO1xuXG4gICAgY29uc3QgcXVlcnkgPSBgXG4gICAgICBSZXNvdXJjZXNcbiAgICAgIHwgd2hlcmUgJHt0YWdDb25kaXRpb25zfVxuICAgICAgfCBwcm9qZWN0IGlkLCB0eXBlLCBuYW1lLCBsb2NhdGlvbiwgcmVzb3VyY2VHcm91cCwgdGFnc1xuICAgIGA7XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb25BcmcgPSBzdWJzY3JpcHRpb25cbiAgICAgID8gYC0tc3Vic2NyaXB0aW9ucyBcIiR7c3Vic2NyaXB0aW9ufVwiYFxuICAgICAgOiBcIlwiO1xuXG4gICAgY29uc3QgY29tbWFuZCA9IGBheiBncmFwaCBxdWVyeSAtcSBcIiR7cXVlcnkucmVwbGFjZSgvXFxuL2csIFwiIFwiKX1cIiAke3N1YnNjcmlwdGlvbkFyZ30gLS1vdXRwdXQganNvbmA7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5leGVjdXRlQXp1cmVDb21tYW5kKGNvbW1hbmQpO1xuICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyZXN1bHQpO1xuICAgICAgcmV0dXJuIHBhcnNlZC5kYXRhIHx8IFtdO1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gcXVlcnkgQXp1cmUgUmVzb3VyY2UgR3JhcGg6XCIsIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFZlcmlmaWVzIHRoYXQgYWxsIHJlc291cmNlcyB3aXRoIGEgc3BlY2lmaWMgdGVzdCBydW4gSUQgYXJlIGRlbGV0ZWRcbiAqXG4gKiBQZXJmb3JtcyBBenVyZSBSZXNvdXJjZSBHcmFwaCBxdWVyeSB0byBjaGVjayBmb3IgcmVtYWluaW5nIHJlc291cmNlcy5cbiAqIEltcGxlbWVudHMgcmV0cnkgbG9naWMgdG8gaGFuZGxlIEF6dXJlJ3MgZXZlbnR1YWwgY29uc2lzdGVuY3kuXG4gKlxuICogQHBhcmFtIHJ1bklkIC0gVGVzdCBydW4gVVVJRCB0byB2ZXJpZnlcbiAqIEBwYXJhbSBleHBlY3RlZFJlc291cmNlcyAtIExpc3Qgb2YgcmVzb3VyY2VzIHRoYXQgc2hvdWxkIGJlIGRlbGV0ZWRcbiAqIEBwYXJhbSBzdWJzY3JpcHRpb24gLSBPcHRpb25hbCBzdWJzY3JpcHRpb24gSUQgdG8gcXVlcnlcbiAqIEByZXR1cm5zIFZlcmlmaWNhdGlvbiByZXN1bHQgd2l0aCBkZXRhaWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJpZnlSZXNvdXJjZXNEZWxldGVkKFxuICBydW5JZDogc3RyaW5nLFxuICBleHBlY3RlZFJlc291cmNlczogUmVzb3VyY2VNZXRhZGF0YVtdLFxuICBzdWJzY3JpcHRpb24/OiBzdHJpbmcsXG4pOiBWZXJpZmljYXRpb25SZXN1bHQge1xuICBjb25zdCBzZXJ2aWNlID0gbmV3IFJlc291cmNlQ2xlYW51cFNlcnZpY2UoKTtcblxuICAvLyBDaGVjayBpZiBBenVyZSBDTEkgaXMgYXZhaWxhYmxlIGJlZm9yZSBhdHRlbXB0aW5nIHZlcmlmaWNhdGlvblxuICBpZiAoIXNlcnZpY2UuY2hlY2tBenVyZUNsaUF2YWlsYWJsZSgpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgbWVzc2FnZTogXCJWZXJpZmljYXRpb24gZmFpbGVkOiBBenVyZSBDTEkgaXMgbm90IGF2YWlsYWJsZVwiLFxuICAgICAgb3JwaGFuZWRSZXNvdXJjZXM6IFtdLFxuICAgICAgZXhwZWN0ZWRDb3VudDogZXhwZWN0ZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgZm91bmRDb3VudDogLTEsXG4gICAgfTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3Qgb3JwaGFuZWRSZXNvdXJjZXMgPSBzZXJ2aWNlLnF1ZXJ5QXp1cmVSZXNvdXJjZXNCeVRhZ3MoXG4gICAgICB7IFwidGVzdDpydW4taWRcIjogcnVuSWQgfSxcbiAgICAgIHN1YnNjcmlwdGlvbixcbiAgICApO1xuXG4gICAgaWYgKG9ycGhhbmVkUmVzb3VyY2VzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHJlc291cmNlSWRzID0gb3JwaGFuZWRSZXNvdXJjZXMubWFwKChyOiBhbnkpID0+IHIuaWQpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgIG1lc3NhZ2U6IGBGb3VuZCAke29ycGhhbmVkUmVzb3VyY2VzLmxlbmd0aH0gb3JwaGFuZWQgcmVzb3VyY2VzIGFmdGVyIGRlc3Ryb3lgLFxuICAgICAgICBvcnBoYW5lZFJlc291cmNlczogcmVzb3VyY2VJZHMsXG4gICAgICAgIGV4cGVjdGVkQ291bnQ6IGV4cGVjdGVkUmVzb3VyY2VzLmxlbmd0aCxcbiAgICAgICAgZm91bmRDb3VudDogb3JwaGFuZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgIG1lc3NhZ2U6IFwiQWxsIHJlc291cmNlcyBzdWNjZXNzZnVsbHkgZGVsZXRlZFwiLFxuICAgICAgb3JwaGFuZWRSZXNvdXJjZXM6IFtdLFxuICAgICAgZXhwZWN0ZWRDb3VudDogZXhwZWN0ZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgZm91bmRDb3VudDogMCxcbiAgICB9O1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgbWVzc2FnZTogYFZlcmlmaWNhdGlvbiBmYWlsZWQ6ICR7ZXJyb3IubWVzc2FnZX1gLFxuICAgICAgb3JwaGFuZWRSZXNvdXJjZXM6IFtdLFxuICAgICAgZXhwZWN0ZWRDb3VudDogZXhwZWN0ZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgZm91bmRDb3VudDogLTEsXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIEZpbmRzIG9ycGhhbmVkIHRlc3QgcmVzb3VyY2VzIHRoYXQgYXJlIHBhc3QgdGhlaXIgVFRMXG4gKlxuICogUXVlcmllcyBBenVyZSBmb3IgcmVzb3VyY2VzIHdpdGggdGVzdCB0YWdzIHRoYXQgYXJlIG9sZGVyIHRoYW5cbiAqIHRoZWlyIGNsZWFudXAtYWZ0ZXIgdGltZXN0YW1wLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gQ2xlYW51cCBvcHRpb25zXG4gKiBAcmV0dXJucyBMaXN0IG9mIG9ycGhhbmVkIHJlc291cmNlc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZE9ycGhhbmVkUmVzb3VyY2VzKFxuICBvcHRpb25zOiBDbGVhbnVwT3B0aW9ucyxcbik6IFByb21pc2U8T3JwaGFuZWRSZXNvdXJjZVtdPiB7XG4gIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG5cbiAgY29uc29sZS5sb2coYFtDbGVhbnVwXSBTZWFyY2hpbmcgZm9yIG9ycGhhbmVkIHRlc3QgcmVzb3VyY2VzLi4uYCk7XG4gIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0gTWluaW11bSBhZ2U6ICR7b3B0aW9ucy5taW5BZ2VIb3Vyc30gaG91cnNgKTtcblxuICAvLyBRdWVyeSBmb3IgdGVzdCByZXNvdXJjZXNcbiAgY29uc3QgcXVlcnkgPSBgXG4gICAgUmVzb3VyY2VzXG4gICAgfCB3aGVyZSB0YWdzWyd0ZXN0Om1hbmFnZWQtYnknXSA9PSAndGVycmFmb3JtLWNkay1jb25zdHJ1Y3RzLXRlc3RzJ1xuICAgIHwgd2hlcmUgdGFnc1sndGVzdDphdXRvLWNsZWFudXAnXSA9PSAndHJ1ZSdcbiAgICB8IHByb2plY3QgaWQsIHR5cGUsIG5hbWUsIGxvY2F0aW9uLCByZXNvdXJjZUdyb3VwLFxuICAgICAgICAgICAgICB0ZXN0UnVuSWQgPSB0YWdzWyd0ZXN0OnJ1bi1pZCddLFxuICAgICAgICAgICAgICBjcmVhdGVkQXQgPSB0YWdzWyd0ZXN0OmNyZWF0ZWQtYXQnXSxcbiAgICAgICAgICAgICAgY2xlYW51cEFmdGVyID0gdGFnc1sndGVzdDpjbGVhbnVwLWFmdGVyJ10sXG4gICAgICAgICAgICAgIHRlc3ROYW1lID0gdGFnc1sndGVzdDpuYW1lJ11cbiAgICB8IG9yZGVyIGJ5IHRvc3RyaW5nKGNyZWF0ZWRBdCkgYXNjXG4gIGA7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBzdWJzY3JpcHRpb25BcmcgPSBvcHRpb25zLnN1YnNjcmlwdGlvblxuICAgICAgPyBgLS1zdWJzY3JpcHRpb25zIFwiJHtvcHRpb25zLnN1YnNjcmlwdGlvbn1cImBcbiAgICAgIDogXCJcIjtcblxuICAgIGNvbnN0IGNvbW1hbmQgPSBgYXogZ3JhcGggcXVlcnkgLXEgXCIke3F1ZXJ5LnJlcGxhY2UoL1xcbi9nLCBcIiBcIil9XCIgJHtzdWJzY3JpcHRpb25Bcmd9IC0tb3V0cHV0IGpzb25gO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gZXhlY1N5bmMoY29tbWFuZCwge1xuICAgICAgZW5jb2Rpbmc6IFwidXRmLThcIixcbiAgICAgIHN0ZGlvOiBcInBpcGVcIixcbiAgICB9KTtcblxuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UocmVzdWx0KTtcbiAgICBjb25zdCByZXNvdXJjZXMgPSBwYXJzZWQuZGF0YSB8fCBbXTtcblxuICAgIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0gRm91bmQgJHtyZXNvdXJjZXMubGVuZ3RofSB0ZXN0IHJlc291cmNlc2ApO1xuXG4gICAgLy8gRmlsdGVyIGJ5IGFnZSBhbmQgY2xlYW51cCBlbGlnaWJpbGl0eVxuICAgIGNvbnN0IG9ycGhhbmVkOiBPcnBoYW5lZFJlc291cmNlW10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgcmVzb3VyY2VzKSB7XG4gICAgICBjb25zdCBjcmVhdGVkQXQgPSBuZXcgRGF0ZShyZXNvdXJjZS5jcmVhdGVkQXQpO1xuICAgICAgY29uc3QgY2xlYW51cEFmdGVyID0gbmV3IERhdGUocmVzb3VyY2UuY2xlYW51cEFmdGVyKTtcbiAgICAgIGNvbnN0IGFnZUhvdXJzID0gKG5vdy5nZXRUaW1lKCkgLSBjcmVhdGVkQXQuZ2V0VGltZSgpKSAvICg2MCAqIDYwICogMTAwMCk7XG5cbiAgICAgIC8vIEFwcGx5IHNhZmV0eSBjaGVja3NcbiAgICAgIGlmIChhZ2VIb3VycyA8IE1JTklNVU1fQUdFX0hPVVJTKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBbQ2xlYW51cF0gU2tpcHBpbmcgJHtyZXNvdXJjZS5uYW1lfTogdG9vIHlvdW5nICgke2FnZUhvdXJzLnRvRml4ZWQoMSl9aCA8ICR7TUlOSU1VTV9BR0VfSE9VUlN9aClgLFxuICAgICAgICApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5vdyA8IGNsZWFudXBBZnRlcikge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgW0NsZWFudXBdIFNraXBwaW5nICR7cmVzb3VyY2UubmFtZX06IG5vdCB5ZXQgZWxpZ2libGUgZm9yIGNsZWFudXBgLFxuICAgICAgICApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFnZUhvdXJzIDwgb3B0aW9ucy5taW5BZ2VIb3Vycykge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgW0NsZWFudXBdIFNraXBwaW5nICR7cmVzb3VyY2UubmFtZX06IHlvdW5nZXIgdGhhbiBtaW4gYWdlICgke2FnZUhvdXJzLnRvRml4ZWQoMSl9aCA8ICR7b3B0aW9ucy5taW5BZ2VIb3Vyc31oKWAsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBvcnBoYW5lZC5wdXNoKHtcbiAgICAgICAgcmVzb3VyY2VJZDogcmVzb3VyY2UuaWQsXG4gICAgICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2UudHlwZSxcbiAgICAgICAgbmFtZTogcmVzb3VyY2UubmFtZSxcbiAgICAgICAgbG9jYXRpb246IHJlc291cmNlLmxvY2F0aW9uLFxuICAgICAgICByZXNvdXJjZUdyb3VwOiByZXNvdXJjZS5yZXNvdXJjZUdyb3VwLFxuICAgICAgICB0ZXN0UnVuSWQ6IHJlc291cmNlLnRlc3RSdW5JZCxcbiAgICAgICAgY3JlYXRlZEF0LFxuICAgICAgICBjbGVhbnVwQWZ0ZXIsXG4gICAgICAgIHRlc3ROYW1lOiByZXNvdXJjZS50ZXN0TmFtZSxcbiAgICAgICAgYWdlSG91cnMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBbQ2xlYW51cF0gRm91bmQgJHtvcnBoYW5lZC5sZW5ndGh9IG9ycGhhbmVkIHJlc291cmNlcyBlbGlnaWJsZSBmb3IgY2xlYW51cGAsXG4gICAgKTtcblxuICAgIC8vIExpbWl0IHJlc291cmNlcyBpZiBzcGVjaWZpZWRcbiAgICBpZiAob3B0aW9ucy5tYXhSZXNvdXJjZXMgJiYgb3JwaGFuZWQubGVuZ3RoID4gb3B0aW9ucy5tYXhSZXNvdXJjZXMpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0gTGltaXRpbmcgdG8gJHtvcHRpb25zLm1heFJlc291cmNlc30gcmVzb3VyY2VzYCk7XG4gICAgICByZXR1cm4gb3JwaGFuZWQuc2xpY2UoMCwgb3B0aW9ucy5tYXhSZXNvdXJjZXMpO1xuICAgIH1cblxuICAgIHJldHVybiBvcnBoYW5lZDtcbiAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBcIltDbGVhbnVwXSBGYWlsZWQgdG8gZmluZCBvcnBoYW5lZCByZXNvdXJjZXM6XCIsXG4gICAgICBlcnJvci5tZXNzYWdlLFxuICAgICk7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBDbGVhbnMgdXAgb3JwaGFuZWQgdGVzdCByZXNvdXJjZXNcbiAqXG4gKiBEZWxldGVzIHJlc291cmNlIGdyb3VwcyBjb250YWluaW5nIG9ycGhhbmVkIHRlc3QgcmVzb3VyY2VzLlxuICogSW1wbGVtZW50cyBzYWZldHkgY2hlY2tzIGFuZCBkcnktcnVuIG1vZGUuXG4gKlxuICogQHBhcmFtIHJlc291cmNlcyAtIExpc3Qgb2Ygb3JwaGFuZWQgcmVzb3VyY2VzIHRvIGNsZWFuIHVwXG4gKiBAcGFyYW0gb3B0aW9ucyAtIENsZWFudXAgb3B0aW9uc1xuICogQHJldHVybnMgQ2xlYW51cCByZXN1bHQgd2l0aCBzdGF0aXN0aWNzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbGVhbnVwT3JwaGFuZWRSZXNvdXJjZXMoXG4gIHJlc291cmNlczogT3JwaGFuZWRSZXNvdXJjZVtdLFxuICBvcHRpb25zOiBDbGVhbnVwT3B0aW9ucyxcbik6IFByb21pc2U8Q2xlYW51cFJlc3VsdD4ge1xuICBpZiAocmVzb3VyY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIGNvbnNvbGUubG9nKFwiW0NsZWFudXBdIE5vIHJlc291cmNlcyB0byBjbGVhbiB1cFwiKTtcbiAgICByZXR1cm4geyBkZWxldGVkOiAwLCBmYWlsZWQ6IDAsIHNraXBwZWQ6IDAgfTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLmRyeVJ1bikge1xuICAgIGNvbnNvbGUubG9nKFwiW0NsZWFudXBdIERSWSBSVU4gLSBXb3VsZCBkZWxldGUgdGhlIGZvbGxvd2luZyByZXNvdXJjZXM6XCIpO1xuICAgIHJlc291cmNlcy5mb3JFYWNoKChyKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYCAgLSAke3IubmFtZX0gKCR7ci5yZXNvdXJjZVR5cGV9KSBpbiAke3IucmVzb3VyY2VHcm91cH0gLSBBZ2U6ICR7ci5hZ2VIb3Vycy50b0ZpeGVkKDEpfWhgLFxuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4geyBkZWxldGVkOiAwLCBmYWlsZWQ6IDAsIHNraXBwZWQ6IHJlc291cmNlcy5sZW5ndGggfTtcbiAgfVxuXG4gIC8vIEdyb3VwIHJlc291cmNlcyBieSByZXNvdXJjZSBncm91cCBmb3IgZWZmaWNpZW50IGRlbGV0aW9uXG4gIGNvbnN0IGJ5UmVzb3VyY2VHcm91cCA9IG5ldyBNYXA8c3RyaW5nLCBPcnBoYW5lZFJlc291cmNlW10+KCk7XG4gIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgcmVzb3VyY2VzKSB7XG4gICAgY29uc3QgZ3JvdXAgPSBieVJlc291cmNlR3JvdXAuZ2V0KHJlc291cmNlLnJlc291cmNlR3JvdXApIHx8IFtdO1xuICAgIGdyb3VwLnB1c2gocmVzb3VyY2UpO1xuICAgIGJ5UmVzb3VyY2VHcm91cC5zZXQocmVzb3VyY2UucmVzb3VyY2VHcm91cCwgZ3JvdXApO1xuICB9XG5cbiAgY29uc29sZS5sb2coXG4gICAgYFtDbGVhbnVwXSBEZWxldGluZyAke2J5UmVzb3VyY2VHcm91cC5zaXplfSByZXNvdXJjZSBncm91cHMgY29udGFpbmluZyAke3Jlc291cmNlcy5sZW5ndGh9IHJlc291cmNlc2AsXG4gICk7XG5cbiAgbGV0IGRlbGV0ZWQgPSAwO1xuICBsZXQgZmFpbGVkID0gMDtcbiAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgW3JnTmFtZSwgcmdSZXNvdXJjZXNdIG9mIGJ5UmVzb3VyY2VHcm91cCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYFtDbGVhbnVwXSBEZWxldGluZyByZXNvdXJjZSBncm91cDogJHtyZ05hbWV9ICgke3JnUmVzb3VyY2VzLmxlbmd0aH0gcmVzb3VyY2VzKWAsXG4gICAgICApO1xuXG4gICAgICAvLyBWYWxpZGF0ZSB0aGF0IGFsbCByZXNvdXJjZXMgaW4gdGhlIGdyb3VwIGFyZSB0ZXN0IHJlc291cmNlc1xuICAgICAgY29uc3QgYWxsVGVzdFJlc291cmNlcyA9IHJnUmVzb3VyY2VzLmV2ZXJ5KFxuICAgICAgICAocikgPT4gci50ZXN0UnVuSWQgJiYgci5hZ2VIb3VycyA+PSBNSU5JTVVNX0FHRV9IT1VSUyxcbiAgICAgICk7XG5cbiAgICAgIGlmICghYWxsVGVzdFJlc291cmNlcykge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYFtDbGVhbnVwXSBTa2lwcGluZyAke3JnTmFtZX06IG5vdCBhbGwgcmVzb3VyY2VzIGFyZSB2YWxpZCB0ZXN0IHJlc291cmNlc2AsXG4gICAgICAgICk7XG4gICAgICAgIGZhaWxlZCArPSByZ1Jlc291cmNlcy5sZW5ndGg7XG4gICAgICAgIGVycm9ycy5wdXNoKGBSZXNvdXJjZSBncm91cCAke3JnTmFtZX0gY29udGFpbnMgbm9uLXRlc3QgcmVzb3VyY2VzYCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBEZWxldGUgcmVzb3VyY2UgZ3JvdXAgKGFzeW5jLCBuby13YWl0KVxuICAgICAgZXhlY1N5bmMoYGF6IGdyb3VwIGRlbGV0ZSAtLW5hbWUgXCIke3JnTmFtZX1cIiAtLXllcyAtLW5vLXdhaXRgLCB7XG4gICAgICAgIGVuY29kaW5nOiBcInV0Zi04XCIsXG4gICAgICAgIHN0ZGlvOiBcInBpcGVcIixcbiAgICAgIH0pO1xuXG4gICAgICBkZWxldGVkICs9IHJnUmVzb3VyY2VzLmxlbmd0aDtcbiAgICAgIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0g4pyTIEluaXRpYXRlZCBkZWxldGlvbiBvZiAke3JnTmFtZX1gKTtcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBbQ2xlYW51cF0g4pyXIEZhaWxlZCB0byBkZWxldGUgJHtyZ05hbWV9OmAsIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgZmFpbGVkICs9IHJnUmVzb3VyY2VzLmxlbmd0aDtcbiAgICAgIGVycm9ycy5wdXNoKGBGYWlsZWQgdG8gZGVsZXRlICR7cmdOYW1lfTogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHJlc3VsdDogQ2xlYW51cFJlc3VsdCA9IHtcbiAgICBkZWxldGVkLFxuICAgIGZhaWxlZCxcbiAgICBza2lwcGVkOiAwLFxuICAgIGVycm9yczogZXJyb3JzLmxlbmd0aCA+IDAgPyBlcnJvcnMgOiB1bmRlZmluZWQsXG4gIH07XG5cbiAgY29uc29sZS5sb2coXCJbQ2xlYW51cF0gU3VtbWFyeTpcIik7XG4gIGNvbnNvbGUubG9nKGAgIC0gRGVsZXRlZDogJHtyZXN1bHQuZGVsZXRlZH0gcmVzb3VyY2VzYCk7XG4gIGNvbnNvbGUubG9nKGAgIC0gRmFpbGVkOiAke3Jlc3VsdC5mYWlsZWR9IHJlc291cmNlc2ApO1xuICBpZiAocmVzdWx0LmVycm9ycykge1xuICAgIGNvbnNvbGUubG9nKGAgIC0gRXJyb3JzOiAke3Jlc3VsdC5lcnJvcnMubGVuZ3RofWApO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBWZXJpZmllcyByZXNvdXJjZSBjbGVhbnVwIHdpdGggcmV0cnkgbG9naWMgZm9yIGV2ZW50dWFsIGNvbnNpc3RlbmN5XG4gKlxuICogV3JhcHBlciBhcm91bmQgdmVyaWZ5UmVzb3VyY2VzRGVsZXRlZCB0aGF0IGltcGxlbWVudHMgcmV0cnkgbG9naWNcbiAqIHRvIGhhbmRsZSBBenVyZSdzIGV2ZW50dWFsIGNvbnNpc3RlbmN5IGRlbGF5cy5cbiAqXG4gKiBAcGFyYW0gcnVuSWQgLSBUZXN0IHJ1biBVVUlEIHRvIHZlcmlmeVxuICogQHBhcmFtIGV4cGVjdGVkUmVzb3VyY2VzIC0gTGlzdCBvZiByZXNvdXJjZXMgdGhhdCBzaG91bGQgYmUgZGVsZXRlZFxuICogQHBhcmFtIHN1YnNjcmlwdGlvbiAtIE9wdGlvbmFsIHN1YnNjcmlwdGlvbiBJRCB0byBxdWVyeVxuICogQHBhcmFtIG1heFJldHJpZXMgLSBNYXhpbXVtIG51bWJlciBvZiByZXRyeSBhdHRlbXB0c1xuICogQHBhcmFtIHJldHJ5V2FpdE1zIC0gV2FpdCB0aW1lIGJldHdlZW4gcmV0cmllcyBpbiBtaWxsaXNlY29uZHNcbiAqIEByZXR1cm5zIEZpbmFsIHZlcmlmaWNhdGlvbiByZXN1bHRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZlcmlmeVJlc291cmNlc0RlbGV0ZWRXaXRoUmV0cnkoXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGV4cGVjdGVkUmVzb3VyY2VzOiBSZXNvdXJjZU1ldGFkYXRhW10sXG4gIHN1YnNjcmlwdGlvbj86IHN0cmluZyxcbiAgbWF4UmV0cmllczogbnVtYmVyID0gTUFYX1JFVFJJRVMsXG4gIHJldHJ5V2FpdE1zOiBudW1iZXIgPSBSRVRSWV9XQUlUX01TLFxuKTogUHJvbWlzZTxWZXJpZmljYXRpb25SZXN1bHQ+IHtcbiAgbGV0IGxhc3RSZXN1bHQ6IFZlcmlmaWNhdGlvblJlc3VsdDtcblxuICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSBtYXhSZXRyaWVzOyBhdHRlbXB0KyspIHtcbiAgICBjb25zb2xlLmxvZyhgW1ZlcmlmaWNhdGlvbl0gQXR0ZW1wdCAke2F0dGVtcHR9LyR7bWF4UmV0cmllc31gKTtcblxuICAgIGxhc3RSZXN1bHQgPSB2ZXJpZnlSZXNvdXJjZXNEZWxldGVkKHJ1bklkLCBleHBlY3RlZFJlc291cmNlcywgc3Vic2NyaXB0aW9uKTtcblxuICAgIGlmIChsYXN0UmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgIGNvbnNvbGUubG9nKFwiW1ZlcmlmaWNhdGlvbl0g4pyTIEFsbCByZXNvdXJjZXMgY29uZmlybWVkIGRlbGV0ZWRcIik7XG4gICAgICByZXR1cm4gbGFzdFJlc3VsdDtcbiAgICB9XG5cbiAgICBpZiAoYXR0ZW1wdCA8IG1heFJldHJpZXMpIHtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBgW1ZlcmlmaWNhdGlvbl0gRm91bmQgJHtsYXN0UmVzdWx0LmZvdW5kQ291bnR9IHJlc291cmNlcywgcmV0cnlpbmcgaW4gJHtyZXRyeVdhaXRNcyAvIDEwMDB9cy4uLmAsXG4gICAgICApO1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgcmV0cnlXYWl0TXMpKTtcbiAgICB9XG4gIH1cblxuICBjb25zb2xlLmVycm9yKFxuICAgIGBbVmVyaWZpY2F0aW9uXSDinJcgRmFpbGVkIGFmdGVyICR7bWF4UmV0cmllc30gYXR0ZW1wdHM6ICR7bGFzdFJlc3VsdCEubWVzc2FnZX1gLFxuICApO1xuICByZXR1cm4gbGFzdFJlc3VsdCE7XG59XG4iXX0=