@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.
- package/.jsii +60999 -15780
- package/API.md +54947 -10610
- package/README.md +72 -36
- package/docs/monitoring-guide.md +206 -0
- package/docs/testing.md +84 -1
- package/lib/azure-actiongroup/index.d.ts +11 -0
- package/lib/azure-actiongroup/index.js +28 -0
- package/lib/azure-actiongroup/lib/action-group-schemas.d.ts +24 -0
- package/lib/azure-actiongroup/lib/action-group-schemas.js +201 -0
- package/lib/azure-actiongroup/lib/action-group.d.ts +312 -0
- package/lib/azure-actiongroup/lib/action-group.js +201 -0
- package/lib/azure-actiongroup/lib/index.d.ts +5 -0
- package/lib/azure-actiongroup/lib/index.js +22 -0
- package/lib/azure-actiongroup/test/action-group.integ.d.ts +9 -0
- package/lib/azure-actiongroup/test/action-group.integ.js +79 -0
- package/lib/azure-actiongroup/test/action-group.spec.d.ts +8 -0
- package/lib/azure-actiongroup/test/action-group.spec.js +602 -0
- package/lib/azure-activitylogalert/index.d.ts +11 -0
- package/lib/azure-activitylogalert/index.js +28 -0
- package/lib/azure-activitylogalert/lib/activity-log-alert-schemas.d.ts +24 -0
- package/lib/azure-activitylogalert/lib/activity-log-alert-schemas.js +182 -0
- package/lib/azure-activitylogalert/lib/activity-log-alert.d.ts +236 -0
- package/lib/azure-activitylogalert/lib/activity-log-alert.js +212 -0
- package/lib/azure-activitylogalert/lib/index.d.ts +5 -0
- package/lib/azure-activitylogalert/lib/index.js +22 -0
- package/lib/azure-activitylogalert/test/activity-log-alert.integ.d.ts +9 -0
- package/lib/azure-activitylogalert/test/activity-log-alert.integ.js +98 -0
- package/lib/azure-activitylogalert/test/activity-log-alert.spec.d.ts +9 -0
- package/lib/azure-activitylogalert/test/activity-log-alert.spec.js +1101 -0
- package/lib/azure-aks/index.d.ts +9 -0
- package/lib/azure-aks/index.js +28 -0
- package/lib/azure-aks/lib/aks-cluster-schemas.d.ts +505 -0
- package/lib/azure-aks/lib/aks-cluster-schemas.js +572 -0
- package/lib/azure-aks/lib/aks-cluster.d.ts +395 -0
- package/lib/azure-aks/lib/aks-cluster.js +489 -0
- package/lib/azure-aks/lib/index.d.ts +11 -0
- package/lib/azure-aks/lib/index.js +38 -0
- package/lib/azure-aks/test/aks-cluster.integ.d.ts +9 -0
- package/lib/azure-aks/test/aks-cluster.integ.js +260 -0
- package/lib/azure-aks/test/aks-cluster.spec.d.ts +8 -0
- package/lib/azure-aks/test/aks-cluster.spec.js +1396 -0
- package/lib/azure-diagnosticsettings/index.d.ts +7 -0
- package/lib/azure-diagnosticsettings/index.js +24 -0
- package/lib/azure-diagnosticsettings/lib/diagnostic-settings-schemas.d.ts +50 -0
- package/lib/azure-diagnosticsettings/lib/diagnostic-settings-schemas.js +207 -0
- package/lib/azure-diagnosticsettings/lib/diagnostic-settings.d.ts +193 -0
- package/lib/azure-diagnosticsettings/lib/diagnostic-settings.js +200 -0
- package/lib/azure-diagnosticsettings/lib/index.d.ts +8 -0
- package/lib/azure-diagnosticsettings/lib/index.js +25 -0
- package/lib/azure-diagnosticsettings/test/diagnostic-settings.spec.d.ts +8 -0
- package/lib/azure-diagnosticsettings/test/diagnostic-settings.spec.js +432 -0
- package/lib/azure-metricalert/index.d.ts +11 -0
- package/lib/azure-metricalert/index.js +28 -0
- package/lib/azure-metricalert/lib/index.d.ts +5 -0
- package/lib/azure-metricalert/lib/index.js +22 -0
- package/lib/azure-metricalert/lib/metric-alert-schemas.d.ts +24 -0
- package/lib/azure-metricalert/lib/metric-alert-schemas.js +242 -0
- package/lib/azure-metricalert/lib/metric-alert.d.ts +344 -0
- package/lib/azure-metricalert/lib/metric-alert.js +252 -0
- package/lib/azure-metricalert/test/metric-alert.integ.d.ts +9 -0
- package/lib/azure-metricalert/test/metric-alert.integ.js +123 -0
- package/lib/azure-metricalert/test/metric-alert.spec.d.ts +9 -0
- package/lib/azure-metricalert/test/metric-alert.spec.js +1266 -0
- package/lib/azure-networkinterface/index.d.ts +4 -0
- package/lib/azure-networkinterface/index.js +21 -0
- package/lib/azure-networkinterface/lib/index.d.ts +6 -0
- package/lib/azure-networkinterface/lib/index.js +22 -0
- package/lib/azure-networkinterface/lib/network-interface-schemas.d.ts +32 -0
- package/lib/azure-networkinterface/lib/network-interface-schemas.js +222 -0
- package/lib/azure-networkinterface/lib/network-interface.d.ts +265 -0
- package/lib/azure-networkinterface/lib/network-interface.js +228 -0
- package/lib/azure-networkinterface/test/network-interface.integ.d.ts +9 -0
- package/lib/azure-networkinterface/test/network-interface.integ.js +102 -0
- package/lib/azure-networkinterface/test/network-interface.spec.d.ts +8 -0
- package/lib/azure-networkinterface/test/network-interface.spec.js +655 -0
- package/lib/azure-networksecuritygroup/index.d.ts +6 -0
- package/lib/azure-networksecuritygroup/index.js +23 -0
- package/lib/azure-networksecuritygroup/lib/index.d.ts +5 -0
- package/lib/azure-networksecuritygroup/lib/index.js +16 -0
- package/lib/azure-networksecuritygroup/lib/network-security-group-schemas.d.ts +32 -0
- package/lib/azure-networksecuritygroup/lib/network-security-group-schemas.js +198 -0
- package/lib/azure-networksecuritygroup/lib/network-security-group.d.ts +268 -0
- package/lib/azure-networksecuritygroup/lib/network-security-group.js +248 -0
- package/lib/azure-networksecuritygroup/test/network-security-group.integ.d.ts +9 -0
- package/lib/azure-networksecuritygroup/test/network-security-group.integ.js +151 -0
- package/lib/azure-networksecuritygroup/test/network-security-group.spec.d.ts +8 -0
- package/lib/azure-networksecuritygroup/test/network-security-group.spec.js +652 -0
- package/lib/azure-publicipaddress/index.d.ts +6 -0
- package/lib/azure-publicipaddress/index.js +23 -0
- package/lib/azure-publicipaddress/lib/index.d.ts +9 -0
- package/lib/azure-publicipaddress/lib/index.js +19 -0
- package/lib/azure-publicipaddress/lib/public-ip-address-schemas.d.ts +32 -0
- package/lib/azure-publicipaddress/lib/public-ip-address-schemas.js +227 -0
- package/lib/azure-publicipaddress/lib/public-ip-address.d.ts +256 -0
- package/lib/azure-publicipaddress/lib/public-ip-address.js +267 -0
- package/lib/azure-publicipaddress/test/public-ip-address.integ.d.ts +9 -0
- package/lib/azure-publicipaddress/test/public-ip-address.integ.js +75 -0
- package/lib/azure-publicipaddress/test/public-ip-address.spec.d.ts +15 -0
- package/lib/azure-publicipaddress/test/public-ip-address.spec.js +498 -0
- package/lib/azure-resourcegroup/lib/resource-group.js +1 -1
- package/lib/azure-resourcegroup/test/resource-group.integ.js +23 -11
- package/lib/azure-storageaccount/lib/storage-account-schemas.d.ts +98 -0
- package/lib/azure-storageaccount/lib/storage-account-schemas.js +1 -1
- package/lib/azure-storageaccount/lib/storage-account.d.ts +38 -1
- package/lib/azure-storageaccount/lib/storage-account.js +138 -2
- package/lib/azure-storageaccount/test/storage-account.integ.js +91 -12
- package/lib/azure-subnet/index.d.ts +4 -0
- package/lib/azure-subnet/index.js +21 -0
- package/lib/azure-subnet/lib/index.d.ts +5 -0
- package/lib/azure-subnet/lib/index.js +22 -0
- package/lib/azure-subnet/lib/subnet-schemas.d.ts +32 -0
- package/lib/azure-subnet/lib/subnet-schemas.js +237 -0
- package/lib/azure-subnet/lib/subnet.d.ts +285 -0
- package/lib/azure-subnet/lib/subnet.js +254 -0
- package/lib/azure-subnet/test/subnet.integ.d.ts +11 -0
- package/lib/azure-subnet/test/subnet.integ.js +80 -0
- package/lib/azure-subnet/test/subnet.spec.d.ts +8 -0
- package/lib/azure-subnet/test/subnet.spec.js +396 -0
- package/lib/azure-virtualmachine/index.d.ts +7 -0
- package/lib/azure-virtualmachine/index.js +24 -0
- package/lib/azure-virtualmachine/lib/index.d.ts +11 -0
- package/lib/azure-virtualmachine/lib/index.js +38 -0
- package/lib/azure-virtualmachine/lib/virtual-machine-schemas.d.ts +327 -0
- package/lib/azure-virtualmachine/lib/virtual-machine-schemas.js +544 -0
- package/lib/azure-virtualmachine/lib/virtual-machine.d.ts +377 -0
- package/lib/azure-virtualmachine/lib/virtual-machine.js +462 -0
- package/lib/azure-virtualmachine/test/virtual-machine.integ.d.ts +9 -0
- package/lib/azure-virtualmachine/test/virtual-machine.integ.js +220 -0
- package/lib/azure-virtualmachine/test/virtual-machine.spec.d.ts +9 -0
- package/lib/azure-virtualmachine/test/virtual-machine.spec.js +1032 -0
- package/lib/azure-virtualnetwork/index.d.ts +10 -0
- package/lib/azure-virtualnetwork/index.js +28 -0
- package/lib/azure-virtualnetwork/lib/index.d.ts +9 -0
- package/lib/azure-virtualnetwork/lib/index.js +22 -0
- package/lib/azure-virtualnetwork/lib/virtual-network-schemas.d.ts +32 -0
- package/lib/azure-virtualnetwork/lib/virtual-network-schemas.js +236 -0
- package/lib/azure-virtualnetwork/lib/virtual-network.d.ts +213 -0
- package/lib/azure-virtualnetwork/lib/virtual-network.js +245 -0
- package/lib/azure-virtualnetwork/test/virtual-network.integ.d.ts +9 -0
- package/lib/azure-virtualnetwork/test/virtual-network.integ.js +91 -0
- package/lib/azure-virtualnetwork/test/virtual-network.spec.d.ts +8 -0
- package/lib/azure-virtualnetwork/test/virtual-network.spec.js +398 -0
- package/lib/azure-vmss/index.d.ts +6 -0
- package/lib/azure-vmss/index.js +23 -0
- package/lib/azure-vmss/lib/index.d.ts +9 -0
- package/lib/azure-vmss/lib/index.js +39 -0
- package/lib/azure-vmss/lib/virtual-machine-scale-set.d.ts +258 -0
- package/lib/azure-vmss/lib/virtual-machine-scale-set.js +503 -0
- package/lib/azure-vmss/lib/vmss-schemas.d.ts +472 -0
- package/lib/azure-vmss/lib/vmss-schemas.js +444 -0
- package/lib/azure-vmss/test/virtual-machine-scale-set.integ.d.ts +15 -0
- package/lib/azure-vmss/test/virtual-machine-scale-set.integ.js +261 -0
- package/lib/azure-vmss/test/virtual-machine-scale-set.spec.d.ts +8 -0
- package/lib/azure-vmss/test/virtual-machine-scale-set.spec.js +997 -0
- package/lib/core-azure/lib/azapi/azapi-resource.d.ts +95 -27
- package/lib/core-azure/lib/azapi/azapi-resource.js +95 -58
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-client-config/index.d.ts +33 -21
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-client-config/index.js +69 -27
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource/index.d.ts +134 -120
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource/index.js +209 -59
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-action/index.d.ts +141 -128
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-action/index.js +183 -36
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-id/index.d.ts +55 -43
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-id/index.js +94 -26
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-list/index.d.ts +129 -116
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource-list/index.js +155 -32
- package/lib/core-azure/lib/azapi/providers-azapi/data-plane-resource/index.d.ts +187 -174
- package/lib/core-azure/lib/azapi/providers-azapi/data-plane-resource/index.js +267 -48
- package/lib/core-azure/lib/azapi/providers-azapi/index.d.ts +10 -10
- package/lib/core-azure/lib/azapi/providers-azapi/index.js +1 -1
- package/lib/core-azure/lib/azapi/providers-azapi/lazy-index.d.ts +0 -0
- package/lib/core-azure/lib/azapi/providers-azapi/lazy-index.js +13 -0
- package/lib/core-azure/lib/azapi/providers-azapi/provider/index.d.ts +174 -162
- package/lib/core-azure/lib/azapi/providers-azapi/provider/index.js +274 -14
- package/lib/core-azure/lib/azapi/providers-azapi/resource/index.d.ts +239 -225
- package/lib/core-azure/lib/azapi/providers-azapi/resource/index.js +360 -76
- package/lib/core-azure/lib/azapi/providers-azapi/resource-action/index.d.ts +163 -150
- package/lib/core-azure/lib/azapi/providers-azapi/resource-action/index.js +221 -46
- package/lib/core-azure/lib/azapi/providers-azapi/update-resource/index.d.ts +162 -149
- package/lib/core-azure/lib/azapi/providers-azapi/update-resource/index.js +249 -50
- package/lib/core-azure/lib/azapi/schema-mapper/schema-mapper.js +4 -2
- package/lib/core-azure/lib/version-manager/api-version-manager.js +1 -1
- package/lib/core-azure/lib/version-manager/interfaces/version-interfaces.js +7 -7
- package/lib/index.d.ts +37 -0
- package/lib/index.js +40 -2
- package/lib/testing/index.d.ts +92 -2
- package/lib/testing/index.js +258 -18
- package/lib/testing/lib/cleanup.d.ts +229 -0
- package/lib/testing/lib/cleanup.js +331 -0
- package/lib/testing/lib/metadata.d.ts +151 -0
- package/lib/testing/lib/metadata.js +180 -0
- package/lib/testing/lib/naming.d.ts +96 -0
- package/lib/testing/lib/naming.js +336 -0
- package/node_modules/uuid/LICENSE.md +9 -0
- package/node_modules/uuid/README.md +510 -0
- package/node_modules/uuid/dist/cjs/index.d.ts +15 -0
- package/node_modules/uuid/dist/cjs/index.js +31 -0
- package/node_modules/uuid/dist/cjs/max.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/max.js +3 -0
- package/node_modules/uuid/dist/cjs/md5.d.ts +4 -0
- package/node_modules/uuid/dist/cjs/md5.js +13 -0
- package/node_modules/uuid/dist/cjs/native.d.ts +6 -0
- package/node_modules/uuid/dist/cjs/native.js +4 -0
- package/node_modules/uuid/dist/cjs/nil.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/nil.js +3 -0
- package/node_modules/uuid/dist/cjs/package.json +1 -0
- package/node_modules/uuid/dist/cjs/parse.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/parse.js +11 -0
- package/node_modules/uuid/dist/cjs/regex.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/regex.js +3 -0
- package/node_modules/uuid/dist/cjs/rng.d.ts +1 -0
- package/node_modules/uuid/dist/cjs/rng.js +13 -0
- package/node_modules/uuid/dist/cjs/sha1.d.ts +4 -0
- package/node_modules/uuid/dist/cjs/sha1.js +13 -0
- package/node_modules/uuid/dist/cjs/stringify.d.ts +3 -0
- package/node_modules/uuid/dist/cjs/stringify.js +39 -0
- package/node_modules/uuid/dist/cjs/types.d.ts +21 -0
- package/node_modules/uuid/dist/cjs/types.js +2 -0
- package/node_modules/uuid/dist/cjs/uuid-bin.d.ts +1 -0
- package/node_modules/uuid/dist/cjs/uuid-bin.js +72 -0
- package/node_modules/uuid/dist/cjs/v1.d.ts +11 -0
- package/node_modules/uuid/dist/cjs/v1.js +87 -0
- package/node_modules/uuid/dist/cjs/v1ToV6.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/v1ToV6.js +13 -0
- package/node_modules/uuid/dist/cjs/v3.d.ts +9 -0
- package/node_modules/uuid/dist/cjs/v3.js +14 -0
- package/node_modules/uuid/dist/cjs/v35.d.ts +7 -0
- package/node_modules/uuid/dist/cjs/v35.js +41 -0
- package/node_modules/uuid/dist/cjs/v4.d.ts +4 -0
- package/node_modules/uuid/dist/cjs/v4.js +29 -0
- package/node_modules/uuid/dist/cjs/v5.d.ts +9 -0
- package/node_modules/uuid/dist/cjs/v5.js +14 -0
- package/node_modules/uuid/dist/cjs/v6.d.ts +4 -0
- package/node_modules/uuid/dist/cjs/v6.js +19 -0
- package/node_modules/uuid/dist/cjs/v6ToV1.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/v6ToV1.js +13 -0
- package/node_modules/uuid/dist/cjs/v7.d.ts +9 -0
- package/node_modules/uuid/dist/cjs/v7.js +69 -0
- package/node_modules/uuid/dist/cjs/validate.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/validate.js +7 -0
- package/node_modules/uuid/dist/cjs/version.d.ts +2 -0
- package/node_modules/uuid/dist/cjs/version.js +10 -0
- package/node_modules/uuid/dist/cjs-browser/index.d.ts +15 -0
- package/node_modules/uuid/dist/cjs-browser/index.js +31 -0
- package/node_modules/uuid/dist/cjs-browser/max.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/max.js +3 -0
- package/node_modules/uuid/dist/cjs-browser/md5.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/md5.js +137 -0
- package/node_modules/uuid/dist/cjs-browser/native.d.ts +4 -0
- package/node_modules/uuid/dist/cjs-browser/native.js +4 -0
- package/node_modules/uuid/dist/cjs-browser/nil.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/nil.js +3 -0
- package/node_modules/uuid/dist/cjs-browser/package.json +1 -0
- package/node_modules/uuid/dist/cjs-browser/parse.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/parse.js +11 -0
- package/node_modules/uuid/dist/cjs-browser/regex.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/regex.js +3 -0
- package/node_modules/uuid/dist/cjs-browser/rng.d.ts +1 -0
- package/node_modules/uuid/dist/cjs-browser/rng.js +14 -0
- package/node_modules/uuid/dist/cjs-browser/sha1.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/sha1.js +72 -0
- package/node_modules/uuid/dist/cjs-browser/stringify.d.ts +3 -0
- package/node_modules/uuid/dist/cjs-browser/stringify.js +39 -0
- package/node_modules/uuid/dist/cjs-browser/types.d.ts +21 -0
- package/node_modules/uuid/dist/cjs-browser/types.js +2 -0
- package/node_modules/uuid/dist/cjs-browser/uuid-bin.d.ts +1 -0
- package/node_modules/uuid/dist/cjs-browser/uuid-bin.js +72 -0
- package/node_modules/uuid/dist/cjs-browser/v1.d.ts +11 -0
- package/node_modules/uuid/dist/cjs-browser/v1.js +87 -0
- package/node_modules/uuid/dist/cjs-browser/v1ToV6.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/v1ToV6.js +13 -0
- package/node_modules/uuid/dist/cjs-browser/v3.d.ts +9 -0
- package/node_modules/uuid/dist/cjs-browser/v3.js +14 -0
- package/node_modules/uuid/dist/cjs-browser/v35.d.ts +7 -0
- package/node_modules/uuid/dist/cjs-browser/v35.js +41 -0
- package/node_modules/uuid/dist/cjs-browser/v4.d.ts +4 -0
- package/node_modules/uuid/dist/cjs-browser/v4.js +29 -0
- package/node_modules/uuid/dist/cjs-browser/v5.d.ts +9 -0
- package/node_modules/uuid/dist/cjs-browser/v5.js +14 -0
- package/node_modules/uuid/dist/cjs-browser/v6.d.ts +4 -0
- package/node_modules/uuid/dist/cjs-browser/v6.js +19 -0
- package/node_modules/uuid/dist/cjs-browser/v6ToV1.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/v6ToV1.js +13 -0
- package/node_modules/uuid/dist/cjs-browser/v7.d.ts +9 -0
- package/node_modules/uuid/dist/cjs-browser/v7.js +69 -0
- package/node_modules/uuid/dist/cjs-browser/validate.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/validate.js +7 -0
- package/node_modules/uuid/dist/cjs-browser/version.d.ts +2 -0
- package/node_modules/uuid/dist/cjs-browser/version.js +10 -0
- package/node_modules/uuid/dist/esm/bin/uuid +2 -0
- package/node_modules/uuid/dist/esm/index.d.ts +15 -0
- package/node_modules/uuid/dist/esm/index.js +14 -0
- package/node_modules/uuid/dist/esm/max.d.ts +2 -0
- package/node_modules/uuid/dist/esm/max.js +1 -0
- package/node_modules/uuid/dist/esm/md5.d.ts +4 -0
- package/node_modules/uuid/dist/esm/md5.js +11 -0
- package/node_modules/uuid/dist/esm/native.d.ts +6 -0
- package/node_modules/uuid/dist/esm/native.js +2 -0
- package/node_modules/uuid/dist/esm/nil.d.ts +2 -0
- package/node_modules/uuid/dist/esm/nil.js +1 -0
- package/node_modules/uuid/dist/esm/parse.d.ts +2 -0
- package/node_modules/uuid/dist/esm/parse.js +9 -0
- package/node_modules/uuid/dist/esm/regex.d.ts +2 -0
- package/node_modules/uuid/dist/esm/regex.js +1 -0
- package/node_modules/uuid/dist/esm/rng.d.ts +1 -0
- package/node_modules/uuid/dist/esm/rng.js +10 -0
- package/node_modules/uuid/dist/esm/sha1.d.ts +4 -0
- package/node_modules/uuid/dist/esm/sha1.js +11 -0
- package/node_modules/uuid/dist/esm/stringify.d.ts +3 -0
- package/node_modules/uuid/dist/esm/stringify.js +35 -0
- package/node_modules/uuid/dist/esm/types.d.ts +21 -0
- package/node_modules/uuid/dist/esm/types.js +1 -0
- package/node_modules/uuid/dist/esm/uuid-bin.d.ts +1 -0
- package/node_modules/uuid/dist/esm/uuid-bin.js +70 -0
- package/node_modules/uuid/dist/esm/v1.d.ts +11 -0
- package/node_modules/uuid/dist/esm/v1.js +83 -0
- package/node_modules/uuid/dist/esm/v1ToV6.d.ts +2 -0
- package/node_modules/uuid/dist/esm/v1ToV6.js +10 -0
- package/node_modules/uuid/dist/esm/v3.d.ts +9 -0
- package/node_modules/uuid/dist/esm/v3.js +9 -0
- package/node_modules/uuid/dist/esm/v35.d.ts +7 -0
- package/node_modules/uuid/dist/esm/v35.js +36 -0
- package/node_modules/uuid/dist/esm/v4.d.ts +4 -0
- package/node_modules/uuid/dist/esm/v4.js +27 -0
- package/node_modules/uuid/dist/esm/v5.d.ts +9 -0
- package/node_modules/uuid/dist/esm/v5.js +9 -0
- package/node_modules/uuid/dist/esm/v6.d.ts +4 -0
- package/node_modules/uuid/dist/esm/v6.js +17 -0
- package/node_modules/uuid/dist/esm/v6ToV1.d.ts +2 -0
- package/node_modules/uuid/dist/esm/v6ToV1.js +10 -0
- package/node_modules/uuid/dist/esm/v7.d.ts +9 -0
- package/node_modules/uuid/dist/esm/v7.js +65 -0
- package/node_modules/uuid/dist/esm/validate.d.ts +2 -0
- package/node_modules/uuid/dist/esm/validate.js +5 -0
- package/node_modules/uuid/dist/esm/version.d.ts +2 -0
- package/node_modules/uuid/dist/esm/version.js +8 -0
- package/node_modules/uuid/dist/esm-browser/index.d.ts +15 -0
- package/node_modules/uuid/dist/esm-browser/index.js +14 -0
- package/node_modules/uuid/dist/esm-browser/max.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/max.js +1 -0
- package/node_modules/uuid/dist/esm-browser/md5.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/md5.js +135 -0
- package/node_modules/uuid/dist/esm-browser/native.d.ts +4 -0
- package/node_modules/uuid/dist/esm-browser/native.js +2 -0
- package/node_modules/uuid/dist/esm-browser/nil.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/nil.js +1 -0
- package/node_modules/uuid/dist/esm-browser/parse.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/parse.js +9 -0
- package/node_modules/uuid/dist/esm-browser/regex.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/regex.js +1 -0
- package/node_modules/uuid/dist/esm-browser/rng.d.ts +1 -0
- package/node_modules/uuid/dist/esm-browser/rng.js +11 -0
- package/node_modules/uuid/dist/esm-browser/sha1.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/sha1.js +70 -0
- package/node_modules/uuid/dist/esm-browser/stringify.d.ts +3 -0
- package/node_modules/uuid/dist/esm-browser/stringify.js +35 -0
- package/node_modules/uuid/dist/esm-browser/types.d.ts +21 -0
- package/node_modules/uuid/dist/esm-browser/types.js +1 -0
- package/node_modules/uuid/dist/esm-browser/uuid-bin.d.ts +1 -0
- package/node_modules/uuid/dist/esm-browser/uuid-bin.js +70 -0
- package/node_modules/uuid/dist/esm-browser/v1.d.ts +11 -0
- package/node_modules/uuid/dist/esm-browser/v1.js +83 -0
- package/node_modules/uuid/dist/esm-browser/v1ToV6.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/v1ToV6.js +10 -0
- package/node_modules/uuid/dist/esm-browser/v3.d.ts +9 -0
- package/node_modules/uuid/dist/esm-browser/v3.js +9 -0
- package/node_modules/uuid/dist/esm-browser/v35.d.ts +7 -0
- package/node_modules/uuid/dist/esm-browser/v35.js +36 -0
- package/node_modules/uuid/dist/esm-browser/v4.d.ts +4 -0
- package/node_modules/uuid/dist/esm-browser/v4.js +27 -0
- package/node_modules/uuid/dist/esm-browser/v5.d.ts +9 -0
- package/node_modules/uuid/dist/esm-browser/v5.js +9 -0
- package/node_modules/uuid/dist/esm-browser/v6.d.ts +4 -0
- package/node_modules/uuid/dist/esm-browser/v6.js +17 -0
- package/node_modules/uuid/dist/esm-browser/v6ToV1.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/v6ToV1.js +10 -0
- package/node_modules/uuid/dist/esm-browser/v7.d.ts +9 -0
- package/node_modules/uuid/dist/esm-browser/v7.js +65 -0
- package/node_modules/uuid/dist/esm-browser/validate.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/validate.js +5 -0
- package/node_modules/uuid/dist/esm-browser/version.d.ts +2 -0
- package/node_modules/uuid/dist/esm-browser/version.js +8 -0
- package/node_modules/uuid/package.json +132 -0
- package/package.json +17 -12
- 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xlYW51cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL2xpYi9jbGVhbnVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUF3U0Esd0RBbURDO0FBV0Qsc0RBb0dDO0FBWUQsNERBcUZDO0FBZUQsMEVBK0JDOztBQXpsQkQ7Ozs7O0dBS0c7QUFFSCxpREFBeUM7QUFnTXpDOztHQUVHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7QUFFNUI7O0dBRUc7QUFDSCxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7QUFFdEI7O0dBRUc7QUFDSCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsQ0FBQyxhQUFhO0FBRTFDOztHQUVHO0FBQ0gsTUFBYSxzQkFBc0I7SUFDakM7O09BRUc7SUFDSSxzQkFBc0I7UUFDM0IsSUFBSSxDQUFDO1lBQ0gsSUFBQSx3QkFBUSxFQUFDLGNBQWMsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzVDLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxtQkFBbUIsQ0FBQyxPQUFlO1FBQ3pDLElBQUksQ0FBQztZQUNILE9BQU8sSUFBQSx3QkFBUSxFQUFDLE9BQU8sRUFBRTtnQkFDdkIsUUFBUSxFQUFFLE9BQU87Z0JBQ2pCLEtBQUssRUFBRSxNQUFNO2FBQ2QsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7WUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FDYiw2QkFBNkIsS0FBSyxDQUFDLE9BQU8sSUFBSTtnQkFDNUMsWUFBWSxPQUFPLElBQUk7Z0JBQ3ZCLFdBQVcsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxLQUFLLEVBQUUsQ0FDakQsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLHlCQUF5QixDQUM5QixJQUE0QixFQUM1QixZQUFxQjtRQUVyQiw4QkFBOEI7UUFDOUIsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7YUFDdkMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLFNBQVMsR0FBRyxVQUFVLEtBQUssR0FBRyxDQUFDO2FBQ3JELElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqQixNQUFNLEtBQUssR0FBRzs7Z0JBRUYsYUFBYTs7S0FFeEIsQ0FBQztRQUVGLE1BQU0sZUFBZSxHQUFHLFlBQVk7WUFDbEMsQ0FBQyxDQUFDLG9CQUFvQixZQUFZLEdBQUc7WUFDckMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUVQLE1BQU0sT0FBTyxHQUFHLHNCQUFzQixLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxlQUFlLGdCQUFnQixDQUFDO1FBRXBHLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNqRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2xDLE9BQU8sTUFBTSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7UUFDM0IsQ0FBQztRQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7WUFDcEIsT0FBTyxDQUFDLEtBQUssQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEUsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO0lBQ0gsQ0FBQzs7QUFqRUgsd0RBa0VDOzs7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsU0FBZ0Isc0JBQXNCLENBQ3BDLEtBQWEsRUFDYixpQkFBcUMsRUFDckMsWUFBcUI7SUFFckIsTUFBTSxPQUFPLEdBQUcsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO0lBRTdDLGlFQUFpRTtJQUNqRSxJQUFJLENBQUMsT0FBTyxDQUFDLHNCQUFzQixFQUFFLEVBQUUsQ0FBQztRQUN0QyxPQUFPO1lBQ0wsT0FBTyxFQUFFLEtBQUs7WUFDZCxPQUFPLEVBQUUsaURBQWlEO1lBQzFELGlCQUFpQixFQUFFLEVBQUU7WUFDckIsYUFBYSxFQUFFLGlCQUFpQixDQUFDLE1BQU07WUFDdkMsVUFBVSxFQUFFLENBQUMsQ0FBQztTQUNmLENBQUM7SUFDSixDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUMseUJBQXlCLENBQ3pELEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxFQUN4QixZQUFZLENBQ2IsQ0FBQztRQUVGLElBQUksaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sV0FBVyxHQUFHLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzVELE9BQU87Z0JBQ0wsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsT0FBTyxFQUFFLFNBQVMsaUJBQWlCLENBQUMsTUFBTSxtQ0FBbUM7Z0JBQzdFLGlCQUFpQixFQUFFLFdBQVc7Z0JBQzlCLGFBQWEsRUFBRSxpQkFBaUIsQ0FBQyxNQUFNO2dCQUN2QyxVQUFVLEVBQUUsaUJBQWlCLENBQUMsTUFBTTthQUNyQyxDQUFDO1FBQ0osQ0FBQztRQUVELE9BQU87WUFDTCxPQUFPLEVBQUUsSUFBSTtZQUNiLE9BQU8sRUFBRSxvQ0FBb0M7WUFDN0MsaUJBQWlCLEVBQUUsRUFBRTtZQUNyQixhQUFhLEVBQUUsaUJBQWlCLENBQUMsTUFBTTtZQUN2QyxVQUFVLEVBQUUsQ0FBQztTQUNkLENBQUM7SUFDSixDQUFDO0lBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztRQUNwQixPQUFPO1lBQ0wsT0FBTyxFQUFFLEtBQUs7WUFDZCxPQUFPLEVBQUUsd0JBQXdCLEtBQUssQ0FBQyxPQUFPLEVBQUU7WUFDaEQsaUJBQWlCLEVBQUUsRUFBRTtZQUNyQixhQUFhLEVBQUUsaUJBQWlCLENBQUMsTUFBTTtZQUN2QyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1NBQ2YsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSSxLQUFLLFVBQVUscUJBQXFCLENBQ3pDLE9BQXVCO0lBRXZCLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7SUFFdkIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO0lBQ2xFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLE9BQU8sQ0FBQyxXQUFXLFFBQVEsQ0FBQyxDQUFDO0lBRW5FLDJCQUEyQjtJQUMzQixNQUFNLEtBQUssR0FBRzs7Ozs7Ozs7OztHQVViLENBQUM7SUFFRixJQUFJLENBQUM7UUFDSCxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsWUFBWTtZQUMxQyxDQUFDLENBQUMsb0JBQW9CLE9BQU8sQ0FBQyxZQUFZLEdBQUc7WUFDN0MsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUVQLE1BQU0sT0FBTyxHQUFHLHNCQUFzQixLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxlQUFlLGdCQUFnQixDQUFDO1FBRXBHLE1BQU0sTUFBTSxHQUFHLElBQUEsd0JBQVEsRUFBQyxPQUFPLEVBQUU7WUFDL0IsUUFBUSxFQUFFLE9BQU87WUFDakIsS0FBSyxFQUFFLE1BQU07U0FDZCxDQUFDLENBQUM7UUFFSCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1FBRXBDLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLFNBQVMsQ0FBQyxNQUFNLGlCQUFpQixDQUFDLENBQUM7UUFFbEUsd0NBQXdDO1FBQ3hDLE1BQU0sUUFBUSxHQUF1QixFQUFFLENBQUM7UUFFeEMsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNqQyxNQUFNLFNBQVMsR0FBRyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDL0MsTUFBTSxZQUFZLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3JELE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxHQUFHLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztZQUUxRSxzQkFBc0I7WUFDdEIsSUFBSSxRQUFRLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQztnQkFDakMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxzQkFBc0IsUUFBUSxDQUFDLElBQUksZ0JBQWdCLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8saUJBQWlCLElBQUksQ0FDbkcsQ0FBQztnQkFDRixTQUFTO1lBQ1gsQ0FBQztZQUVELElBQUksR0FBRyxHQUFHLFlBQVksRUFBRSxDQUFDO2dCQUN2QixPQUFPLENBQUMsR0FBRyxDQUNULHNCQUFzQixRQUFRLENBQUMsSUFBSSxnQ0FBZ0MsQ0FDcEUsQ0FBQztnQkFDRixTQUFTO1lBQ1gsQ0FBQztZQUVELElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkMsT0FBTyxDQUFDLEdBQUcsQ0FDVCxzQkFBc0IsUUFBUSxDQUFDLElBQUksMkJBQTJCLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sT0FBTyxDQUFDLFdBQVcsSUFBSSxDQUNoSCxDQUFDO2dCQUNGLFNBQVM7WUFDWCxDQUFDO1lBRUQsUUFBUSxDQUFDLElBQUksQ0FBQztnQkFDWixVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUU7Z0JBQ3ZCLFlBQVksRUFBRSxRQUFRLENBQUMsSUFBSTtnQkFDM0IsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJO2dCQUNuQixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVE7Z0JBQzNCLGFBQWEsRUFBRSxRQUFRLENBQUMsYUFBYTtnQkFDckMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxTQUFTO2dCQUM3QixTQUFTO2dCQUNULFlBQVk7Z0JBQ1osUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO2dCQUMzQixRQUFRO2FBQ1QsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sQ0FBQyxHQUFHLENBQ1QsbUJBQW1CLFFBQVEsQ0FBQyxNQUFNLDBDQUEwQyxDQUM3RSxDQUFDO1FBRUYsK0JBQStCO1FBQy9CLElBQUksT0FBTyxDQUFDLFlBQVksSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixPQUFPLENBQUMsWUFBWSxZQUFZLENBQUMsQ0FBQztZQUN2RSxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNqRCxDQUFDO1FBRUQsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7UUFDcEIsT0FBTyxDQUFDLEtBQUssQ0FDWCw4Q0FBOEMsRUFDOUMsS0FBSyxDQUFDLE9BQU8sQ0FDZCxDQUFDO1FBQ0YsTUFBTSxLQUFLLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNJLEtBQUssVUFBVSx3QkFBd0IsQ0FDNUMsU0FBNkIsRUFDN0IsT0FBdUI7SUFFdkIsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUNsRCxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUMvQyxDQUFDO0lBRUQsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDbkIsT0FBTyxDQUFDLEdBQUcsQ0FBQywyREFBMkQsQ0FBQyxDQUFDO1FBQ3pFLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUN0QixPQUFPLENBQUMsR0FBRyxDQUNULE9BQU8sQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsWUFBWSxRQUFRLENBQUMsQ0FBQyxhQUFhLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FDM0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQzlELENBQUM7SUFFRCwyREFBMkQ7SUFDM0QsTUFBTSxlQUFlLEdBQUcsSUFBSSxHQUFHLEVBQThCLENBQUM7SUFDOUQsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUNqQyxNQUFNLEtBQUssR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEUsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyQixlQUFlLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELE9BQU8sQ0FBQyxHQUFHLENBQ1Qsc0JBQXNCLGVBQWUsQ0FBQyxJQUFJLCtCQUErQixTQUFTLENBQUMsTUFBTSxZQUFZLENBQ3RHLENBQUM7SUFFRixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDaEIsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBRTVCLEtBQUssTUFBTSxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUNwRCxJQUFJLENBQUM7WUFDSCxPQUFPLENBQUMsR0FBRyxDQUNULHNDQUFzQyxNQUFNLEtBQUssV0FBVyxDQUFDLE1BQU0sYUFBYSxDQUNqRixDQUFDO1lBRUYsOERBQThEO1lBQzlELE1BQU0sZ0JBQWdCLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FDeEMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLFFBQVEsSUFBSSxpQkFBaUIsQ0FDdEQsQ0FBQztZQUVGLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUN0QixPQUFPLENBQUMsSUFBSSxDQUNWLHNCQUFzQixNQUFNLDhDQUE4QyxDQUMzRSxDQUFDO2dCQUNGLE1BQU0sSUFBSSxXQUFXLENBQUMsTUFBTSxDQUFDO2dCQUM3QixNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixNQUFNLDhCQUE4QixDQUFDLENBQUM7Z0JBQ3BFLFNBQVM7WUFDWCxDQUFDO1lBRUQseUNBQXlDO1lBQ3pDLElBQUEsd0JBQVEsRUFBQywyQkFBMkIsTUFBTSxtQkFBbUIsRUFBRTtnQkFDN0QsUUFBUSxFQUFFLE9BQU87Z0JBQ2pCLEtBQUssRUFBRSxNQUFNO2FBQ2QsQ0FBQyxDQUFDO1lBRUgsT0FBTyxJQUFJLFdBQVcsQ0FBQyxNQUFNLENBQUM7WUFDOUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQ0FBcUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixPQUFPLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxNQUFNLEdBQUcsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEUsTUFBTSxJQUFJLFdBQVcsQ0FBQyxNQUFNLENBQUM7WUFDN0IsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsTUFBTSxLQUFLLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzlELENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQWtCO1FBQzVCLE9BQU87UUFDUCxNQUFNO1FBQ04sT0FBTyxFQUFFLENBQUM7UUFDVixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsU0FBUztLQUMvQyxDQUFDO0lBRUYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQ2xDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLE1BQU0sQ0FBQyxPQUFPLFlBQVksQ0FBQyxDQUFDO0lBQ3hELE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxNQUFNLENBQUMsTUFBTSxZQUFZLENBQUMsQ0FBQztJQUN0RCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0ksS0FBSyxVQUFVLCtCQUErQixDQUNuRCxLQUFhLEVBQ2IsaUJBQXFDLEVBQ3JDLFlBQXFCLEVBQ3JCLGFBQXFCLFdBQVcsRUFDaEMsY0FBc0IsYUFBYTtJQUVuQyxJQUFJLFVBQThCLENBQUM7SUFFbkMsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxJQUFJLFVBQVUsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ3ZELE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBRS9ELFVBQVUsR0FBRyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFNUUsSUFBSSxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdkIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO1lBQ2hFLE9BQU8sVUFBVSxDQUFDO1FBQ3BCLENBQUM7UUFFRCxJQUFJLE9BQU8sR0FBRyxVQUFVLEVBQUUsQ0FBQztZQUN6QixPQUFPLENBQUMsR0FBRyxDQUNULHdCQUF3QixVQUFVLENBQUMsVUFBVSwyQkFBMkIsV0FBVyxHQUFHLElBQUksTUFBTSxDQUNqRyxDQUFDO1lBQ0YsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxDQUFDLEtBQUssQ0FDWCxpQ0FBaUMsVUFBVSxjQUFjLFVBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FDL0UsQ0FBQztJQUNGLE9BQU8sVUFBVyxDQUFDO0FBQ3JCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENsZWFudXAgYW5kIHZlcmlmaWNhdGlvbiB1dGlsaXRpZXMgZm9yIGludGVncmF0aW9uIHRlc3RzXG4gKlxuICogUHJvdmlkZXMgZnVuY3Rpb25zIGZvciB2ZXJpZnlpbmcgcmVzb3VyY2UgZGVsZXRpb24gdmlhIEF6dXJlIFJlc291cmNlIEdyYXBoXG4gKiBhbmQgZmluZGluZy9jbGVhbmluZyBvcnBoYW5lZCByZXNvdXJjZXMgd2l0aCBjb21wcmVoZW5zaXZlIHNhZmV0eSBtZWNoYW5pc21zLlxuICovXG5cbmltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcblxuLyoqXG4gKiBNZXRhZGF0YSBmb3IgYW4gaW5kaXZpZHVhbCByZXNvdXJjZSBjcmVhdGVkIGR1cmluZyB0ZXN0aW5nXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VNZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBBenVyZSByZXNvdXJjZSBJRFxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBenVyZSByZXNvdXJjZSB0eXBlIChlLmcuLCAnTWljcm9zb2Z0LlJlc291cmNlcy9yZXNvdXJjZUdyb3VwcycpXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZVR5cGU6IHN0cmluZztcblxuICAvKipcbiAgICogUmVzb3VyY2UgbmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZSBsb2NhdGlvbiAoQXp1cmUgcmVnaW9uKVxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIHRhZ3NcbiAgICovXG4gIHJlYWRvbmx5IHRhZ3M6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbiAgLyoqXG4gICAqIFRlc3QgcnVuIElEIHRoYXQgY3JlYXRlZCB0aGlzIHJlc291cmNlXG4gICAqL1xuICByZWFkb25seSB0ZXN0UnVuSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGltZXN0YW1wIHdoZW4gcmVzb3VyY2Ugd2FzIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IGNyZWF0ZWRBdDogRGF0ZTtcblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHJlc291cmNlIHdhcyBzdWNjZXNzZnVsbHkgZGVzdHJveWVkXG4gICAqL1xuICByZWFkb25seSBkZXN0cm95ZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaW1lc3RhbXAgd2hlbiByZXNvdXJjZSB3YXMgZGVzdHJveWVkXG4gICAqL1xuICByZWFkb25seSBkZXN0cm95ZWRBdD86IERhdGU7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIHJlc291cmNlIGNsZWFudXAgdmVyaWZpY2F0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVyaWZpY2F0aW9uUmVzdWx0IHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdmVyaWZpY2F0aW9uIHN1Y2NlZWRlZCAoYWxsIHJlc291cmNlcyBkZWxldGVkKVxuICAgKi9cbiAgcmVhZG9ubHkgc3VjY2VzczogYm9vbGVhbjtcblxuICAvKipcbiAgICogSHVtYW4tcmVhZGFibGUgbWVzc2FnZSBkZXNjcmliaW5nIHRoZSByZXN1bHRcbiAgICovXG4gIHJlYWRvbmx5IG1lc3NhZ2U6IHN0cmluZztcblxuICAvKipcbiAgICogTGlzdCBvZiBvcnBoYW5lZCByZXNvdXJjZSBJRHMgKGlmIGFueSlcbiAgICovXG4gIHJlYWRvbmx5IG9ycGhhbmVkUmVzb3VyY2VzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTnVtYmVyIG9mIHJlc291cmNlcyBleHBlY3RlZCB0byBiZSBkZWxldGVkXG4gICAqL1xuICByZWFkb25seSBleHBlY3RlZENvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgcmVzb3VyY2VzIGFjdHVhbGx5IGZvdW5kXG4gICAqL1xuICByZWFkb25seSBmb3VuZENvdW50PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGNsZWFudXAgb3BlcmF0aW9uc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIENsZWFudXBPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gcGVyZm9ybSBkcnktcnVuIChubyBhY3R1YWwgZGVsZXRpb24pXG4gICAqL1xuICByZWFkb25seSBkcnlSdW46IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE1pbmltdW0gYWdlIGluIGhvdXJzIGJlZm9yZSByZXNvdXJjZSBjYW4gYmUgY2xlYW5lZCB1cFxuICAgKi9cbiAgcmVhZG9ubHkgbWluQWdlSG91cnM6IG51bWJlcjtcblxuICAvKipcbiAgICogQXp1cmUgc3Vic2NyaXB0aW9uIElEIHRvIHRhcmdldCAob3B0aW9uYWwpXG4gICAqL1xuICByZWFkb25seSBzdWJzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmljIHJlc291cmNlIGdyb3VwcyB0byB0YXJnZXQgKG9wdGlvbmFsKVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VHcm91cHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2YgcmVzb3VyY2VzIHRvIGNsZWFuIHVwIGluIG9uZSBvcGVyYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IG1heFJlc291cmNlcz86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBPcnBoYW5lZCByZXNvdXJjZSBpbmZvcm1hdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9ycGhhbmVkUmVzb3VyY2Uge1xuICAvKipcbiAgICogQXp1cmUgcmVzb3VyY2UgSURcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogQXp1cmUgcmVzb3VyY2UgdHlwZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VUeXBlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogUmVzb3VyY2UgbG9jYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGxvY2F0aW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIGdyb3VwIG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlR3JvdXA6IHN0cmluZztcblxuICAvKipcbiAgICogVGVzdCBydW4gSUQgZnJvbSB0YWdzXG4gICAqL1xuICByZWFkb25seSB0ZXN0UnVuSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogQ3JlYXRpb24gdGltZXN0YW1wIGZyb20gdGFnc1xuICAgKi9cbiAgcmVhZG9ubHkgY3JlYXRlZEF0OiBEYXRlO1xuXG4gIC8qKlxuICAgKiBDbGVhbnVwIGFmdGVyIHRpbWVzdGFtcCBmcm9tIHRhZ3NcbiAgICovXG4gIHJlYWRvbmx5IGNsZWFudXBBZnRlcjogRGF0ZTtcblxuICAvKipcbiAgICogVGVzdCBuYW1lIGZyb20gdGFnc1xuICAgKi9cbiAgcmVhZG9ubHkgdGVzdE5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogQWdlIGluIGhvdXJzIHNpbmNlIGNyZWF0aW9uXG4gICAqL1xuICByZWFkb25seSBhZ2VIb3VyczogbnVtYmVyO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBjbGVhbnVwIG9wZXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsZWFudXBSZXN1bHQge1xuICAvKipcbiAgICogTnVtYmVyIG9mIHJlc291cmNlcyBzdWNjZXNzZnVsbHkgZGVsZXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgZGVsZXRlZDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgcmVzb3VyY2VzIHRoYXQgZmFpbGVkIHRvIGRlbGV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgZmFpbGVkOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiByZXNvdXJjZXMgc2tpcHBlZCAoZS5nLiwgdG9vIHlvdW5nKVxuICAgKi9cbiAgcmVhZG9ubHkgc2tpcHBlZDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBEZXRhaWxlZCBlcnJvciBtZXNzYWdlcyBmb3IgZmFpbHVyZXNcbiAgICovXG4gIHJlYWRvbmx5IGVycm9ycz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIE1pbmltdW0gYWdlIHRocmVzaG9sZCAoaG91cnMpIGJlZm9yZSBjbGVhbnVwIGlzIGFsbG93ZWRcbiAqL1xuY29uc3QgTUlOSU1VTV9BR0VfSE9VUlMgPSAyO1xuXG4vKipcbiAqIE1heGltdW0gcmV0cnkgYXR0ZW1wdHMgZm9yIGV2ZW50dWFsIGNvbnNpc3RlbmN5XG4gKi9cbmNvbnN0IE1BWF9SRVRSSUVTID0gNTtcblxuLyoqXG4gKiBXYWl0IHRpbWUgYmV0d2VlbiByZXRyaWVzIChtaWxsaXNlY29uZHMpXG4gKi9cbmNvbnN0IFJFVFJZX1dBSVRfTVMgPSAzMDAwMDsgLy8gMzAgc2Vjb25kc1xuXG4vKipcbiAqIE1haW4gY2xlYW51cCBzZXJ2aWNlIGNsYXNzXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXNvdXJjZUNsZWFudXBTZXJ2aWNlIHtcbiAgLyoqXG4gICAqIENoZWNrcyBpZiBBenVyZSBDTEkgaXMgYXZhaWxhYmxlXG4gICAqL1xuICBwdWJsaWMgY2hlY2tBenVyZUNsaUF2YWlsYWJsZSgpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZXhlY1N5bmMoXCJheiAtLXZlcnNpb25cIiwgeyBzdGRpbzogXCJwaXBlXCIgfSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyBhbiBBenVyZSBDTEkgY29tbWFuZCB3aXRoIGVycm9yIGhhbmRsaW5nXG4gICAqL1xuICBwcml2YXRlIGV4ZWN1dGVBenVyZUNvbW1hbmQoY29tbWFuZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGV4ZWNTeW5jKGNvbW1hbmQsIHtcbiAgICAgICAgZW5jb2Rpbmc6IFwidXRmLThcIixcbiAgICAgICAgc3RkaW86IFwicGlwZVwiLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQXp1cmUgQ0xJIGNvbW1hbmQgZmFpbGVkOiAke2Vycm9yLm1lc3NhZ2V9XFxuYCArXG4gICAgICAgICAgYENvbW1hbmQ6ICR7Y29tbWFuZH1cXG5gICtcbiAgICAgICAgICBgU3RkZXJyOiAke2Vycm9yLnN0ZGVycj8udG9TdHJpbmcoKSB8fCBcIk4vQVwifWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBRdWVyaWVzIEF6dXJlIFJlc291cmNlIEdyYXBoIGZvciByZXNvdXJjZXMgYnkgdGFnc1xuICAgKlxuICAgKiBSZXR1cm5zIGVtcHR5IGFycmF5IG9uIGVycm9ycyBmb3IgZ3JhY2VmdWwgZGVncmFkYXRpb24uXG4gICAqL1xuICBwdWJsaWMgcXVlcnlBenVyZVJlc291cmNlc0J5VGFncyhcbiAgICB0YWdzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgIHN1YnNjcmlwdGlvbj86IHN0cmluZyxcbiAgKTogYW55W10ge1xuICAgIC8vIEJ1aWxkIHRhZyBmaWx0ZXIgY29uZGl0aW9uc1xuICAgIGNvbnN0IHRhZ0NvbmRpdGlvbnMgPSBPYmplY3QuZW50cmllcyh0YWdzKVxuICAgICAgLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgdGFnc1snJHtrZXl9J10gPT0gJyR7dmFsdWV9J2ApXG4gICAgICAuam9pbihcIiBhbmQgXCIpO1xuXG4gICAgY29uc3QgcXVlcnkgPSBgXG4gICAgICBSZXNvdXJjZXNcbiAgICAgIHwgd2hlcmUgJHt0YWdDb25kaXRpb25zfVxuICAgICAgfCBwcm9qZWN0IGlkLCB0eXBlLCBuYW1lLCBsb2NhdGlvbiwgcmVzb3VyY2VHcm91cCwgdGFnc1xuICAgIGA7XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb25BcmcgPSBzdWJzY3JpcHRpb25cbiAgICAgID8gYC0tc3Vic2NyaXB0aW9ucyBcIiR7c3Vic2NyaXB0aW9ufVwiYFxuICAgICAgOiBcIlwiO1xuXG4gICAgY29uc3QgY29tbWFuZCA9IGBheiBncmFwaCBxdWVyeSAtcSBcIiR7cXVlcnkucmVwbGFjZSgvXFxuL2csIFwiIFwiKX1cIiAke3N1YnNjcmlwdGlvbkFyZ30gLS1vdXRwdXQganNvbmA7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5leGVjdXRlQXp1cmVDb21tYW5kKGNvbW1hbmQpO1xuICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyZXN1bHQpO1xuICAgICAgcmV0dXJuIHBhcnNlZC5kYXRhIHx8IFtdO1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gcXVlcnkgQXp1cmUgUmVzb3VyY2UgR3JhcGg6XCIsIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFZlcmlmaWVzIHRoYXQgYWxsIHJlc291cmNlcyB3aXRoIGEgc3BlY2lmaWMgdGVzdCBydW4gSUQgYXJlIGRlbGV0ZWRcbiAqXG4gKiBQZXJmb3JtcyBBenVyZSBSZXNvdXJjZSBHcmFwaCBxdWVyeSB0byBjaGVjayBmb3IgcmVtYWluaW5nIHJlc291cmNlcy5cbiAqIEltcGxlbWVudHMgcmV0cnkgbG9naWMgdG8gaGFuZGxlIEF6dXJlJ3MgZXZlbnR1YWwgY29uc2lzdGVuY3kuXG4gKlxuICogQHBhcmFtIHJ1bklkIC0gVGVzdCBydW4gVVVJRCB0byB2ZXJpZnlcbiAqIEBwYXJhbSBleHBlY3RlZFJlc291cmNlcyAtIExpc3Qgb2YgcmVzb3VyY2VzIHRoYXQgc2hvdWxkIGJlIGRlbGV0ZWRcbiAqIEBwYXJhbSBzdWJzY3JpcHRpb24gLSBPcHRpb25hbCBzdWJzY3JpcHRpb24gSUQgdG8gcXVlcnlcbiAqIEByZXR1cm5zIFZlcmlmaWNhdGlvbiByZXN1bHQgd2l0aCBkZXRhaWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJpZnlSZXNvdXJjZXNEZWxldGVkKFxuICBydW5JZDogc3RyaW5nLFxuICBleHBlY3RlZFJlc291cmNlczogUmVzb3VyY2VNZXRhZGF0YVtdLFxuICBzdWJzY3JpcHRpb24/OiBzdHJpbmcsXG4pOiBWZXJpZmljYXRpb25SZXN1bHQge1xuICBjb25zdCBzZXJ2aWNlID0gbmV3IFJlc291cmNlQ2xlYW51cFNlcnZpY2UoKTtcblxuICAvLyBDaGVjayBpZiBBenVyZSBDTEkgaXMgYXZhaWxhYmxlIGJlZm9yZSBhdHRlbXB0aW5nIHZlcmlmaWNhdGlvblxuICBpZiAoIXNlcnZpY2UuY2hlY2tBenVyZUNsaUF2YWlsYWJsZSgpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgbWVzc2FnZTogXCJWZXJpZmljYXRpb24gZmFpbGVkOiBBenVyZSBDTEkgaXMgbm90IGF2YWlsYWJsZVwiLFxuICAgICAgb3JwaGFuZWRSZXNvdXJjZXM6IFtdLFxuICAgICAgZXhwZWN0ZWRDb3VudDogZXhwZWN0ZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgZm91bmRDb3VudDogLTEsXG4gICAgfTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3Qgb3JwaGFuZWRSZXNvdXJjZXMgPSBzZXJ2aWNlLnF1ZXJ5QXp1cmVSZXNvdXJjZXNCeVRhZ3MoXG4gICAgICB7IFwidGVzdDpydW4taWRcIjogcnVuSWQgfSxcbiAgICAgIHN1YnNjcmlwdGlvbixcbiAgICApO1xuXG4gICAgaWYgKG9ycGhhbmVkUmVzb3VyY2VzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHJlc291cmNlSWRzID0gb3JwaGFuZWRSZXNvdXJjZXMubWFwKChyOiBhbnkpID0+IHIuaWQpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgIG1lc3NhZ2U6IGBGb3VuZCAke29ycGhhbmVkUmVzb3VyY2VzLmxlbmd0aH0gb3JwaGFuZWQgcmVzb3VyY2VzIGFmdGVyIGRlc3Ryb3lgLFxuICAgICAgICBvcnBoYW5lZFJlc291cmNlczogcmVzb3VyY2VJZHMsXG4gICAgICAgIGV4cGVjdGVkQ291bnQ6IGV4cGVjdGVkUmVzb3VyY2VzLmxlbmd0aCxcbiAgICAgICAgZm91bmRDb3VudDogb3JwaGFuZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgIG1lc3NhZ2U6IFwiQWxsIHJlc291cmNlcyBzdWNjZXNzZnVsbHkgZGVsZXRlZFwiLFxuICAgICAgb3JwaGFuZWRSZXNvdXJjZXM6IFtdLFxuICAgICAgZXhwZWN0ZWRDb3VudDogZXhwZWN0ZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgZm91bmRDb3VudDogMCxcbiAgICB9O1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgbWVzc2FnZTogYFZlcmlmaWNhdGlvbiBmYWlsZWQ6ICR7ZXJyb3IubWVzc2FnZX1gLFxuICAgICAgb3JwaGFuZWRSZXNvdXJjZXM6IFtdLFxuICAgICAgZXhwZWN0ZWRDb3VudDogZXhwZWN0ZWRSZXNvdXJjZXMubGVuZ3RoLFxuICAgICAgZm91bmRDb3VudDogLTEsXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIEZpbmRzIG9ycGhhbmVkIHRlc3QgcmVzb3VyY2VzIHRoYXQgYXJlIHBhc3QgdGhlaXIgVFRMXG4gKlxuICogUXVlcmllcyBBenVyZSBmb3IgcmVzb3VyY2VzIHdpdGggdGVzdCB0YWdzIHRoYXQgYXJlIG9sZGVyIHRoYW5cbiAqIHRoZWlyIGNsZWFudXAtYWZ0ZXIgdGltZXN0YW1wLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gQ2xlYW51cCBvcHRpb25zXG4gKiBAcmV0dXJucyBMaXN0IG9mIG9ycGhhbmVkIHJlc291cmNlc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZE9ycGhhbmVkUmVzb3VyY2VzKFxuICBvcHRpb25zOiBDbGVhbnVwT3B0aW9ucyxcbik6IFByb21pc2U8T3JwaGFuZWRSZXNvdXJjZVtdPiB7XG4gIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG5cbiAgY29uc29sZS5sb2coYFtDbGVhbnVwXSBTZWFyY2hpbmcgZm9yIG9ycGhhbmVkIHRlc3QgcmVzb3VyY2VzLi4uYCk7XG4gIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0gTWluaW11bSBhZ2U6ICR7b3B0aW9ucy5taW5BZ2VIb3Vyc30gaG91cnNgKTtcblxuICAvLyBRdWVyeSBmb3IgdGVzdCByZXNvdXJjZXNcbiAgY29uc3QgcXVlcnkgPSBgXG4gICAgUmVzb3VyY2VzXG4gICAgfCB3aGVyZSB0YWdzWyd0ZXN0Om1hbmFnZWQtYnknXSA9PSAndGVycmFmb3JtLWNkay1jb25zdHJ1Y3RzLXRlc3RzJ1xuICAgIHwgd2hlcmUgdGFnc1sndGVzdDphdXRvLWNsZWFudXAnXSA9PSAndHJ1ZSdcbiAgICB8IHByb2plY3QgaWQsIHR5cGUsIG5hbWUsIGxvY2F0aW9uLCByZXNvdXJjZUdyb3VwLFxuICAgICAgICAgICAgICB0ZXN0UnVuSWQgPSB0YWdzWyd0ZXN0OnJ1bi1pZCddLFxuICAgICAgICAgICAgICBjcmVhdGVkQXQgPSB0YWdzWyd0ZXN0OmNyZWF0ZWQtYXQnXSxcbiAgICAgICAgICAgICAgY2xlYW51cEFmdGVyID0gdGFnc1sndGVzdDpjbGVhbnVwLWFmdGVyJ10sXG4gICAgICAgICAgICAgIHRlc3ROYW1lID0gdGFnc1sndGVzdDpuYW1lJ11cbiAgICB8IG9yZGVyIGJ5IHRvc3RyaW5nKGNyZWF0ZWRBdCkgYXNjXG4gIGA7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBzdWJzY3JpcHRpb25BcmcgPSBvcHRpb25zLnN1YnNjcmlwdGlvblxuICAgICAgPyBgLS1zdWJzY3JpcHRpb25zIFwiJHtvcHRpb25zLnN1YnNjcmlwdGlvbn1cImBcbiAgICAgIDogXCJcIjtcblxuICAgIGNvbnN0IGNvbW1hbmQgPSBgYXogZ3JhcGggcXVlcnkgLXEgXCIke3F1ZXJ5LnJlcGxhY2UoL1xcbi9nLCBcIiBcIil9XCIgJHtzdWJzY3JpcHRpb25Bcmd9IC0tb3V0cHV0IGpzb25gO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gZXhlY1N5bmMoY29tbWFuZCwge1xuICAgICAgZW5jb2Rpbmc6IFwidXRmLThcIixcbiAgICAgIHN0ZGlvOiBcInBpcGVcIixcbiAgICB9KTtcblxuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UocmVzdWx0KTtcbiAgICBjb25zdCByZXNvdXJjZXMgPSBwYXJzZWQuZGF0YSB8fCBbXTtcblxuICAgIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0gRm91bmQgJHtyZXNvdXJjZXMubGVuZ3RofSB0ZXN0IHJlc291cmNlc2ApO1xuXG4gICAgLy8gRmlsdGVyIGJ5IGFnZSBhbmQgY2xlYW51cCBlbGlnaWJpbGl0eVxuICAgIGNvbnN0IG9ycGhhbmVkOiBPcnBoYW5lZFJlc291cmNlW10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgcmVzb3VyY2VzKSB7XG4gICAgICBjb25zdCBjcmVhdGVkQXQgPSBuZXcgRGF0ZShyZXNvdXJjZS5jcmVhdGVkQXQpO1xuICAgICAgY29uc3QgY2xlYW51cEFmdGVyID0gbmV3IERhdGUocmVzb3VyY2UuY2xlYW51cEFmdGVyKTtcbiAgICAgIGNvbnN0IGFnZUhvdXJzID0gKG5vdy5nZXRUaW1lKCkgLSBjcmVhdGVkQXQuZ2V0VGltZSgpKSAvICg2MCAqIDYwICogMTAwMCk7XG5cbiAgICAgIC8vIEFwcGx5IHNhZmV0eSBjaGVja3NcbiAgICAgIGlmIChhZ2VIb3VycyA8IE1JTklNVU1fQUdFX0hPVVJTKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBbQ2xlYW51cF0gU2tpcHBpbmcgJHtyZXNvdXJjZS5uYW1lfTogdG9vIHlvdW5nICgke2FnZUhvdXJzLnRvRml4ZWQoMSl9aCA8ICR7TUlOSU1VTV9BR0VfSE9VUlN9aClgLFxuICAgICAgICApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5vdyA8IGNsZWFudXBBZnRlcikge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgW0NsZWFudXBdIFNraXBwaW5nICR7cmVzb3VyY2UubmFtZX06IG5vdCB5ZXQgZWxpZ2libGUgZm9yIGNsZWFudXBgLFxuICAgICAgICApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFnZUhvdXJzIDwgb3B0aW9ucy5taW5BZ2VIb3Vycykge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgW0NsZWFudXBdIFNraXBwaW5nICR7cmVzb3VyY2UubmFtZX06IHlvdW5nZXIgdGhhbiBtaW4gYWdlICgke2FnZUhvdXJzLnRvRml4ZWQoMSl9aCA8ICR7b3B0aW9ucy5taW5BZ2VIb3Vyc31oKWAsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBvcnBoYW5lZC5wdXNoKHtcbiAgICAgICAgcmVzb3VyY2VJZDogcmVzb3VyY2UuaWQsXG4gICAgICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2UudHlwZSxcbiAgICAgICAgbmFtZTogcmVzb3VyY2UubmFtZSxcbiAgICAgICAgbG9jYXRpb246IHJlc291cmNlLmxvY2F0aW9uLFxuICAgICAgICByZXNvdXJjZUdyb3VwOiByZXNvdXJjZS5yZXNvdXJjZUdyb3VwLFxuICAgICAgICB0ZXN0UnVuSWQ6IHJlc291cmNlLnRlc3RSdW5JZCxcbiAgICAgICAgY3JlYXRlZEF0LFxuICAgICAgICBjbGVhbnVwQWZ0ZXIsXG4gICAgICAgIHRlc3ROYW1lOiByZXNvdXJjZS50ZXN0TmFtZSxcbiAgICAgICAgYWdlSG91cnMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBbQ2xlYW51cF0gRm91bmQgJHtvcnBoYW5lZC5sZW5ndGh9IG9ycGhhbmVkIHJlc291cmNlcyBlbGlnaWJsZSBmb3IgY2xlYW51cGAsXG4gICAgKTtcblxuICAgIC8vIExpbWl0IHJlc291cmNlcyBpZiBzcGVjaWZpZWRcbiAgICBpZiAob3B0aW9ucy5tYXhSZXNvdXJjZXMgJiYgb3JwaGFuZWQubGVuZ3RoID4gb3B0aW9ucy5tYXhSZXNvdXJjZXMpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0gTGltaXRpbmcgdG8gJHtvcHRpb25zLm1heFJlc291cmNlc30gcmVzb3VyY2VzYCk7XG4gICAgICByZXR1cm4gb3JwaGFuZWQuc2xpY2UoMCwgb3B0aW9ucy5tYXhSZXNvdXJjZXMpO1xuICAgIH1cblxuICAgIHJldHVybiBvcnBoYW5lZDtcbiAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBcIltDbGVhbnVwXSBGYWlsZWQgdG8gZmluZCBvcnBoYW5lZCByZXNvdXJjZXM6XCIsXG4gICAgICBlcnJvci5tZXNzYWdlLFxuICAgICk7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBDbGVhbnMgdXAgb3JwaGFuZWQgdGVzdCByZXNvdXJjZXNcbiAqXG4gKiBEZWxldGVzIHJlc291cmNlIGdyb3VwcyBjb250YWluaW5nIG9ycGhhbmVkIHRlc3QgcmVzb3VyY2VzLlxuICogSW1wbGVtZW50cyBzYWZldHkgY2hlY2tzIGFuZCBkcnktcnVuIG1vZGUuXG4gKlxuICogQHBhcmFtIHJlc291cmNlcyAtIExpc3Qgb2Ygb3JwaGFuZWQgcmVzb3VyY2VzIHRvIGNsZWFuIHVwXG4gKiBAcGFyYW0gb3B0aW9ucyAtIENsZWFudXAgb3B0aW9uc1xuICogQHJldHVybnMgQ2xlYW51cCByZXN1bHQgd2l0aCBzdGF0aXN0aWNzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbGVhbnVwT3JwaGFuZWRSZXNvdXJjZXMoXG4gIHJlc291cmNlczogT3JwaGFuZWRSZXNvdXJjZVtdLFxuICBvcHRpb25zOiBDbGVhbnVwT3B0aW9ucyxcbik6IFByb21pc2U8Q2xlYW51cFJlc3VsdD4ge1xuICBpZiAocmVzb3VyY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIGNvbnNvbGUubG9nKFwiW0NsZWFudXBdIE5vIHJlc291cmNlcyB0byBjbGVhbiB1cFwiKTtcbiAgICByZXR1cm4geyBkZWxldGVkOiAwLCBmYWlsZWQ6IDAsIHNraXBwZWQ6IDAgfTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLmRyeVJ1bikge1xuICAgIGNvbnNvbGUubG9nKFwiW0NsZWFudXBdIERSWSBSVU4gLSBXb3VsZCBkZWxldGUgdGhlIGZvbGxvd2luZyByZXNvdXJjZXM6XCIpO1xuICAgIHJlc291cmNlcy5mb3JFYWNoKChyKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYCAgLSAke3IubmFtZX0gKCR7ci5yZXNvdXJjZVR5cGV9KSBpbiAke3IucmVzb3VyY2VHcm91cH0gLSBBZ2U6ICR7ci5hZ2VIb3Vycy50b0ZpeGVkKDEpfWhgLFxuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4geyBkZWxldGVkOiAwLCBmYWlsZWQ6IDAsIHNraXBwZWQ6IHJlc291cmNlcy5sZW5ndGggfTtcbiAgfVxuXG4gIC8vIEdyb3VwIHJlc291cmNlcyBieSByZXNvdXJjZSBncm91cCBmb3IgZWZmaWNpZW50IGRlbGV0aW9uXG4gIGNvbnN0IGJ5UmVzb3VyY2VHcm91cCA9IG5ldyBNYXA8c3RyaW5nLCBPcnBoYW5lZFJlc291cmNlW10+KCk7XG4gIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgcmVzb3VyY2VzKSB7XG4gICAgY29uc3QgZ3JvdXAgPSBieVJlc291cmNlR3JvdXAuZ2V0KHJlc291cmNlLnJlc291cmNlR3JvdXApIHx8IFtdO1xuICAgIGdyb3VwLnB1c2gocmVzb3VyY2UpO1xuICAgIGJ5UmVzb3VyY2VHcm91cC5zZXQocmVzb3VyY2UucmVzb3VyY2VHcm91cCwgZ3JvdXApO1xuICB9XG5cbiAgY29uc29sZS5sb2coXG4gICAgYFtDbGVhbnVwXSBEZWxldGluZyAke2J5UmVzb3VyY2VHcm91cC5zaXplfSByZXNvdXJjZSBncm91cHMgY29udGFpbmluZyAke3Jlc291cmNlcy5sZW5ndGh9IHJlc291cmNlc2AsXG4gICk7XG5cbiAgbGV0IGRlbGV0ZWQgPSAwO1xuICBsZXQgZmFpbGVkID0gMDtcbiAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgW3JnTmFtZSwgcmdSZXNvdXJjZXNdIG9mIGJ5UmVzb3VyY2VHcm91cCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYFtDbGVhbnVwXSBEZWxldGluZyByZXNvdXJjZSBncm91cDogJHtyZ05hbWV9ICgke3JnUmVzb3VyY2VzLmxlbmd0aH0gcmVzb3VyY2VzKWAsXG4gICAgICApO1xuXG4gICAgICAvLyBWYWxpZGF0ZSB0aGF0IGFsbCByZXNvdXJjZXMgaW4gdGhlIGdyb3VwIGFyZSB0ZXN0IHJlc291cmNlc1xuICAgICAgY29uc3QgYWxsVGVzdFJlc291cmNlcyA9IHJnUmVzb3VyY2VzLmV2ZXJ5KFxuICAgICAgICAocikgPT4gci50ZXN0UnVuSWQgJiYgci5hZ2VIb3VycyA+PSBNSU5JTVVNX0FHRV9IT1VSUyxcbiAgICAgICk7XG5cbiAgICAgIGlmICghYWxsVGVzdFJlc291cmNlcykge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYFtDbGVhbnVwXSBTa2lwcGluZyAke3JnTmFtZX06IG5vdCBhbGwgcmVzb3VyY2VzIGFyZSB2YWxpZCB0ZXN0IHJlc291cmNlc2AsXG4gICAgICAgICk7XG4gICAgICAgIGZhaWxlZCArPSByZ1Jlc291cmNlcy5sZW5ndGg7XG4gICAgICAgIGVycm9ycy5wdXNoKGBSZXNvdXJjZSBncm91cCAke3JnTmFtZX0gY29udGFpbnMgbm9uLXRlc3QgcmVzb3VyY2VzYCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBEZWxldGUgcmVzb3VyY2UgZ3JvdXAgKGFzeW5jLCBuby13YWl0KVxuICAgICAgZXhlY1N5bmMoYGF6IGdyb3VwIGRlbGV0ZSAtLW5hbWUgXCIke3JnTmFtZX1cIiAtLXllcyAtLW5vLXdhaXRgLCB7XG4gICAgICAgIGVuY29kaW5nOiBcInV0Zi04XCIsXG4gICAgICAgIHN0ZGlvOiBcInBpcGVcIixcbiAgICAgIH0pO1xuXG4gICAgICBkZWxldGVkICs9IHJnUmVzb3VyY2VzLmxlbmd0aDtcbiAgICAgIGNvbnNvbGUubG9nKGBbQ2xlYW51cF0g4pyTIEluaXRpYXRlZCBkZWxldGlvbiBvZiAke3JnTmFtZX1gKTtcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBbQ2xlYW51cF0g4pyXIEZhaWxlZCB0byBkZWxldGUgJHtyZ05hbWV9OmAsIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgZmFpbGVkICs9IHJnUmVzb3VyY2VzLmxlbmd0aDtcbiAgICAgIGVycm9ycy5wdXNoKGBGYWlsZWQgdG8gZGVsZXRlICR7cmdOYW1lfTogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHJlc3VsdDogQ2xlYW51cFJlc3VsdCA9IHtcbiAgICBkZWxldGVkLFxuICAgIGZhaWxlZCxcbiAgICBza2lwcGVkOiAwLFxuICAgIGVycm9yczogZXJyb3JzLmxlbmd0aCA+IDAgPyBlcnJvcnMgOiB1bmRlZmluZWQsXG4gIH07XG5cbiAgY29uc29sZS5sb2coXCJbQ2xlYW51cF0gU3VtbWFyeTpcIik7XG4gIGNvbnNvbGUubG9nKGAgIC0gRGVsZXRlZDogJHtyZXN1bHQuZGVsZXRlZH0gcmVzb3VyY2VzYCk7XG4gIGNvbnNvbGUubG9nKGAgIC0gRmFpbGVkOiAke3Jlc3VsdC5mYWlsZWR9IHJlc291cmNlc2ApO1xuICBpZiAocmVzdWx0LmVycm9ycykge1xuICAgIGNvbnNvbGUubG9nKGAgIC0gRXJyb3JzOiAke3Jlc3VsdC5lcnJvcnMubGVuZ3RofWApO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBWZXJpZmllcyByZXNvdXJjZSBjbGVhbnVwIHdpdGggcmV0cnkgbG9naWMgZm9yIGV2ZW50dWFsIGNvbnNpc3RlbmN5XG4gKlxuICogV3JhcHBlciBhcm91bmQgdmVyaWZ5UmVzb3VyY2VzRGVsZXRlZCB0aGF0IGltcGxlbWVudHMgcmV0cnkgbG9naWNcbiAqIHRvIGhhbmRsZSBBenVyZSdzIGV2ZW50dWFsIGNvbnNpc3RlbmN5IGRlbGF5cy5cbiAqXG4gKiBAcGFyYW0gcnVuSWQgLSBUZXN0IHJ1biBVVUlEIHRvIHZlcmlmeVxuICogQHBhcmFtIGV4cGVjdGVkUmVzb3VyY2VzIC0gTGlzdCBvZiByZXNvdXJjZXMgdGhhdCBzaG91bGQgYmUgZGVsZXRlZFxuICogQHBhcmFtIHN1YnNjcmlwdGlvbiAtIE9wdGlvbmFsIHN1YnNjcmlwdGlvbiBJRCB0byBxdWVyeVxuICogQHBhcmFtIG1heFJldHJpZXMgLSBNYXhpbXVtIG51bWJlciBvZiByZXRyeSBhdHRlbXB0c1xuICogQHBhcmFtIHJldHJ5V2FpdE1zIC0gV2FpdCB0aW1lIGJldHdlZW4gcmV0cmllcyBpbiBtaWxsaXNlY29uZHNcbiAqIEByZXR1cm5zIEZpbmFsIHZlcmlmaWNhdGlvbiByZXN1bHRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZlcmlmeVJlc291cmNlc0RlbGV0ZWRXaXRoUmV0cnkoXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGV4cGVjdGVkUmVzb3VyY2VzOiBSZXNvdXJjZU1ldGFkYXRhW10sXG4gIHN1YnNjcmlwdGlvbj86IHN0cmluZyxcbiAgbWF4UmV0cmllczogbnVtYmVyID0gTUFYX1JFVFJJRVMsXG4gIHJldHJ5V2FpdE1zOiBudW1iZXIgPSBSRVRSWV9XQUlUX01TLFxuKTogUHJvbWlzZTxWZXJpZmljYXRpb25SZXN1bHQ+IHtcbiAgbGV0IGxhc3RSZXN1bHQ6IFZlcmlmaWNhdGlvblJlc3VsdDtcblxuICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSBtYXhSZXRyaWVzOyBhdHRlbXB0KyspIHtcbiAgICBjb25zb2xlLmxvZyhgW1ZlcmlmaWNhdGlvbl0gQXR0ZW1wdCAke2F0dGVtcHR9LyR7bWF4UmV0cmllc31gKTtcblxuICAgIGxhc3RSZXN1bHQgPSB2ZXJpZnlSZXNvdXJjZXNEZWxldGVkKHJ1bklkLCBleHBlY3RlZFJlc291cmNlcywgc3Vic2NyaXB0aW9uKTtcblxuICAgIGlmIChsYXN0UmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgIGNvbnNvbGUubG9nKFwiW1ZlcmlmaWNhdGlvbl0g4pyTIEFsbCByZXNvdXJjZXMgY29uZmlybWVkIGRlbGV0ZWRcIik7XG4gICAgICByZXR1cm4gbGFzdFJlc3VsdDtcbiAgICB9XG5cbiAgICBpZiAoYXR0ZW1wdCA8IG1heFJldHJpZXMpIHtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBgW1ZlcmlmaWNhdGlvbl0gRm91bmQgJHtsYXN0UmVzdWx0LmZvdW5kQ291bnR9IHJlc291cmNlcywgcmV0cnlpbmcgaW4gJHtyZXRyeVdhaXRNcyAvIDEwMDB9cy4uLmAsXG4gICAgICApO1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgcmV0cnlXYWl0TXMpKTtcbiAgICB9XG4gIH1cblxuICBjb25zb2xlLmVycm9yKFxuICAgIGBbVmVyaWZpY2F0aW9uXSDinJcgRmFpbGVkIGFmdGVyICR7bWF4UmV0cmllc30gYXR0ZW1wdHM6ICR7bGFzdFJlc3VsdCEubWVzc2FnZX1gLFxuICApO1xuICByZXR1cm4gbGFzdFJlc3VsdCE7XG59XG4iXX0=
|