@microsoft/terraform-cdk-constructs 1.2.0 → 1.3.1
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 +54630 -26185
- package/API.md +72091 -23784
- package/lib/azure-actiongroup/index.d.ts +0 -10
- package/lib/azure-actiongroup/index.js +1 -11
- package/lib/azure-actiongroup/lib/action-group.d.ts +0 -10
- package/lib/azure-actiongroup/lib/action-group.js +6 -32
- package/lib/azure-actiongroup/lib/index.d.ts +1 -4
- package/lib/azure-actiongroup/lib/index.js +2 -5
- package/lib/azure-activitylogalert/index.d.ts +0 -10
- package/lib/azure-activitylogalert/index.js +1 -11
- package/lib/azure-activitylogalert/lib/activity-log-alert.d.ts +0 -10
- package/lib/azure-activitylogalert/lib/activity-log-alert.js +6 -32
- package/lib/azure-activitylogalert/lib/index.d.ts +1 -4
- package/lib/azure-activitylogalert/lib/index.js +2 -5
- package/lib/azure-aks/index.d.ts +0 -8
- package/lib/azure-aks/index.js +1 -11
- package/lib/azure-aks/lib/aks-cluster.d.ts +4 -13
- package/lib/azure-aks/lib/aks-cluster.js +13 -36
- package/lib/azure-aks/lib/index.d.ts +1 -10
- package/lib/azure-aks/lib/index.js +2 -21
- package/lib/azure-diagnosticsettings/index.d.ts +0 -6
- package/lib/azure-diagnosticsettings/index.js +1 -7
- package/lib/azure-diagnosticsettings/lib/diagnostic-settings.d.ts +0 -10
- package/lib/azure-diagnosticsettings/lib/diagnostic-settings.js +6 -32
- package/lib/azure-diagnosticsettings/lib/index.d.ts +1 -7
- package/lib/azure-diagnosticsettings/lib/index.js +2 -8
- package/lib/azure-dnsforwardingruleset/index.d.ts +1 -0
- package/lib/azure-dnsforwardingruleset/index.js +18 -0
- package/lib/azure-dnsforwardingruleset/lib/dns-forwarding-ruleset-schemas.d.ts +24 -0
- package/lib/azure-dnsforwardingruleset/lib/dns-forwarding-ruleset-schemas.js +206 -0
- package/lib/azure-dnsforwardingruleset/lib/dns-forwarding-ruleset.d.ts +174 -0
- package/lib/azure-dnsforwardingruleset/lib/dns-forwarding-ruleset.js +214 -0
- package/lib/azure-dnsforwardingruleset/lib/forwarding-rule-schemas.d.ts +24 -0
- package/lib/azure-dnsforwardingruleset/lib/forwarding-rule-schemas.js +242 -0
- package/lib/azure-dnsforwardingruleset/lib/forwarding-rule.d.ts +193 -0
- package/lib/azure-dnsforwardingruleset/lib/forwarding-rule.js +193 -0
- package/lib/azure-dnsforwardingruleset/lib/index.d.ts +6 -0
- package/lib/azure-dnsforwardingruleset/lib/index.js +23 -0
- package/lib/azure-dnsforwardingruleset/lib/virtual-network-link-schemas.d.ts +24 -0
- package/lib/azure-dnsforwardingruleset/lib/virtual-network-link-schemas.js +199 -0
- package/lib/azure-dnsforwardingruleset/lib/virtual-network-link.d.ts +160 -0
- package/lib/azure-dnsforwardingruleset/lib/virtual-network-link.js +178 -0
- package/lib/azure-dnsforwardingruleset/test/dns-forwarding-ruleset.integ.d.ts +9 -0
- package/lib/azure-dnsforwardingruleset/test/dns-forwarding-ruleset.integ.js +133 -0
- package/lib/azure-dnsforwardingruleset/test/dns-forwarding-ruleset.spec.d.ts +9 -0
- package/lib/azure-dnsforwardingruleset/test/dns-forwarding-ruleset.spec.js +350 -0
- package/lib/azure-dnsforwardingruleset/test/forwarding-rule.spec.d.ts +9 -0
- package/lib/azure-dnsforwardingruleset/test/forwarding-rule.spec.js +397 -0
- package/lib/azure-dnsforwardingruleset/test/virtual-network-link.spec.d.ts +9 -0
- package/lib/azure-dnsforwardingruleset/test/virtual-network-link.spec.js +285 -0
- package/lib/azure-dnsresolver/index.d.ts +1 -0
- package/lib/azure-dnsresolver/index.js +18 -0
- package/lib/azure-dnsresolver/lib/dns-resolver-schemas.d.ts +24 -0
- package/lib/azure-dnsresolver/lib/dns-resolver-schemas.js +218 -0
- package/lib/azure-dnsresolver/lib/dns-resolver.d.ts +170 -0
- package/lib/azure-dnsresolver/lib/dns-resolver.js +236 -0
- package/lib/azure-dnsresolver/lib/inbound-endpoint-schemas.d.ts +24 -0
- package/lib/azure-dnsresolver/lib/inbound-endpoint-schemas.js +261 -0
- package/lib/azure-dnsresolver/lib/inbound-endpoint.d.ts +189 -0
- package/lib/azure-dnsresolver/lib/inbound-endpoint.js +243 -0
- package/lib/azure-dnsresolver/lib/index.d.ts +6 -0
- package/lib/azure-dnsresolver/lib/index.js +23 -0
- package/lib/azure-dnsresolver/lib/outbound-endpoint-schemas.d.ts +24 -0
- package/lib/azure-dnsresolver/lib/outbound-endpoint-schemas.js +231 -0
- package/lib/azure-dnsresolver/lib/outbound-endpoint.d.ts +175 -0
- package/lib/azure-dnsresolver/lib/outbound-endpoint.js +234 -0
- package/lib/azure-dnsresolver/test/dns-resolver.integ.d.ts +14 -0
- package/lib/azure-dnsresolver/test/dns-resolver.integ.js +117 -0
- package/lib/azure-dnsresolver/test/dns-resolver.spec.d.ts +9 -0
- package/lib/azure-dnsresolver/test/dns-resolver.spec.js +353 -0
- package/lib/azure-dnsresolver/test/inbound-endpoint.integ.d.ts +9 -0
- package/lib/azure-dnsresolver/test/inbound-endpoint.integ.js +151 -0
- package/lib/azure-dnsresolver/test/inbound-endpoint.spec.d.ts +9 -0
- package/lib/azure-dnsresolver/test/inbound-endpoint.spec.js +441 -0
- package/lib/azure-dnsresolver/test/outbound-endpoint.integ.d.ts +9 -0
- package/lib/azure-dnsresolver/test/outbound-endpoint.integ.js +149 -0
- package/lib/azure-dnsresolver/test/outbound-endpoint.spec.d.ts +9 -0
- package/lib/azure-dnsresolver/test/outbound-endpoint.spec.js +301 -0
- package/lib/azure-dnszone/index.d.ts +1 -0
- package/lib/azure-dnszone/index.js +18 -0
- package/lib/azure-dnszone/lib/dns-zone-schemas.d.ts +24 -0
- package/lib/azure-dnszone/lib/dns-zone-schemas.js +191 -0
- package/lib/azure-dnszone/lib/dns-zone.d.ts +182 -0
- package/lib/azure-dnszone/lib/dns-zone.js +228 -0
- package/lib/azure-dnszone/lib/index.d.ts +2 -0
- package/lib/azure-dnszone/lib/index.js +19 -0
- package/lib/azure-dnszone/test/dns-zone.integ.d.ts +9 -0
- package/lib/azure-dnszone/test/dns-zone.integ.js +85 -0
- package/lib/azure-dnszone/test/dns-zone.spec.d.ts +9 -0
- package/lib/azure-dnszone/test/dns-zone.spec.js +285 -0
- package/lib/azure-metricalert/index.d.ts +0 -10
- package/lib/azure-metricalert/index.js +1 -11
- package/lib/azure-metricalert/lib/index.d.ts +1 -4
- package/lib/azure-metricalert/lib/index.js +2 -5
- package/lib/azure-metricalert/lib/metric-alert.d.ts +0 -10
- package/lib/azure-metricalert/lib/metric-alert.js +6 -32
- package/lib/azure-networkinterface/index.d.ts +0 -3
- package/lib/azure-networkinterface/index.js +1 -4
- package/lib/azure-networkinterface/lib/index.d.ts +1 -5
- package/lib/azure-networkinterface/lib/index.js +2 -5
- package/lib/azure-networkinterface/lib/network-interface.d.ts +4 -9
- package/lib/azure-networkinterface/lib/network-interface.js +14 -29
- package/lib/azure-networkinterface/test/network-interface.integ.js +20 -6
- package/lib/azure-networksecuritygroup/index.d.ts +0 -5
- package/lib/azure-networksecuritygroup/index.js +1 -6
- package/lib/azure-networksecuritygroup/lib/index.d.ts +2 -5
- package/lib/azure-networksecuritygroup/lib/index.js +17 -14
- package/lib/azure-networksecuritygroup/lib/network-security-group.d.ts +4 -13
- package/lib/azure-networksecuritygroup/lib/network-security-group.js +14 -36
- package/lib/azure-policyassignment/index.d.ts +1 -0
- package/lib/azure-policyassignment/index.js +18 -0
- package/lib/azure-policyassignment/lib/index.d.ts +2 -0
- package/lib/azure-policyassignment/lib/index.js +19 -0
- package/lib/azure-policyassignment/lib/policy-assignment-schemas.d.ts +25 -0
- package/lib/azure-policyassignment/lib/policy-assignment-schemas.js +260 -0
- package/lib/azure-policyassignment/lib/policy-assignment.d.ts +349 -0
- package/lib/azure-policyassignment/lib/policy-assignment.js +237 -0
- package/lib/azure-policyassignment/test/policy-assignment.integ.d.ts +13 -0
- package/lib/azure-policyassignment/test/policy-assignment.integ.js +153 -0
- package/lib/azure-policyassignment/test/policy-assignment.spec.d.ts +9 -0
- package/lib/azure-policyassignment/test/policy-assignment.spec.js +651 -0
- package/lib/azure-policydefinition/index.d.ts +1 -0
- package/lib/azure-policydefinition/index.js +18 -0
- package/lib/azure-policydefinition/lib/index.d.ts +2 -0
- package/lib/azure-policydefinition/lib/index.js +19 -0
- package/lib/azure-policydefinition/lib/policy-definition-schemas.d.ts +25 -0
- package/lib/azure-policydefinition/lib/policy-definition-schemas.js +210 -0
- package/lib/azure-policydefinition/lib/policy-definition.d.ts +281 -0
- package/lib/azure-policydefinition/lib/policy-definition.js +236 -0
- package/lib/azure-policydefinition/test/policy-definition.integ.d.ts +9 -0
- package/lib/azure-policydefinition/test/policy-definition.integ.js +137 -0
- package/lib/azure-policydefinition/test/policy-definition.spec.d.ts +9 -0
- package/lib/azure-policydefinition/test/policy-definition.spec.js +806 -0
- package/lib/azure-privatednszone/index.d.ts +1 -0
- package/lib/azure-privatednszone/index.js +18 -0
- package/lib/azure-privatednszone/lib/index.d.ts +2 -0
- package/lib/azure-privatednszone/lib/index.js +19 -0
- package/lib/azure-privatednszone/lib/private-dns-zone-schemas.d.ts +24 -0
- package/lib/azure-privatednszone/lib/private-dns-zone-schemas.js +254 -0
- package/lib/azure-privatednszone/lib/private-dns-zone.d.ts +178 -0
- package/lib/azure-privatednszone/lib/private-dns-zone.js +272 -0
- package/lib/azure-privatednszone/test/private-dns-zone.integ.d.ts +9 -0
- package/lib/azure-privatednszone/test/private-dns-zone.integ.js +84 -0
- package/lib/azure-privatednszone/test/private-dns-zone.spec.d.ts +9 -0
- package/lib/azure-privatednszone/test/private-dns-zone.spec.js +341 -0
- package/lib/azure-privatednszonelink/index.d.ts +1 -0
- package/lib/azure-privatednszonelink/index.js +18 -0
- package/lib/azure-privatednszonelink/lib/index.d.ts +2 -0
- package/lib/azure-privatednszonelink/lib/index.js +19 -0
- package/lib/azure-privatednszonelink/lib/private-dns-zone-link-schemas.d.ts +24 -0
- package/lib/azure-privatednszonelink/lib/private-dns-zone-link-schemas.js +262 -0
- package/lib/azure-privatednszonelink/lib/private-dns-zone-link.d.ts +202 -0
- package/lib/azure-privatednszonelink/lib/private-dns-zone-link.js +250 -0
- package/lib/azure-privatednszonelink/test/private-dns-zone-link.integ.d.ts +9 -0
- package/lib/azure-privatednszonelink/test/private-dns-zone-link.integ.js +110 -0
- package/lib/azure-privatednszonelink/test/private-dns-zone-link.spec.d.ts +9 -0
- package/lib/azure-privatednszonelink/test/private-dns-zone-link.spec.js +465 -0
- package/lib/azure-publicipaddress/index.d.ts +0 -5
- package/lib/azure-publicipaddress/index.js +1 -6
- package/lib/azure-publicipaddress/lib/index.d.ts +2 -9
- package/lib/azure-publicipaddress/lib/index.js +17 -17
- package/lib/azure-publicipaddress/lib/public-ip-address.d.ts +4 -13
- package/lib/azure-publicipaddress/lib/public-ip-address.js +14 -36
- package/lib/azure-resourcegroup/index.d.ts +0 -37
- package/lib/azure-resourcegroup/index.js +1 -39
- package/lib/azure-resourcegroup/lib/index.d.ts +1 -44
- package/lib/azure-resourcegroup/lib/index.js +2 -43
- package/lib/azure-resourcegroup/lib/resource-group.d.ts +9 -23
- package/lib/azure-resourcegroup/lib/resource-group.js +23 -56
- package/lib/azure-resourcegroup/test/resource-group.spec.js +13 -19
- package/lib/azure-roleassignment/index.d.ts +1 -0
- package/lib/azure-roleassignment/index.js +18 -0
- package/lib/azure-roleassignment/lib/index.d.ts +2 -0
- package/lib/azure-roleassignment/lib/index.js +19 -0
- package/lib/azure-roleassignment/lib/role-assignment-schemas.d.ts +25 -0
- package/lib/azure-roleassignment/lib/role-assignment-schemas.js +238 -0
- package/lib/azure-roleassignment/lib/role-assignment.d.ts +294 -0
- package/lib/azure-roleassignment/lib/role-assignment.js +257 -0
- package/lib/azure-roleassignment/test/role-assignment.integ.d.ts +12 -0
- package/lib/azure-roleassignment/test/role-assignment.integ.js +101 -0
- package/lib/azure-roleassignment/test/role-assignment.spec.d.ts +9 -0
- package/lib/azure-roleassignment/test/role-assignment.spec.js +633 -0
- package/lib/azure-roledefinition/index.d.ts +1 -0
- package/lib/azure-roledefinition/index.js +18 -0
- package/lib/azure-roledefinition/lib/index.d.ts +2 -0
- package/lib/azure-roledefinition/lib/index.js +19 -0
- package/lib/azure-roledefinition/lib/role-definition-schemas.d.ts +25 -0
- package/lib/azure-roledefinition/lib/role-definition-schemas.js +195 -0
- package/lib/azure-roledefinition/lib/role-definition.d.ts +236 -0
- package/lib/azure-roledefinition/lib/role-definition.js +192 -0
- package/lib/azure-roledefinition/test/role-definition.integ.d.ts +12 -0
- package/lib/azure-roledefinition/test/role-definition.integ.js +142 -0
- package/lib/azure-roledefinition/test/role-definition.spec.d.ts +9 -0
- package/lib/azure-roledefinition/test/role-definition.spec.js +946 -0
- package/lib/azure-storageaccount/index.d.ts +0 -19
- package/lib/azure-storageaccount/index.js +1 -20
- package/lib/azure-storageaccount/lib/index.d.ts +1 -7
- package/lib/azure-storageaccount/lib/index.js +2 -8
- package/lib/azure-storageaccount/lib/storage-account.d.ts +4 -9
- package/lib/azure-storageaccount/lib/storage-account.js +15 -29
- package/lib/azure-subnet/index.d.ts +0 -3
- package/lib/azure-subnet/index.js +1 -4
- package/lib/azure-subnet/lib/index.d.ts +1 -4
- package/lib/azure-subnet/lib/index.js +2 -5
- package/lib/azure-subnet/lib/subnet.d.ts +3 -14
- package/lib/azure-subnet/lib/subnet.js +28 -47
- package/lib/azure-subnet/test/subnet.integ.js +19 -7
- package/lib/azure-subnet/test/subnet.spec.js +1 -2
- package/lib/azure-virtualmachine/index.d.ts +0 -6
- package/lib/azure-virtualmachine/index.js +1 -7
- package/lib/azure-virtualmachine/lib/index.d.ts +1 -10
- package/lib/azure-virtualmachine/lib/index.js +2 -21
- package/lib/azure-virtualmachine/lib/virtual-machine.d.ts +4 -13
- package/lib/azure-virtualmachine/lib/virtual-machine.js +15 -36
- package/lib/azure-virtualnetwork/index.d.ts +0 -9
- package/lib/azure-virtualnetwork/index.js +1 -11
- package/lib/azure-virtualnetwork/lib/index.d.ts +2 -9
- package/lib/azure-virtualnetwork/lib/index.js +17 -20
- package/lib/azure-virtualnetwork/lib/virtual-network.d.ts +4 -13
- package/lib/azure-virtualnetwork/lib/virtual-network.js +15 -36
- package/lib/azure-virtualnetworkmanager/index.d.ts +1 -0
- package/lib/azure-virtualnetworkmanager/index.js +18 -0
- package/lib/azure-virtualnetworkmanager/lib/connectivity-configuration-schemas.d.ts +48 -0
- package/lib/azure-virtualnetworkmanager/lib/connectivity-configuration-schemas.js +265 -0
- package/lib/azure-virtualnetworkmanager/lib/connectivity-configuration.d.ts +185 -0
- package/lib/azure-virtualnetworkmanager/lib/connectivity-configuration.js +206 -0
- package/lib/azure-virtualnetworkmanager/lib/index.d.ts +14 -0
- package/lib/azure-virtualnetworkmanager/lib/index.js +31 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group-schemas.d.ts +32 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group-schemas.js +189 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group-static-member-schemas.d.ts +32 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group-static-member-schemas.js +201 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group-static-member.d.ts +135 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group-static-member.js +163 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group.d.ts +139 -0
- package/lib/azure-virtualnetworkmanager/lib/network-group.js +158 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-configuration-schemas.d.ts +32 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-configuration-schemas.js +182 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-configuration.d.ts +144 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-configuration.js +164 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule-collection-schemas.d.ts +38 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule-collection-schemas.js +206 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule-collection.d.ts +142 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule-collection.js +162 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule-schemas.d.ts +39 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule-schemas.js +359 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule.d.ts +221 -0
- package/lib/azure-virtualnetworkmanager/lib/security-admin-rule.js +204 -0
- package/lib/azure-virtualnetworkmanager/lib/virtual-network-manager-schemas.d.ts +32 -0
- package/lib/azure-virtualnetworkmanager/lib/virtual-network-manager-schemas.js +236 -0
- package/lib/azure-virtualnetworkmanager/lib/virtual-network-manager.d.ts +337 -0
- package/lib/azure-virtualnetworkmanager/lib/virtual-network-manager.js +283 -0
- package/lib/azure-virtualnetworkmanager/test/virtual-network-manager.integ.d.ts +25 -0
- package/lib/azure-virtualnetworkmanager/test/virtual-network-manager.integ.js +402 -0
- package/lib/azure-virtualnetworkmanager/test/virtual-network-manager.spec.d.ts +9 -0
- package/lib/azure-virtualnetworkmanager/test/virtual-network-manager.spec.js +1652 -0
- package/lib/azure-vmss/index.d.ts +0 -5
- package/lib/azure-vmss/index.js +1 -6
- package/lib/azure-vmss/lib/index.d.ts +0 -7
- package/lib/azure-vmss/lib/index.js +1 -21
- package/lib/azure-vmss/lib/virtual-machine-scale-set.d.ts +5 -13
- package/lib/azure-vmss/lib/virtual-machine-scale-set.js +29 -53
- package/lib/core-azure/lib/azapi/azapi-resource-tags.spec.d.ts +10 -0
- package/lib/core-azure/lib/azapi/azapi-resource-tags.spec.js +218 -0
- package/lib/core-azure/lib/azapi/azapi-resource.d.ts +206 -26
- package/lib/core-azure/lib/azapi/azapi-resource.js +379 -91
- package/lib/core-azure/lib/azapi/azapi-resource.spec.js +2 -2
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-client-config/index.js +2 -2
- package/lib/core-azure/lib/azapi/providers-azapi/data-azapi-resource/index.js +5 -5
- package/lib/core-azure/lib/azapi/providers-azapi/provider/index.js +5 -3
- package/lib/core-azure/lib/azapi/providers-azapi/resource/index.js +5 -5
- package/lib/core-azure/lib/azapi/providers-azapi/resource-action/index.js +3 -3
- package/lib/core-azure/lib/azapi/providers-azapi/update-resource/index.js +3 -3
- package/lib/core-azure/lib/azapi/resource-schema-validator.d.ts +118 -0
- package/lib/core-azure/lib/azapi/resource-schema-validator.js +236 -0
- package/lib/core-azure/lib/azapi/resource-version-manager.d.ts +103 -0
- package/lib/core-azure/lib/azapi/resource-version-manager.js +168 -0
- package/lib/core-azure/lib/azapi/schema-mapper/schema-mapper.js +11 -6
- package/lib/core-azure/lib/index.d.ts +2 -2
- package/lib/core-azure/lib/index.js +5 -5
- 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 +19 -0
- package/lib/index.js +21 -2
- package/lib/testing/index.js +2 -2
- package/lib/testing/lib/cleanup.d.ts +1 -0
- package/lib/testing/lib/cleanup.js +19 -12
- package/lib/testing/lib/metadata.js +19 -16
- package/package.json +1 -1
- package/scripts/cleanup-test-resources.ts +22 -4
- package/scripts/generate-index.js +25 -8
|
@@ -0,0 +1,806 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Comprehensive tests for the unified PolicyDefinition implementation
|
|
4
|
+
*
|
|
5
|
+
* This test suite validates the unified PolicyDefinition class that uses
|
|
6
|
+
* the VersionedAzapiResource framework. Tests cover automatic version resolution,
|
|
7
|
+
* explicit version pinning, schema validation, property transformation, and
|
|
8
|
+
* policy-specific functionality.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const cdktf_1 = require("cdktf");
|
|
12
|
+
const cdktf = require("cdktf");
|
|
13
|
+
const api_version_manager_1 = require("../../core-azure/lib/version-manager/api-version-manager");
|
|
14
|
+
const version_interfaces_1 = require("../../core-azure/lib/version-manager/interfaces/version-interfaces");
|
|
15
|
+
const policy_definition_1 = require("../lib/policy-definition");
|
|
16
|
+
const policy_definition_schemas_1 = require("../lib/policy-definition-schemas");
|
|
17
|
+
describe("PolicyDefinition - Unified Implementation", () => {
|
|
18
|
+
let app;
|
|
19
|
+
let stack;
|
|
20
|
+
let manager;
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
app = cdktf_1.Testing.app();
|
|
23
|
+
stack = new cdktf.TerraformStack(app, "TestStack");
|
|
24
|
+
manager = api_version_manager_1.ApiVersionManager.instance();
|
|
25
|
+
// Ensure Policy Definition schemas are registered
|
|
26
|
+
try {
|
|
27
|
+
manager.registerResourceType(policy_definition_schemas_1.POLICY_DEFINITION_TYPE, policy_definition_schemas_1.ALL_POLICY_DEFINITION_VERSIONS);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// Ignore if already registered
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
describe("Constructor and Basic Properties", () => {
|
|
34
|
+
it("should create policy definition with automatic latest version resolution", () => {
|
|
35
|
+
const props = {
|
|
36
|
+
name: "test-policy",
|
|
37
|
+
policyRule: {
|
|
38
|
+
if: {
|
|
39
|
+
field: "tags['Environment']",
|
|
40
|
+
exists: "false",
|
|
41
|
+
},
|
|
42
|
+
then: {
|
|
43
|
+
effect: "deny",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", props);
|
|
48
|
+
expect(policyDefinition).toBeInstanceOf(policy_definition_1.PolicyDefinition);
|
|
49
|
+
expect(policyDefinition.resolvedApiVersion).toBe("2021-06-01"); // Latest version
|
|
50
|
+
expect(policyDefinition.props).toBe(props);
|
|
51
|
+
expect(policyDefinition.name).toBe("test-policy");
|
|
52
|
+
});
|
|
53
|
+
it("should create policy definition with explicit version pinning", () => {
|
|
54
|
+
const props = {
|
|
55
|
+
name: "test-policy-pinned",
|
|
56
|
+
apiVersion: "2021-06-01",
|
|
57
|
+
policyRule: {
|
|
58
|
+
if: {
|
|
59
|
+
field: "type",
|
|
60
|
+
equals: "Microsoft.Compute/virtualMachines",
|
|
61
|
+
},
|
|
62
|
+
then: {
|
|
63
|
+
effect: "audit",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", props);
|
|
68
|
+
expect(policyDefinition.resolvedApiVersion).toBe("2021-06-01");
|
|
69
|
+
});
|
|
70
|
+
it("should create policy definition with all optional properties", () => {
|
|
71
|
+
const props = {
|
|
72
|
+
name: "test-policy-full",
|
|
73
|
+
displayName: "Test Policy Definition",
|
|
74
|
+
description: "A test policy definition for unit testing",
|
|
75
|
+
policyType: "Custom",
|
|
76
|
+
mode: "All",
|
|
77
|
+
policyRule: {
|
|
78
|
+
if: {
|
|
79
|
+
field: "location",
|
|
80
|
+
notIn: ["eastus", "westus"],
|
|
81
|
+
},
|
|
82
|
+
then: {
|
|
83
|
+
effect: "deny",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
parameters: {
|
|
87
|
+
allowedLocations: {
|
|
88
|
+
type: "Array",
|
|
89
|
+
metadata: {
|
|
90
|
+
displayName: "Allowed locations",
|
|
91
|
+
description: "The list of allowed locations for resources",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
metadata: {
|
|
96
|
+
category: "General",
|
|
97
|
+
version: "1.0.0",
|
|
98
|
+
},
|
|
99
|
+
ignoreChanges: ["metadata"],
|
|
100
|
+
enableValidation: true,
|
|
101
|
+
enableMigrationAnalysis: true,
|
|
102
|
+
enableTransformation: true,
|
|
103
|
+
};
|
|
104
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", props);
|
|
105
|
+
expect(policyDefinition.props.displayName).toBe("Test Policy Definition");
|
|
106
|
+
expect(policyDefinition.props.description).toBe("A test policy definition for unit testing");
|
|
107
|
+
expect(policyDefinition.props.policyType).toBe("Custom");
|
|
108
|
+
expect(policyDefinition.props.mode).toBe("All");
|
|
109
|
+
expect(policyDefinition.props.parameters).toBeDefined();
|
|
110
|
+
expect(policyDefinition.props.metadata).toBeDefined();
|
|
111
|
+
});
|
|
112
|
+
it("should use default name when name is not provided", () => {
|
|
113
|
+
const props = {
|
|
114
|
+
policyRule: {
|
|
115
|
+
if: {
|
|
116
|
+
field: "type",
|
|
117
|
+
equals: "Microsoft.Storage/storageAccounts",
|
|
118
|
+
},
|
|
119
|
+
then: {
|
|
120
|
+
effect: "audit",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", props);
|
|
125
|
+
expect(policyDefinition.name).toBe("TestPolicyDefinition");
|
|
126
|
+
});
|
|
127
|
+
it("should require policyRule to be provided", () => {
|
|
128
|
+
const props = {
|
|
129
|
+
name: "test-policy",
|
|
130
|
+
};
|
|
131
|
+
expect(() => {
|
|
132
|
+
new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", props);
|
|
133
|
+
}).toThrow("Required property 'policyRule' is missing");
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
describe("Framework Integration", () => {
|
|
137
|
+
it("should resolve latest API version automatically", () => {
|
|
138
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
139
|
+
name: "test-policy",
|
|
140
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
141
|
+
});
|
|
142
|
+
expect(policyDefinition.resolvedApiVersion).toBe("2021-06-01");
|
|
143
|
+
expect(policyDefinition.latestVersion()).toBe("2021-06-01");
|
|
144
|
+
});
|
|
145
|
+
it("should support all registered API versions", () => {
|
|
146
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
147
|
+
name: "test-policy",
|
|
148
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
149
|
+
});
|
|
150
|
+
const supportedVersions = policyDefinition.supportedVersions();
|
|
151
|
+
expect(supportedVersions).toContain("2021-06-01");
|
|
152
|
+
});
|
|
153
|
+
it("should validate version support", () => {
|
|
154
|
+
// Valid version
|
|
155
|
+
expect(() => {
|
|
156
|
+
new policy_definition_1.PolicyDefinition(stack, "ValidVersion", {
|
|
157
|
+
name: "test-policy",
|
|
158
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
159
|
+
apiVersion: "2021-06-01",
|
|
160
|
+
});
|
|
161
|
+
}).not.toThrow();
|
|
162
|
+
// Invalid version
|
|
163
|
+
expect(() => {
|
|
164
|
+
new policy_definition_1.PolicyDefinition(stack, "InvalidVersion", {
|
|
165
|
+
name: "test-policy",
|
|
166
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
167
|
+
apiVersion: "2022-01-01",
|
|
168
|
+
});
|
|
169
|
+
}).toThrow("Unsupported API version '2022-01-01'");
|
|
170
|
+
});
|
|
171
|
+
it("should load correct schema for resolved version", () => {
|
|
172
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
173
|
+
name: "test-policy",
|
|
174
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
175
|
+
apiVersion: "2021-06-01",
|
|
176
|
+
});
|
|
177
|
+
expect(policyDefinition.schema).toBeDefined();
|
|
178
|
+
expect(policyDefinition.schema.resourceType).toBe(policy_definition_schemas_1.POLICY_DEFINITION_TYPE);
|
|
179
|
+
expect(policyDefinition.schema.version).toBe("2021-06-01");
|
|
180
|
+
expect(policyDefinition.schema.properties).toBeDefined();
|
|
181
|
+
});
|
|
182
|
+
it("should load version configuration correctly", () => {
|
|
183
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
184
|
+
name: "test-policy",
|
|
185
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
186
|
+
});
|
|
187
|
+
expect(policyDefinition.versionConfig).toBeDefined();
|
|
188
|
+
expect(policyDefinition.versionConfig.version).toBe("2021-06-01");
|
|
189
|
+
expect(policyDefinition.versionConfig.supportLevel).toBe(version_interfaces_1.VersionSupportLevel.ACTIVE);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
describe("Property Validation", () => {
|
|
193
|
+
it("should validate properties when validation is enabled", () => {
|
|
194
|
+
const props = {
|
|
195
|
+
name: "test-policy",
|
|
196
|
+
policyRule: {
|
|
197
|
+
if: {
|
|
198
|
+
field: "type",
|
|
199
|
+
equals: "Microsoft.Compute/virtualMachines",
|
|
200
|
+
},
|
|
201
|
+
then: {
|
|
202
|
+
effect: "audit",
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
enableValidation: true,
|
|
206
|
+
};
|
|
207
|
+
expect(() => {
|
|
208
|
+
new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", props);
|
|
209
|
+
}).not.toThrow();
|
|
210
|
+
});
|
|
211
|
+
it("should have validation results for valid properties", () => {
|
|
212
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
213
|
+
name: "valid-policy",
|
|
214
|
+
displayName: "Valid Policy",
|
|
215
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
216
|
+
enableValidation: true,
|
|
217
|
+
});
|
|
218
|
+
expect(policyDefinition.validationResult).toBeDefined();
|
|
219
|
+
expect(policyDefinition.validationResult.valid).toBe(true);
|
|
220
|
+
expect(policyDefinition.validationResult.errors).toHaveLength(0);
|
|
221
|
+
});
|
|
222
|
+
it("should skip validation when disabled", () => {
|
|
223
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
224
|
+
name: "test-policy",
|
|
225
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
226
|
+
enableValidation: false,
|
|
227
|
+
});
|
|
228
|
+
expect(policyDefinition).toBeDefined();
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
describe("Migration Analysis", () => {
|
|
232
|
+
it("should skip migration analysis for single version", () => {
|
|
233
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
234
|
+
name: "test-policy",
|
|
235
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
236
|
+
apiVersion: "2021-06-01",
|
|
237
|
+
});
|
|
238
|
+
// Since there's only one version, migration analysis should be skipped
|
|
239
|
+
expect(policyDefinition).toBeDefined();
|
|
240
|
+
});
|
|
241
|
+
it("should skip migration analysis when disabled", () => {
|
|
242
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
243
|
+
name: "test-policy",
|
|
244
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
245
|
+
enableMigrationAnalysis: false,
|
|
246
|
+
});
|
|
247
|
+
expect(policyDefinition.migrationAnalysis).toBeUndefined();
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
describe("Resource Creation and Body", () => {
|
|
251
|
+
it("should create correct resource body with minimal properties", () => {
|
|
252
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
253
|
+
name: "test-policy",
|
|
254
|
+
policyRule: {
|
|
255
|
+
if: {
|
|
256
|
+
field: "tags['Environment']",
|
|
257
|
+
exists: "false",
|
|
258
|
+
},
|
|
259
|
+
then: {
|
|
260
|
+
effect: "deny",
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
expect(policyDefinition).toBeDefined();
|
|
265
|
+
expect(policyDefinition.props.policyRule).toBeDefined();
|
|
266
|
+
});
|
|
267
|
+
it("should create correct resource body with all properties", () => {
|
|
268
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
269
|
+
name: "test-policy",
|
|
270
|
+
displayName: "Test Policy",
|
|
271
|
+
description: "A test policy",
|
|
272
|
+
policyType: "Custom",
|
|
273
|
+
mode: "Indexed",
|
|
274
|
+
policyRule: {
|
|
275
|
+
if: {
|
|
276
|
+
field: "location",
|
|
277
|
+
notIn: ["eastus", "westus"],
|
|
278
|
+
},
|
|
279
|
+
then: {
|
|
280
|
+
effect: "deny",
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
parameters: {
|
|
284
|
+
allowedLocations: {
|
|
285
|
+
type: "Array",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
metadata: {
|
|
289
|
+
category: "Compliance",
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
expect(policyDefinition).toBeDefined();
|
|
293
|
+
expect(policyDefinition.props.displayName).toBe("Test Policy");
|
|
294
|
+
expect(policyDefinition.props.policyType).toBe("Custom");
|
|
295
|
+
expect(policyDefinition.props.mode).toBe("Indexed");
|
|
296
|
+
});
|
|
297
|
+
it("should create Terraform outputs", () => {
|
|
298
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
299
|
+
name: "test-policy-outputs",
|
|
300
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
301
|
+
});
|
|
302
|
+
expect(policyDefinition.idOutput).toBeInstanceOf(cdktf.TerraformOutput);
|
|
303
|
+
expect(policyDefinition.nameOutput).toBeInstanceOf(cdktf.TerraformOutput);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
describe("Public Methods and Properties", () => {
|
|
307
|
+
let policyDefinition;
|
|
308
|
+
beforeEach(() => {
|
|
309
|
+
policyDefinition = new policy_definition_1.PolicyDefinition(stack, "TestPolicyDefinition", {
|
|
310
|
+
name: "test-policy",
|
|
311
|
+
displayName: "Test Policy",
|
|
312
|
+
policyType: "Custom",
|
|
313
|
+
mode: "All",
|
|
314
|
+
policyRule: {
|
|
315
|
+
if: {
|
|
316
|
+
field: "type",
|
|
317
|
+
equals: "Microsoft.Compute/virtualMachines",
|
|
318
|
+
},
|
|
319
|
+
then: {
|
|
320
|
+
effect: "audit",
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
it("should have correct id format", () => {
|
|
326
|
+
expect(policyDefinition.id).toMatch(/^\$\{.*\.id\}$/);
|
|
327
|
+
});
|
|
328
|
+
it("should have resourceId property matching id", () => {
|
|
329
|
+
expect(policyDefinition.resourceId).toBe(policyDefinition.id);
|
|
330
|
+
});
|
|
331
|
+
it("should return correct policyType", () => {
|
|
332
|
+
expect(policyDefinition.policyType).toBe("Custom");
|
|
333
|
+
});
|
|
334
|
+
it("should return correct policyMode", () => {
|
|
335
|
+
expect(policyDefinition.policyMode).toBe("All");
|
|
336
|
+
});
|
|
337
|
+
it("should use default policyType when not provided", () => {
|
|
338
|
+
const defaultPolicy = new policy_definition_1.PolicyDefinition(stack, "DefaultTypePolicy", {
|
|
339
|
+
name: "default-policy",
|
|
340
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
341
|
+
});
|
|
342
|
+
expect(defaultPolicy.policyType).toBe("Custom");
|
|
343
|
+
});
|
|
344
|
+
it("should use default mode when not provided", () => {
|
|
345
|
+
const defaultPolicy = new policy_definition_1.PolicyDefinition(stack, "DefaultModePolicy", {
|
|
346
|
+
name: "default-policy",
|
|
347
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
348
|
+
});
|
|
349
|
+
expect(defaultPolicy.policyMode).toBe("All");
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
describe("Ignore Changes Configuration", () => {
|
|
353
|
+
it("should apply ignore changes lifecycle rules", () => {
|
|
354
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "IgnoreChangesPolicy", {
|
|
355
|
+
name: "test-policy",
|
|
356
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
357
|
+
ignoreChanges: ["metadata", "description"],
|
|
358
|
+
});
|
|
359
|
+
expect(policyDefinition).toBeInstanceOf(policy_definition_1.PolicyDefinition);
|
|
360
|
+
});
|
|
361
|
+
it("should handle empty ignore changes array", () => {
|
|
362
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "EmptyIgnorePolicy", {
|
|
363
|
+
name: "test-policy",
|
|
364
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
365
|
+
ignoreChanges: [],
|
|
366
|
+
});
|
|
367
|
+
expect(policyDefinition).toBeInstanceOf(policy_definition_1.PolicyDefinition);
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
describe("Policy Rule Validation", () => {
|
|
371
|
+
it("should accept complex policy rules", () => {
|
|
372
|
+
const complexRule = {
|
|
373
|
+
if: {
|
|
374
|
+
allOf: [
|
|
375
|
+
{
|
|
376
|
+
field: "type",
|
|
377
|
+
equals: "Microsoft.Storage/storageAccounts",
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
field: "Microsoft.Storage/storageAccounts/enableHttpsTrafficOnly",
|
|
381
|
+
notEquals: "true",
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
},
|
|
385
|
+
then: {
|
|
386
|
+
effect: "deny",
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "ComplexRulePolicy", {
|
|
390
|
+
name: "complex-policy",
|
|
391
|
+
policyRule: complexRule,
|
|
392
|
+
});
|
|
393
|
+
expect(policyDefinition).toBeDefined();
|
|
394
|
+
expect(policyDefinition.props.policyRule).toEqual(complexRule);
|
|
395
|
+
});
|
|
396
|
+
it("should accept policy rules with parameters", () => {
|
|
397
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "ParameterizedPolicy", {
|
|
398
|
+
name: "parameterized-policy",
|
|
399
|
+
policyRule: {
|
|
400
|
+
if: {
|
|
401
|
+
field: "[concat('tags[', parameters('tagName'), ']')]",
|
|
402
|
+
exists: "false",
|
|
403
|
+
},
|
|
404
|
+
then: {
|
|
405
|
+
effect: "[parameters('effect')]",
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
parameters: {
|
|
409
|
+
tagName: {
|
|
410
|
+
type: "String",
|
|
411
|
+
metadata: {
|
|
412
|
+
displayName: "Tag Name",
|
|
413
|
+
description: "Name of the tag to check",
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
effect: {
|
|
417
|
+
type: "String",
|
|
418
|
+
allowedValues: ["audit", "deny"],
|
|
419
|
+
defaultValue: "audit",
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
});
|
|
423
|
+
expect(policyDefinition).toBeDefined();
|
|
424
|
+
expect(policyDefinition.props.parameters).toBeDefined();
|
|
425
|
+
});
|
|
426
|
+
it("should preserve complex allOf conditions with multiple field comparisons", () => {
|
|
427
|
+
const complexRule = {
|
|
428
|
+
if: {
|
|
429
|
+
allOf: [
|
|
430
|
+
{
|
|
431
|
+
field: "type",
|
|
432
|
+
equals: "Microsoft.Storage/storageAccounts",
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
field: "Microsoft.Storage/storageAccounts/networkAcls.defaultAction",
|
|
436
|
+
notEquals: "Deny",
|
|
437
|
+
},
|
|
438
|
+
],
|
|
439
|
+
},
|
|
440
|
+
then: {
|
|
441
|
+
effect: "audit",
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "ComplexAllOf", {
|
|
445
|
+
name: "complex-allof-policy",
|
|
446
|
+
displayName: "Complex AllOf Policy",
|
|
447
|
+
policyRule: complexRule,
|
|
448
|
+
});
|
|
449
|
+
expect(policyDefinition).toBeDefined();
|
|
450
|
+
expect(policyDefinition.props.policyRule).toEqual(complexRule);
|
|
451
|
+
// Synthesize and verify the structure is preserved
|
|
452
|
+
const synthesized = cdktf_1.Testing.synth(stack);
|
|
453
|
+
const stackConfig = JSON.parse(synthesized);
|
|
454
|
+
const azapiResource = Object.values(stackConfig.resource.azapi_resource)[0];
|
|
455
|
+
// The body is jsonencode() wrapped, so we need to parse the actual policy rule from props
|
|
456
|
+
expect(policyDefinition.props.policyRule.if.allOf).toHaveLength(2);
|
|
457
|
+
expect(policyDefinition.props.policyRule.if.allOf[0].field).toBe("type");
|
|
458
|
+
expect(policyDefinition.props.policyRule.if.allOf[0].equals).toBe("Microsoft.Storage/storageAccounts");
|
|
459
|
+
expect(policyDefinition.props.policyRule.if.allOf[1].field).toBe("Microsoft.Storage/storageAccounts/networkAcls.defaultAction");
|
|
460
|
+
expect(policyDefinition.props.policyRule.if.allOf[1].notEquals).toBe("Deny");
|
|
461
|
+
expect(policyDefinition.props.policyRule.then.effect).toBe("audit");
|
|
462
|
+
// Verify the synthesized config has the body property set
|
|
463
|
+
expect(azapiResource.body).toBeDefined();
|
|
464
|
+
});
|
|
465
|
+
it("should preserve Azure Policy expressions without converting them", () => {
|
|
466
|
+
const rule = {
|
|
467
|
+
if: {
|
|
468
|
+
field: "location",
|
|
469
|
+
notIn: "[parameters('allowedLocations')]",
|
|
470
|
+
},
|
|
471
|
+
then: {
|
|
472
|
+
effect: "[parameters('effect')]",
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
new policy_definition_1.PolicyDefinition(stack, "AzurePolicyExpressions", {
|
|
476
|
+
name: "azure-expressions-policy",
|
|
477
|
+
policyRule: rule,
|
|
478
|
+
parameters: {
|
|
479
|
+
allowedLocations: { type: "Array" },
|
|
480
|
+
effect: { type: "String" },
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
const synthesized = cdktf_1.Testing.synth(stack);
|
|
484
|
+
const stackConfig = JSON.parse(synthesized);
|
|
485
|
+
const azapiResource = Object.values(stackConfig.resource.azapi_resource)[0];
|
|
486
|
+
// Verify Azure Policy expressions are preserved in the construct's props
|
|
487
|
+
expect(rule.if.notIn).toBe("[parameters('allowedLocations')]");
|
|
488
|
+
expect(rule.then.effect).toBe("[parameters('effect')]");
|
|
489
|
+
// Verify the synthesized config has the body property set
|
|
490
|
+
expect(azapiResource.body).toBeDefined();
|
|
491
|
+
});
|
|
492
|
+
it("should preserve DeployIfNotExists policy with ARM template", () => {
|
|
493
|
+
const complexRule = {
|
|
494
|
+
if: {
|
|
495
|
+
field: "type",
|
|
496
|
+
equals: "Microsoft.Network/virtualNetworks",
|
|
497
|
+
},
|
|
498
|
+
then: {
|
|
499
|
+
effect: "DeployIfNotExists",
|
|
500
|
+
details: {
|
|
501
|
+
type: "Microsoft.Network/networkManagers/networkGroups/staticMembers",
|
|
502
|
+
deploymentScope: "subscription",
|
|
503
|
+
existenceScope: "subscription",
|
|
504
|
+
roleDefinitionIds: [
|
|
505
|
+
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c",
|
|
506
|
+
],
|
|
507
|
+
deployment: {
|
|
508
|
+
location: "[field('location')]",
|
|
509
|
+
properties: {
|
|
510
|
+
mode: "incremental",
|
|
511
|
+
resourceGroup: "[variables('avnmResourceGroup')]",
|
|
512
|
+
subscriptionId: "[parameters('avnmSubscriptionId')]",
|
|
513
|
+
template: {
|
|
514
|
+
$schema: "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
|
515
|
+
contentVersion: "1.0.0.0",
|
|
516
|
+
parameters: {
|
|
517
|
+
vnetId: {
|
|
518
|
+
type: "string",
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
variables: {
|
|
522
|
+
staticMemberName: "[guid(parameters('vnetId'))]",
|
|
523
|
+
},
|
|
524
|
+
resources: [
|
|
525
|
+
{
|
|
526
|
+
type: "Microsoft.Network/networkManagers/networkGroups/staticMembers",
|
|
527
|
+
apiVersion: "2023-04-01",
|
|
528
|
+
name: "[concat(parameters('avnmId'), '/', variables('staticMemberName'))]",
|
|
529
|
+
properties: {
|
|
530
|
+
resourceId: "[parameters('vnetId')]",
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
],
|
|
534
|
+
outputs: {
|
|
535
|
+
memberId: {
|
|
536
|
+
type: "string",
|
|
537
|
+
value: "[resourceId('Microsoft.Network/networkManagers/networkGroups/staticMembers', variables('staticMemberName'))]",
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
parameters: {
|
|
542
|
+
vnetId: {
|
|
543
|
+
value: "[field('id')]",
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
};
|
|
551
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "DeployIfNotExistsPolicy", {
|
|
552
|
+
name: "deploy-if-not-exists-policy",
|
|
553
|
+
displayName: "Deploy If Not Exists with ARM Template",
|
|
554
|
+
policyRule: complexRule,
|
|
555
|
+
parameters: {
|
|
556
|
+
avnmSubscriptionId: { type: "String" },
|
|
557
|
+
},
|
|
558
|
+
});
|
|
559
|
+
expect(policyDefinition).toBeDefined();
|
|
560
|
+
const synthesized = cdktf_1.Testing.synth(stack);
|
|
561
|
+
const stackConfig = JSON.parse(synthesized);
|
|
562
|
+
const azapiResource = Object.values(stackConfig.resource.azapi_resource)[0];
|
|
563
|
+
const details = policyDefinition.props.policyRule.then.details;
|
|
564
|
+
// Verify deployment structure is preserved (not converted to null)
|
|
565
|
+
expect(details.deployment).toBeDefined();
|
|
566
|
+
expect(details.deployment.location).toBe("[field('location')]");
|
|
567
|
+
expect(details.deployment.properties).toBeDefined();
|
|
568
|
+
expect(details.deployment.properties.mode).toBe("incremental");
|
|
569
|
+
expect(details.deployment.properties.resourceGroup).toBe("[variables('avnmResourceGroup')]");
|
|
570
|
+
expect(details.deployment.properties.subscriptionId).toBe("[parameters('avnmSubscriptionId')]");
|
|
571
|
+
// Verify ARM template is fully preserved (not converted to null)
|
|
572
|
+
const template = details.deployment.properties.template;
|
|
573
|
+
expect(template).toBeDefined();
|
|
574
|
+
expect(template.$schema).toBe("https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#");
|
|
575
|
+
expect(template.contentVersion).toBe("1.0.0.0");
|
|
576
|
+
expect(template.parameters).toBeDefined();
|
|
577
|
+
expect(template.parameters.vnetId).toBeDefined();
|
|
578
|
+
expect(template.variables).toBeDefined();
|
|
579
|
+
expect(template.variables.staticMemberName).toBe("[guid(parameters('vnetId'))]");
|
|
580
|
+
expect(template.resources).toHaveLength(1);
|
|
581
|
+
expect(template.resources[0].name).toBe("[concat(parameters('avnmId'), '/', variables('staticMemberName'))]");
|
|
582
|
+
expect(template.outputs).toBeDefined();
|
|
583
|
+
expect(template.outputs.memberId.value).toBe("[resourceId('Microsoft.Network/networkManagers/networkGroups/staticMembers', variables('staticMemberName'))]");
|
|
584
|
+
// Verify ARM template parameters are preserved
|
|
585
|
+
const deploymentParams = details.deployment.properties.parameters;
|
|
586
|
+
expect(deploymentParams).toBeDefined();
|
|
587
|
+
expect(deploymentParams.vnetId.value).toBe("[field('id')]");
|
|
588
|
+
// Verify schema validation is disabled to allow complex nested structures
|
|
589
|
+
expect(azapiResource.schema_validation_enabled).toBe(false);
|
|
590
|
+
expect(azapiResource.ignore_missing_property).toBe(true);
|
|
591
|
+
// Verify the synthesized config has the body property set
|
|
592
|
+
expect(azapiResource.body).toBeDefined();
|
|
593
|
+
});
|
|
594
|
+
it("should preserve deeply nested logical operators", () => {
|
|
595
|
+
const complexRule = {
|
|
596
|
+
if: {
|
|
597
|
+
allOf: [
|
|
598
|
+
{
|
|
599
|
+
field: "type",
|
|
600
|
+
equals: "Microsoft.Network/virtualNetworks",
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
anyOf: [
|
|
604
|
+
{
|
|
605
|
+
field: "Microsoft.Network/virtualNetworks/enableDdosProtection",
|
|
606
|
+
equals: "false",
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
not: {
|
|
610
|
+
field: "Microsoft.Network/virtualNetworks/subnets[*].serviceEndpoints[*].service",
|
|
611
|
+
contains: "Microsoft.Storage",
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
],
|
|
615
|
+
},
|
|
616
|
+
],
|
|
617
|
+
},
|
|
618
|
+
then: {
|
|
619
|
+
effect: "audit",
|
|
620
|
+
},
|
|
621
|
+
};
|
|
622
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "DeeplyNested", {
|
|
623
|
+
name: "deeply-nested-policy",
|
|
624
|
+
policyRule: complexRule,
|
|
625
|
+
});
|
|
626
|
+
expect(policyDefinition.props.policyRule).toEqual(complexRule);
|
|
627
|
+
const synthesized = cdktf_1.Testing.synth(stack);
|
|
628
|
+
const stackConfig = JSON.parse(synthesized);
|
|
629
|
+
const azapiResource = Object.values(stackConfig.resource.azapi_resource)[0];
|
|
630
|
+
// Verify the deeply nested structure is preserved in the construct's props
|
|
631
|
+
expect(policyDefinition.props.policyRule.if.allOf[1].anyOf[1].not).toBeDefined();
|
|
632
|
+
expect(policyDefinition.props.policyRule.if.allOf[1].anyOf[1].not.field).toBe("Microsoft.Network/virtualNetworks/subnets[*].serviceEndpoints[*].service");
|
|
633
|
+
// Verify the synthesized config has the body property set
|
|
634
|
+
expect(azapiResource.body).toBeDefined();
|
|
635
|
+
});
|
|
636
|
+
});
|
|
637
|
+
describe("Error Handling", () => {
|
|
638
|
+
it("should handle invalid API versions gracefully", () => {
|
|
639
|
+
expect(() => {
|
|
640
|
+
new policy_definition_1.PolicyDefinition(stack, "InvalidAPI", {
|
|
641
|
+
name: "test-policy",
|
|
642
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
643
|
+
apiVersion: "invalid-version",
|
|
644
|
+
});
|
|
645
|
+
}).toThrow("Unsupported API version 'invalid-version'");
|
|
646
|
+
});
|
|
647
|
+
it("should handle validation errors when validation is enabled", () => {
|
|
648
|
+
expect(() => {
|
|
649
|
+
new policy_definition_1.PolicyDefinition(stack, "ValidationError", {
|
|
650
|
+
name: "test-policy",
|
|
651
|
+
policyRule: undefined, // Missing required policyRule
|
|
652
|
+
enableValidation: true,
|
|
653
|
+
});
|
|
654
|
+
}).toThrow("Required property 'policyRule' is missing");
|
|
655
|
+
});
|
|
656
|
+
it("should handle schema registration errors gracefully", () => {
|
|
657
|
+
expect(() => {
|
|
658
|
+
new policy_definition_1.PolicyDefinition(stack, "SchemaTest", {
|
|
659
|
+
name: "test-policy",
|
|
660
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
661
|
+
});
|
|
662
|
+
}).not.toThrow();
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
describe("JSII Compliance", () => {
|
|
666
|
+
it("should have JSII-compliant constructor", () => {
|
|
667
|
+
expect(() => {
|
|
668
|
+
new policy_definition_1.PolicyDefinition(stack, "JsiiTest", {
|
|
669
|
+
name: "jsii-test",
|
|
670
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
671
|
+
});
|
|
672
|
+
}).not.toThrow();
|
|
673
|
+
});
|
|
674
|
+
it("should have JSII-compliant properties", () => {
|
|
675
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "JsiiProps", {
|
|
676
|
+
name: "jsii-props",
|
|
677
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
678
|
+
});
|
|
679
|
+
expect(typeof policyDefinition.id).toBe("string");
|
|
680
|
+
expect(typeof policyDefinition.name).toBe("string");
|
|
681
|
+
expect(typeof policyDefinition.resolvedApiVersion).toBe("string");
|
|
682
|
+
expect(typeof policyDefinition.policyType).toBe("string");
|
|
683
|
+
expect(typeof policyDefinition.policyMode).toBe("string");
|
|
684
|
+
});
|
|
685
|
+
it("should have JSII-compliant methods", () => {
|
|
686
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "JsiiMethods", {
|
|
687
|
+
name: "jsii-methods",
|
|
688
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
689
|
+
});
|
|
690
|
+
expect(typeof policyDefinition.latestVersion).toBe("function");
|
|
691
|
+
expect(typeof policyDefinition.supportedVersions).toBe("function");
|
|
692
|
+
});
|
|
693
|
+
it("should serialize complex objects correctly", () => {
|
|
694
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "JsiiSerialization", {
|
|
695
|
+
name: "jsii-serialization",
|
|
696
|
+
policyRule: {
|
|
697
|
+
if: { field: "location", equals: "eastus" },
|
|
698
|
+
then: { effect: "deny" },
|
|
699
|
+
},
|
|
700
|
+
parameters: {
|
|
701
|
+
testParam: {
|
|
702
|
+
type: "String",
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
});
|
|
706
|
+
expect(() => JSON.stringify(policyDefinition.validationResult)).not.toThrow();
|
|
707
|
+
expect(() => JSON.stringify(policyDefinition.schema)).not.toThrow();
|
|
708
|
+
expect(() => JSON.stringify(policyDefinition.versionConfig)).not.toThrow();
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
describe("CDK Terraform Integration", () => {
|
|
712
|
+
it("should synthesize to valid Terraform configuration", () => {
|
|
713
|
+
new policy_definition_1.PolicyDefinition(stack, "SynthTest", {
|
|
714
|
+
name: "synth-test",
|
|
715
|
+
policyRule: {
|
|
716
|
+
if: {
|
|
717
|
+
field: "type",
|
|
718
|
+
equals: "Microsoft.Compute/virtualMachines",
|
|
719
|
+
},
|
|
720
|
+
then: {
|
|
721
|
+
effect: "audit",
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
});
|
|
725
|
+
const synthesized = cdktf_1.Testing.synth(stack);
|
|
726
|
+
expect(synthesized).toBeDefined();
|
|
727
|
+
const stackConfig = JSON.parse(synthesized);
|
|
728
|
+
expect(stackConfig.resource).toBeDefined();
|
|
729
|
+
});
|
|
730
|
+
it("should work in complex CDK constructs", () => {
|
|
731
|
+
class ComplexConstruct extends cdktf.TerraformStack {
|
|
732
|
+
constructor(scope, id) {
|
|
733
|
+
super(scope, id);
|
|
734
|
+
const policy1 = new policy_definition_1.PolicyDefinition(this, "Policy1", {
|
|
735
|
+
name: "policy-1",
|
|
736
|
+
displayName: "First Policy",
|
|
737
|
+
policyRule: { if: {}, then: { effect: "audit" } },
|
|
738
|
+
});
|
|
739
|
+
const policy2 = new policy_definition_1.PolicyDefinition(this, "Policy2", {
|
|
740
|
+
name: "policy-2",
|
|
741
|
+
displayName: "Second Policy",
|
|
742
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
743
|
+
apiVersion: "2021-06-01",
|
|
744
|
+
});
|
|
745
|
+
new cdktf.TerraformOutput(this, "Policy1Id", {
|
|
746
|
+
value: policy1.id,
|
|
747
|
+
});
|
|
748
|
+
new cdktf.TerraformOutput(this, "Policy2Id", {
|
|
749
|
+
value: policy2.id,
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
expect(() => {
|
|
754
|
+
new ComplexConstruct(app, "ComplexStack");
|
|
755
|
+
}).not.toThrow();
|
|
756
|
+
});
|
|
757
|
+
it("should handle multiple policy definitions in the same stack", () => {
|
|
758
|
+
const policy1 = new policy_definition_1.PolicyDefinition(stack, "PolicyDefinition1", {
|
|
759
|
+
name: "policy-1",
|
|
760
|
+
policyRule: { if: {}, then: { effect: "audit" } },
|
|
761
|
+
});
|
|
762
|
+
const policy2 = new policy_definition_1.PolicyDefinition(stack, "PolicyDefinition2", {
|
|
763
|
+
name: "policy-2",
|
|
764
|
+
policyRule: { if: {}, then: { effect: "deny" } },
|
|
765
|
+
apiVersion: "2021-06-01",
|
|
766
|
+
});
|
|
767
|
+
expect(policy1.resolvedApiVersion).toBe("2021-06-01");
|
|
768
|
+
expect(policy2.resolvedApiVersion).toBe("2021-06-01");
|
|
769
|
+
const synthesized = cdktf_1.Testing.synth(stack);
|
|
770
|
+
expect(synthesized).toBeDefined();
|
|
771
|
+
});
|
|
772
|
+
});
|
|
773
|
+
describe("Policy Definition Types", () => {
|
|
774
|
+
it("should support BuiltIn policy type", () => {
|
|
775
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "BuiltInPolicy", {
|
|
776
|
+
name: "builtin-policy",
|
|
777
|
+
policyType: "BuiltIn",
|
|
778
|
+
policyRule: { if: {}, then: { effect: "audit" } },
|
|
779
|
+
});
|
|
780
|
+
expect(policyDefinition.policyType).toBe("BuiltIn");
|
|
781
|
+
});
|
|
782
|
+
it("should support Static policy type", () => {
|
|
783
|
+
const policyDefinition = new policy_definition_1.PolicyDefinition(stack, "StaticPolicy", {
|
|
784
|
+
name: "static-policy",
|
|
785
|
+
policyType: "Static",
|
|
786
|
+
policyRule: { if: {}, then: { effect: "audit" } },
|
|
787
|
+
});
|
|
788
|
+
expect(policyDefinition.policyType).toBe("Static");
|
|
789
|
+
});
|
|
790
|
+
it("should support different policy modes", () => {
|
|
791
|
+
const indexedPolicy = new policy_definition_1.PolicyDefinition(stack, "IndexedPolicy", {
|
|
792
|
+
name: "indexed-policy",
|
|
793
|
+
mode: "Indexed",
|
|
794
|
+
policyRule: { if: {}, then: { effect: "audit" } },
|
|
795
|
+
});
|
|
796
|
+
expect(indexedPolicy.policyMode).toBe("Indexed");
|
|
797
|
+
const resourceProviderPolicy = new policy_definition_1.PolicyDefinition(stack, "ResourceProviderPolicy", {
|
|
798
|
+
name: "resource-provider-policy",
|
|
799
|
+
mode: "Microsoft.KeyVault.Data",
|
|
800
|
+
policyRule: { if: {}, then: { effect: "audit" } },
|
|
801
|
+
});
|
|
802
|
+
expect(resourceProviderPolicy.policyMode).toBe("Microsoft.KeyVault.Data");
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
});
|
|
806
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9saWN5LWRlZmluaXRpb24uc3BlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9henVyZS1wb2xpY3lkZWZpbml0aW9uL3Rlc3QvcG9saWN5LWRlZmluaXRpb24uc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7R0FPRzs7QUFFSCxpQ0FBZ0M7QUFDaEMsK0JBQStCO0FBQy9CLGtHQUE2RjtBQUM3RiwyR0FBeUc7QUFDekcsZ0VBR2tDO0FBQ2xDLGdGQUcwQztBQUUxQyxRQUFRLENBQUMsMkNBQTJDLEVBQUUsR0FBRyxFQUFFO0lBQ3pELElBQUksR0FBYyxDQUFDO0lBQ25CLElBQUksS0FBMkIsQ0FBQztJQUNoQyxJQUFJLE9BQTBCLENBQUM7SUFFL0IsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUNkLEdBQUcsR0FBRyxlQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDcEIsS0FBSyxHQUFHLElBQUksS0FBSyxDQUFDLGNBQWMsQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDbkQsT0FBTyxHQUFHLHVDQUFpQixDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRXZDLGtEQUFrRDtRQUNsRCxJQUFJLENBQUM7WUFDSCxPQUFPLENBQUMsb0JBQW9CLENBQzFCLGtEQUFzQixFQUN0QiwwREFBOEIsQ0FDL0IsQ0FBQztRQUNKLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsK0JBQStCO1FBQ2pDLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxrQ0FBa0MsRUFBRSxHQUFHLEVBQUU7UUFDaEQsRUFBRSxDQUFDLDBFQUEwRSxFQUFFLEdBQUcsRUFBRTtZQUNsRixNQUFNLEtBQUssR0FBMEI7Z0JBQ25DLElBQUksRUFBRSxhQUFhO2dCQUNuQixVQUFVLEVBQUU7b0JBQ1YsRUFBRSxFQUFFO3dCQUNGLEtBQUssRUFBRSxxQkFBcUI7d0JBQzVCLE1BQU0sRUFBRSxP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QUFJLG9DQUFnQixDQUNqRCxLQUFLLEVBQ0wsd0JBQXdCLEVBQ3hCO2dCQUNFLElBQUksRUFBRSwwQkFBMEI7Z0JBQ2hDLElBQUksRUFBRSx5QkFBeUI7Z0JBQy9CLFVBQVUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxFQUFFO2FBQ2xELENBQ0YsQ0FBQztZQUVGLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUM1RSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbXByZWhlbnNpdmUgdGVzdHMgZm9yIHRoZSB1bmlmaWVkIFBvbGljeURlZmluaXRpb24gaW1wbGVtZW50YXRpb25cbiAqXG4gKiBUaGlzIHRlc3Qgc3VpdGUgdmFsaWRhdGVzIHRoZSB1bmlmaWVkIFBvbGljeURlZmluaXRpb24gY2xhc3MgdGhhdCB1c2VzXG4gKiB0aGUgVmVyc2lvbmVkQXphcGlSZXNvdXJjZSBmcmFtZXdvcmsuIFRlc3RzIGNvdmVyIGF1dG9tYXRpYyB2ZXJzaW9uIHJlc29sdXRpb24sXG4gKiBleHBsaWNpdCB2ZXJzaW9uIHBpbm5pbmcsIHNjaGVtYSB2YWxpZGF0aW9uLCBwcm9wZXJ0eSB0cmFuc2Zvcm1hdGlvbiwgYW5kXG4gKiBwb2xpY3ktc3BlY2lmaWMgZnVuY3Rpb25hbGl0eS5cbiAqL1xuXG5pbXBvcnQgeyBUZXN0aW5nIH0gZnJvbSBcImNka3RmXCI7XG5pbXBvcnQgKiBhcyBjZGt0ZiBmcm9tIFwiY2RrdGZcIjtcbmltcG9ydCB7IEFwaVZlcnNpb25NYW5hZ2VyIH0gZnJvbSBcIi4uLy4uL2NvcmUtYXp1cmUvbGliL3ZlcnNpb24tbWFuYWdlci9hcGktdmVyc2lvbi1tYW5hZ2VyXCI7XG5pbXBvcnQgeyBWZXJzaW9uU3VwcG9ydExldmVsIH0gZnJvbSBcIi4uLy4uL2NvcmUtYXp1cmUvbGliL3ZlcnNpb24tbWFuYWdlci9pbnRlcmZhY2VzL3ZlcnNpb24taW50ZXJmYWNlc1wiO1xuaW1wb3J0IHtcbiAgUG9saWN5RGVmaW5pdGlvbixcbiAgUG9saWN5RGVmaW5pdGlvblByb3BzLFxufSBmcm9tIFwiLi4vbGliL3BvbGljeS1kZWZpbml0aW9uXCI7XG5pbXBvcnQge1xuICBBTExfUE9MSUNZX0RFRklOSVRJT05fVkVSU0lPTlMsXG4gIFBPTElDWV9ERUZJTklUSU9OX1RZUEUsXG59IGZyb20gXCIuLi9saWIvcG9saWN5LWRlZmluaXRpb24tc2NoZW1hc1wiO1xuXG5kZXNjcmliZShcIlBvbGljeURlZmluaXRpb24gLSBVbmlmaWVkIEltcGxlbWVudGF0aW9uXCIsICgpID0+IHtcbiAgbGV0IGFwcDogY2RrdGYuQXBwO1xuICBsZXQgc3RhY2s6IGNka3RmLlRlcnJhZm9ybVN0YWNrO1xuICBsZXQgbWFuYWdlcjogQXBpVmVyc2lvbk1hbmFnZXI7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgYXBwID0gVGVzdGluZy5hcHAoKTtcbiAgICBzdGFjayA9IG5ldyBjZGt0Zi5UZXJyYWZvcm1TdGFjayhhcHAsIFwiVGVzdFN0YWNrXCIpO1xuICAgIG1hbmFnZXIgPSBBcGlWZXJzaW9uTWFuYWdlci5pbnN0YW5jZSgpO1xuXG4gICAgLy8gRW5zdXJlIFBvbGljeSBEZWZpbml0aW9uIHNjaGVtYXMgYXJlIHJlZ2lzdGVyZWRcbiAgICB0cnkge1xuICAgICAgbWFuYWdlci5yZWdpc3RlclJlc291cmNlVHlwZShcbiAgICAgICAgUE9MSUNZX0RFRklOSVRJT05fVFlQRSxcbiAgICAgICAgQUxMX1BPTElDWV9ERUZJTklUSU9OX1ZFUlNJT05TLFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gSWdub3JlIGlmIGFscmVhZHkgcmVnaXN0ZXJlZFxuICAgIH1cbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJDb25zdHJ1Y3RvciBhbmQgQmFzaWMgUHJvcGVydGllc1wiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgY3JlYXRlIHBvbGljeSBkZWZpbml0aW9uIHdpdGggYXV0b21hdGljIGxhdGVzdCB2ZXJzaW9uIHJlc29sdXRpb25cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFBvbGljeURlZmluaXRpb25Qcm9wcyA9IHtcbiAgICAgICAgbmFtZTogXCJ0ZXN0LXBvbGljeVwiLFxuICAgICAgICBwb2xpY3lSdWxlOiB7XG4gICAgICAgICAgaWY6IHtcbiAgICAgICAgICAgIGZpZWxkOiBcInRhZ3NbJ0Vudmlyb25tZW50J11cIixcbiAgICAgICAgICAgIGV4aXN0czogXCJmYWxzZVwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdGhlbjoge1xuICAgICAgICAgICAgZWZmZWN0OiBcImRlbnlcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLFxuICAgICAgICBwcm9wcyxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uKS50b0JlSW5zdGFuY2VPZihQb2xpY3lEZWZpbml0aW9uKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnJlc29sdmVkQXBpVmVyc2lvbikudG9CZShcIjIwMjEtMDYtMDFcIik7IC8vIExhdGVzdCB2ZXJzaW9uXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wcm9wcykudG9CZShwcm9wcyk7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5uYW1lKS50b0JlKFwidGVzdC1wb2xpY3lcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBjcmVhdGUgcG9saWN5IGRlZmluaXRpb24gd2l0aCBleHBsaWNpdCB2ZXJzaW9uIHBpbm5pbmdcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFBvbGljeURlZmluaXRpb25Qcm9wcyA9IHtcbiAgICAgICAgbmFtZTogXCJ0ZXN0LXBvbGljeS1waW5uZWRcIixcbiAgICAgICAgYXBpVmVyc2lvbjogXCIyMDIxLTA2LTAxXCIsXG4gICAgICAgIHBvbGljeVJ1bGU6IHtcbiAgICAgICAgICBpZjoge1xuICAgICAgICAgICAgZmllbGQ6IFwidHlwZVwiLFxuICAgICAgICAgICAgZXF1YWxzOiBcIk1pY3Jvc29mdC5Db21wdXRlL3ZpcnR1YWxNYWNoaW5lc1wiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdGhlbjoge1xuICAgICAgICAgICAgZWZmZWN0OiBcImF1ZGl0XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIFwiVGVzdFBvbGljeURlZmluaXRpb25cIixcbiAgICAgICAgcHJvcHMsXG4gICAgICApO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5yZXNvbHZlZEFwaVZlcnNpb24pLnRvQmUoXCIyMDIxLTA2LTAxXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgY3JlYXRlIHBvbGljeSBkZWZpbml0aW9uIHdpdGggYWxsIG9wdGlvbmFsIHByb3BlcnRpZXNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFBvbGljeURlZmluaXRpb25Qcm9wcyA9IHtcbiAgICAgICAgbmFtZTogXCJ0ZXN0LXBvbGljeS1mdWxsXCIsXG4gICAgICAgIGRpc3BsYXlOYW1lOiBcIlRlc3QgUG9saWN5IERlZmluaXRpb25cIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiQSB0ZXN0IHBvbGljeSBkZWZpbml0aW9uIGZvciB1bml0IHRlc3RpbmdcIixcbiAgICAgICAgcG9saWN5VHlwZTogXCJDdXN0b21cIixcbiAgICAgICAgbW9kZTogXCJBbGxcIixcbiAgICAgICAgcG9saWN5UnVsZToge1xuICAgICAgICAgIGlmOiB7XG4gICAgICAgICAgICBmaWVsZDogXCJsb2NhdGlvblwiLFxuICAgICAgICAgICAgbm90SW46IFtcImVhc3R1c1wiLCBcIndlc3R1c1wiXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHRoZW46IHtcbiAgICAgICAgICAgIGVmZmVjdDogXCJkZW55XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgIGFsbG93ZWRMb2NhdGlvbnM6IHtcbiAgICAgICAgICAgIHR5cGU6IFwiQXJyYXlcIixcbiAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiBcIkFsbG93ZWQgbG9jYXRpb25zXCIsXG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBcIlRoZSBsaXN0IG9mIGFsbG93ZWQgbG9jYXRpb25zIGZvciByZXNvdXJjZXNcIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICBjYXRlZ29yeTogXCJHZW5lcmFsXCIsXG4gICAgICAgICAgdmVyc2lvbjogXCIxLjAuMFwiLFxuICAgICAgICB9LFxuICAgICAgICBpZ25vcmVDaGFuZ2VzOiBbXCJtZXRhZGF0YVwiXSxcbiAgICAgICAgZW5hYmxlVmFsaWRhdGlvbjogdHJ1ZSxcbiAgICAgICAgZW5hYmxlTWlncmF0aW9uQW5hbHlzaXM6IHRydWUsXG4gICAgICAgIGVuYWJsZVRyYW5zZm9ybWF0aW9uOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLFxuICAgICAgICBwcm9wcyxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnByb3BzLmRpc3BsYXlOYW1lKS50b0JlKFwiVGVzdCBQb2xpY3kgRGVmaW5pdGlvblwiKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnByb3BzLmRlc2NyaXB0aW9uKS50b0JlKFxuICAgICAgICBcIkEgdGVzdCBwb2xpY3kgZGVmaW5pdGlvbiBmb3IgdW5pdCB0ZXN0aW5nXCIsXG4gICAgICApO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ucHJvcHMucG9saWN5VHlwZSkudG9CZShcIkN1c3RvbVwiKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnByb3BzLm1vZGUpLnRvQmUoXCJBbGxcIik7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wcm9wcy5wYXJhbWV0ZXJzKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ucHJvcHMubWV0YWRhdGEpLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCB1c2UgZGVmYXVsdCBuYW1lIHdoZW4gbmFtZSBpcyBub3QgcHJvdmlkZWRcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFBvbGljeURlZmluaXRpb25Qcm9wcyA9IHtcbiAgICAgICAgcG9saWN5UnVsZToge1xuICAgICAgICAgIGlmOiB7XG4gICAgICAgICAgICBmaWVsZDogXCJ0eXBlXCIsXG4gICAgICAgICAgICBlcXVhbHM6IFwiTWljcm9zb2Z0LlN0b3JhZ2Uvc3RvcmFnZUFjY291bnRzXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0aGVuOiB7XG4gICAgICAgICAgICBlZmZlY3Q6IFwiYXVkaXRcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLFxuICAgICAgICBwcm9wcyxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLm5hbWUpLnRvQmUoXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIHJlcXVpcmUgcG9saWN5UnVsZSB0byBiZSBwcm92aWRlZFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wczogYW55ID0ge1xuICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLCBwcm9wcyk7XG4gICAgICB9KS50b1Rocm93KFwiUmVxdWlyZWQgcHJvcGVydHkgJ3BvbGljeVJ1bGUnIGlzIG1pc3NpbmdcIik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiRnJhbWV3b3JrIEludGVncmF0aW9uXCIsICgpID0+IHtcbiAgICBpdChcInNob3VsZCByZXNvbHZlIGxhdGVzdCBBUEkgdmVyc2lvbiBhdXRvbWF0aWNhbGx5XCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIFwiVGVzdFBvbGljeURlZmluaXRpb25cIixcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1wb2xpY3lcIixcbiAgICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiZGVueVwiIH0gfSxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnJlc29sdmVkQXBpVmVyc2lvbikudG9CZShcIjIwMjEtMDYtMDFcIik7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5sYXRlc3RWZXJzaW9uKCkpLnRvQmUoXCIyMDIxLTA2LTAxXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgc3VwcG9ydCBhbGwgcmVnaXN0ZXJlZCBBUEkgdmVyc2lvbnNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXBvbGljeVwiLFxuICAgICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJkZW55XCIgfSB9LFxuICAgICAgICB9LFxuICAgICAgKTtcblxuICAgICAgY29uc3Qgc3VwcG9ydGVkVmVyc2lvbnMgPSBwb2xpY3lEZWZpbml0aW9uLnN1cHBvcnRlZFZlcnNpb25zKCk7XG4gICAgICBleHBlY3Qoc3VwcG9ydGVkVmVyc2lvbnMpLnRvQ29udGFpbihcIjIwMjEtMDYtMDFcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCB2YWxpZGF0ZSB2ZXJzaW9uIHN1cHBvcnRcIiwgKCkgPT4ge1xuICAgICAgLy8gVmFsaWQgdmVyc2lvblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiVmFsaWRWZXJzaW9uXCIsIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICAgICAgYXBpVmVyc2lvbjogXCIyMDIxLTA2LTAxXCIsXG4gICAgICAgIH0pO1xuICAgICAgfSkubm90LnRvVGhyb3coKTtcblxuICAgICAgLy8gSW52YWxpZCB2ZXJzaW9uXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJJbnZhbGlkVmVyc2lvblwiLCB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXBvbGljeVwiLFxuICAgICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJkZW55XCIgfSB9LFxuICAgICAgICAgIGFwaVZlcnNpb246IFwiMjAyMi0wMS0wMVwiLFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coXCJVbnN1cHBvcnRlZCBBUEkgdmVyc2lvbiAnMjAyMi0wMS0wMSdcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBsb2FkIGNvcnJlY3Qgc2NoZW1hIGZvciByZXNvbHZlZCB2ZXJzaW9uXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIFwiVGVzdFBvbGljeURlZmluaXRpb25cIixcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1wb2xpY3lcIixcbiAgICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiZGVueVwiIH0gfSxcbiAgICAgICAgICBhcGlWZXJzaW9uOiBcIjIwMjEtMDYtMDFcIixcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnNjaGVtYSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnNjaGVtYS5yZXNvdXJjZVR5cGUpLnRvQmUoUE9MSUNZX0RFRklOSVRJT05fVFlQRSk7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5zY2hlbWEudmVyc2lvbikudG9CZShcIjIwMjEtMDYtMDFcIik7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5zY2hlbWEucHJvcGVydGllcykudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIGxvYWQgdmVyc2lvbiBjb25maWd1cmF0aW9uIGNvcnJlY3RseVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oXG4gICAgICAgIHN0YWNrLFxuICAgICAgICBcIlRlc3RQb2xpY3lEZWZpbml0aW9uXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi52ZXJzaW9uQ29uZmlnKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24udmVyc2lvbkNvbmZpZy52ZXJzaW9uKS50b0JlKFwiMjAyMS0wNi0wMVwiKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnZlcnNpb25Db25maWcuc3VwcG9ydExldmVsKS50b0JlKFxuICAgICAgICBWZXJzaW9uU3VwcG9ydExldmVsLkFDVElWRSxcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiUHJvcGVydHkgVmFsaWRhdGlvblwiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgdmFsaWRhdGUgcHJvcGVydGllcyB3aGVuIHZhbGlkYXRpb24gaXMgZW5hYmxlZFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wczogUG9saWN5RGVmaW5pdGlvblByb3BzID0ge1xuICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgIHBvbGljeVJ1bGU6IHtcbiAgICAgICAgICBpZjoge1xuICAgICAgICAgICAgZmllbGQ6IFwidHlwZVwiLFxuICAgICAgICAgICAgZXF1YWxzOiBcIk1pY3Jvc29mdC5Db21wdXRlL3ZpcnR1YWxNYWNoaW5lc1wiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdGhlbjoge1xuICAgICAgICAgICAgZWZmZWN0OiBcImF1ZGl0XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgZW5hYmxlVmFsaWRhdGlvbjogdHJ1ZSxcbiAgICAgIH07XG5cbiAgICAgIGV4cGVjdCgoKSA9PiB7XG4gICAgICAgIG5ldyBQb2xpY3lEZWZpbml0aW9uKHN0YWNrLCBcIlRlc3RQb2xpY3lEZWZpbml0aW9uXCIsIHByb3BzKTtcbiAgICAgIH0pLm5vdC50b1Rocm93KCk7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBoYXZlIHZhbGlkYXRpb24gcmVzdWx0cyBmb3IgdmFsaWQgcHJvcGVydGllc1wiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oXG4gICAgICAgIHN0YWNrLFxuICAgICAgICBcIlRlc3RQb2xpY3lEZWZpbml0aW9uXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInZhbGlkLXBvbGljeVwiLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiBcIlZhbGlkIFBvbGljeVwiLFxuICAgICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJkZW55XCIgfSB9LFxuICAgICAgICAgIGVuYWJsZVZhbGlkYXRpb246IHRydWUsXG4gICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi52YWxpZGF0aW9uUmVzdWx0KS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24udmFsaWRhdGlvblJlc3VsdCEudmFsaWQpLnRvQmUodHJ1ZSk7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi52YWxpZGF0aW9uUmVzdWx0IS5lcnJvcnMpLnRvSGF2ZUxlbmd0aCgwKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIHNraXAgdmFsaWRhdGlvbiB3aGVuIGRpc2FibGVkXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIFwiVGVzdFBvbGljeURlZmluaXRpb25cIixcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1wb2xpY3lcIixcbiAgICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiZGVueVwiIH0gfSxcbiAgICAgICAgICBlbmFibGVWYWxpZGF0aW9uOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uKS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcIk1pZ3JhdGlvbiBBbmFseXNpc1wiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgc2tpcCBtaWdyYXRpb24gYW5hbHlzaXMgZm9yIHNpbmdsZSB2ZXJzaW9uXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIFwiVGVzdFBvbGljeURlZmluaXRpb25cIixcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1wb2xpY3lcIixcbiAgICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiZGVueVwiIH0gfSxcbiAgICAgICAgICBhcGlWZXJzaW9uOiBcIjIwMjEtMDYtMDFcIixcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIC8vIFNpbmNlIHRoZXJlJ3Mgb25seSBvbmUgdmVyc2lvbiwgbWlncmF0aW9uIGFuYWx5c2lzIHNob3VsZCBiZSBza2lwcGVkXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbikudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIHNraXAgbWlncmF0aW9uIGFuYWx5c2lzIHdoZW4gZGlzYWJsZWRcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXBvbGljeVwiLFxuICAgICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJkZW55XCIgfSB9LFxuICAgICAgICAgIGVuYWJsZU1pZ3JhdGlvbkFuYWx5c2lzOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLm1pZ3JhdGlvbkFuYWx5c2lzKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiUmVzb3VyY2UgQ3JlYXRpb24gYW5kIEJvZHlcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIGNyZWF0ZSBjb3JyZWN0IHJlc291cmNlIGJvZHkgd2l0aCBtaW5pbWFsIHByb3BlcnRpZXNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXBvbGljeVwiLFxuICAgICAgICAgIHBvbGljeVJ1bGU6IHtcbiAgICAgICAgICAgIGlmOiB7XG4gICAgICAgICAgICAgIGZpZWxkOiBcInRhZ3NbJ0Vudmlyb25tZW50J11cIixcbiAgICAgICAgICAgICAgZXhpc3RzOiBcImZhbHNlXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhlbjoge1xuICAgICAgICAgICAgICBlZmZlY3Q6IFwiZGVueVwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wcm9wcy5wb2xpY3lSdWxlKS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgY3JlYXRlIGNvcnJlY3QgcmVzb3VyY2UgYm9keSB3aXRoIGFsbCBwcm9wZXJ0aWVzXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIFwiVGVzdFBvbGljeURlZmluaXRpb25cIixcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1wb2xpY3lcIixcbiAgICAgICAgICBkaXNwbGF5TmFtZTogXCJUZXN0IFBvbGljeVwiLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiBcIkEgdGVzdCBwb2xpY3lcIixcbiAgICAgICAgICBwb2xpY3lUeXBlOiBcIkN1c3RvbVwiLFxuICAgICAgICAgIG1vZGU6IFwiSW5kZXhlZFwiLFxuICAgICAgICAgIHBvbGljeVJ1bGU6IHtcbiAgICAgICAgICAgIGlmOiB7XG4gICAgICAgICAgICAgIGZpZWxkOiBcImxvY2F0aW9uXCIsXG4gICAgICAgICAgICAgIG5vdEluOiBbXCJlYXN0dXNcIiwgXCJ3ZXN0dXNcIl0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhlbjoge1xuICAgICAgICAgICAgICBlZmZlY3Q6IFwiZGVueVwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgIGFsbG93ZWRMb2NhdGlvbnM6IHtcbiAgICAgICAgICAgICAgdHlwZTogXCJBcnJheVwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICBjYXRlZ29yeTogXCJDb21wbGlhbmNlXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ucHJvcHMuZGlzcGxheU5hbWUpLnRvQmUoXCJUZXN0IFBvbGljeVwiKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnByb3BzLnBvbGljeVR5cGUpLnRvQmUoXCJDdXN0b21cIik7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wcm9wcy5tb2RlKS50b0JlKFwiSW5kZXhlZFwiKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIGNyZWF0ZSBUZXJyYWZvcm0gb3V0cHV0c1wiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oXG4gICAgICAgIHN0YWNrLFxuICAgICAgICBcIlRlc3RQb2xpY3lEZWZpbml0aW9uXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5LW91dHB1dHNcIixcbiAgICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiZGVueVwiIH0gfSxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLmlkT3V0cHV0KS50b0JlSW5zdGFuY2VPZihjZGt0Zi5UZXJyYWZvcm1PdXRwdXQpO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ubmFtZU91dHB1dCkudG9CZUluc3RhbmNlT2YoY2RrdGYuVGVycmFmb3JtT3V0cHV0KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJQdWJsaWMgTWV0aG9kcyBhbmQgUHJvcGVydGllc1wiLCAoKSA9PiB7XG4gICAgbGV0IHBvbGljeURlZmluaXRpb246IFBvbGljeURlZmluaXRpb247XG5cbiAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgIHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJUZXN0UG9saWN5RGVmaW5pdGlvblwiLCB7XG4gICAgICAgIG5hbWU6IFwidGVzdC1wb2xpY3lcIixcbiAgICAgICAgZGlzcGxheU5hbWU6IFwiVGVzdCBQb2xpY3lcIixcbiAgICAgICAgcG9saWN5VHlwZTogXCJDdXN0b21cIixcbiAgICAgICAgbW9kZTogXCJBbGxcIixcbiAgICAgICAgcG9saWN5UnVsZToge1xuICAgICAgICAgIGlmOiB7XG4gICAgICAgICAgICBmaWVsZDogXCJ0eXBlXCIsXG4gICAgICAgICAgICBlcXVhbHM6IFwiTWljcm9zb2Z0LkNvbXB1dGUvdmlydHVhbE1hY2hpbmVzXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0aGVuOiB7XG4gICAgICAgICAgICBlZmZlY3Q6IFwiYXVkaXRcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBoYXZlIGNvcnJlY3QgaWQgZm9ybWF0XCIsICgpID0+IHtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLmlkKS50b01hdGNoKC9eXFwkXFx7LipcXC5pZFxcfSQvKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIGhhdmUgcmVzb3VyY2VJZCBwcm9wZXJ0eSBtYXRjaGluZyBpZFwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5yZXNvdXJjZUlkKS50b0JlKHBvbGljeURlZmluaXRpb24uaWQpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgcmV0dXJuIGNvcnJlY3QgcG9saWN5VHlwZVwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wb2xpY3lUeXBlKS50b0JlKFwiQ3VzdG9tXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgcmV0dXJuIGNvcnJlY3QgcG9saWN5TW9kZVwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wb2xpY3lNb2RlKS50b0JlKFwiQWxsXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgdXNlIGRlZmF1bHQgcG9saWN5VHlwZSB3aGVuIG5vdCBwcm92aWRlZFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBkZWZhdWx0UG9saWN5ID0gbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiRGVmYXVsdFR5cGVQb2xpY3lcIiwge1xuICAgICAgICBuYW1lOiBcImRlZmF1bHQtcG9saWN5XCIsXG4gICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJkZW55XCIgfSB9LFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChkZWZhdWx0UG9saWN5LnBvbGljeVR5cGUpLnRvQmUoXCJDdXN0b21cIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCB1c2UgZGVmYXVsdCBtb2RlIHdoZW4gbm90IHByb3ZpZGVkXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGRlZmF1bHRQb2xpY3kgPSBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJEZWZhdWx0TW9kZVBvbGljeVwiLCB7XG4gICAgICAgIG5hbWU6IFwiZGVmYXVsdC1wb2xpY3lcIixcbiAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KGRlZmF1bHRQb2xpY3kucG9saWN5TW9kZSkudG9CZShcIkFsbFwiKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJJZ25vcmUgQ2hhbmdlcyBDb25maWd1cmF0aW9uXCIsICgpID0+IHtcbiAgICBpdChcInNob3VsZCBhcHBseSBpZ25vcmUgY2hhbmdlcyBsaWZlY3ljbGUgcnVsZXNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJJZ25vcmVDaGFuZ2VzUG9saWN5XCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICAgICAgaWdub3JlQ2hhbmdlczogW1wibWV0YWRhdGFcIiwgXCJkZXNjcmlwdGlvblwiXSxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uKS50b0JlSW5zdGFuY2VPZihQb2xpY3lEZWZpbml0aW9uKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIGhhbmRsZSBlbXB0eSBpZ25vcmUgY2hhbmdlcyBhcnJheVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oXG4gICAgICAgIHN0YWNrLFxuICAgICAgICBcIkVtcHR5SWdub3JlUG9saWN5XCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICAgICAgaWdub3JlQ2hhbmdlczogW10sXG4gICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbikudG9CZUluc3RhbmNlT2YoUG9saWN5RGVmaW5pdGlvbik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiUG9saWN5IFJ1bGUgVmFsaWRhdGlvblwiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgYWNjZXB0IGNvbXBsZXggcG9saWN5IHJ1bGVzXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGNvbXBsZXhSdWxlID0ge1xuICAgICAgICBpZjoge1xuICAgICAgICAgIGFsbE9mOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpZWxkOiBcInR5cGVcIixcbiAgICAgICAgICAgICAgZXF1YWxzOiBcIk1pY3Jvc29mdC5TdG9yYWdlL3N0b3JhZ2VBY2NvdW50c1wiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZmllbGQ6IFwiTWljcm9zb2Z0LlN0b3JhZ2Uvc3RvcmFnZUFjY291bnRzL2VuYWJsZUh0dHBzVHJhZmZpY09ubHlcIixcbiAgICAgICAgICAgICAgbm90RXF1YWxzOiBcInRydWVcIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgdGhlbjoge1xuICAgICAgICAgIGVmZmVjdDogXCJkZW55XCIsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oXG4gICAgICAgIHN0YWNrLFxuICAgICAgICBcIkNvbXBsZXhSdWxlUG9saWN5XCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcImNvbXBsZXgtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogY29tcGxleFJ1bGUsXG4gICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbikudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnByb3BzLnBvbGljeVJ1bGUpLnRvRXF1YWwoY29tcGxleFJ1bGUpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgYWNjZXB0IHBvbGljeSBydWxlcyB3aXRoIHBhcmFtZXRlcnNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJQYXJhbWV0ZXJpemVkUG9saWN5XCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInBhcmFtZXRlcml6ZWQtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZToge1xuICAgICAgICAgICAgaWY6IHtcbiAgICAgICAgICAgICAgZmllbGQ6IFwiW2NvbmNhdCgndGFnc1snLCBwYXJhbWV0ZXJzKCd0YWdOYW1lJyksICddJyldXCIsXG4gICAgICAgICAgICAgIGV4aXN0czogXCJmYWxzZVwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoZW46IHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBcIltwYXJhbWV0ZXJzKCdlZmZlY3QnKV1cIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgICB0YWdOYW1lOiB7XG4gICAgICAgICAgICAgIHR5cGU6IFwiU3RyaW5nXCIsXG4gICAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6IFwiVGFnIE5hbWVcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogXCJOYW1lIG9mIHRoZSB0YWcgdG8gY2hlY2tcIixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZmZlY3Q6IHtcbiAgICAgICAgICAgICAgdHlwZTogXCJTdHJpbmdcIixcbiAgICAgICAgICAgICAgYWxsb3dlZFZhbHVlczogW1wiYXVkaXRcIiwgXCJkZW55XCJdLFxuICAgICAgICAgICAgICBkZWZhdWx0VmFsdWU6IFwiYXVkaXRcIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ucHJvcHMucGFyYW1ldGVycykudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIHByZXNlcnZlIGNvbXBsZXggYWxsT2YgY29uZGl0aW9ucyB3aXRoIG11bHRpcGxlIGZpZWxkIGNvbXBhcmlzb25zXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGNvbXBsZXhSdWxlID0ge1xuICAgICAgICBpZjoge1xuICAgICAgICAgIGFsbE9mOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpZWxkOiBcInR5cGVcIixcbiAgICAgICAgICAgICAgZXF1YWxzOiBcIk1pY3Jvc29mdC5TdG9yYWdlL3N0b3JhZ2VBY2NvdW50c1wiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZmllbGQ6XG4gICAgICAgICAgICAgICAgXCJNaWNyb3NvZnQuU3RvcmFnZS9zdG9yYWdlQWNjb3VudHMvbmV0d29ya0FjbHMuZGVmYXVsdEFjdGlvblwiLFxuICAgICAgICAgICAgICBub3RFcXVhbHM6IFwiRGVueVwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICB0aGVuOiB7XG4gICAgICAgICAgZWZmZWN0OiBcImF1ZGl0XCIsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiQ29tcGxleEFsbE9mXCIsIHtcbiAgICAgICAgbmFtZTogXCJjb21wbGV4LWFsbG9mLXBvbGljeVwiLFxuICAgICAgICBkaXNwbGF5TmFtZTogXCJDb21wbGV4IEFsbE9mIFBvbGljeVwiLFxuICAgICAgICBwb2xpY3lSdWxlOiBjb21wbGV4UnVsZSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbikudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnByb3BzLnBvbGljeVJ1bGUpLnRvRXF1YWwoY29tcGxleFJ1bGUpO1xuXG4gICAgICAvLyBTeW50aGVzaXplIGFuZCB2ZXJpZnkgdGhlIHN0cnVjdHVyZSBpcyBwcmVzZXJ2ZWRcbiAgICAgIGNvbnN0IHN5bnRoZXNpemVkID0gVGVzdGluZy5zeW50aChzdGFjayk7XG4gICAgICBjb25zdCBzdGFja0NvbmZpZyA9IEpTT04ucGFyc2Uoc3ludGhlc2l6ZWQpO1xuICAgICAgY29uc3QgYXphcGlSZXNvdXJjZSA9IE9iamVjdC52YWx1ZXMoXG4gICAgICAgIHN0YWNrQ29uZmlnLnJlc291cmNlLmF6YXBpX3Jlc291cmNlLFxuICAgICAgKVswXSBhcyBhbnk7XG5cbiAgICAgIC8vIFRoZSBib2R5IGlzIGpzb25lbmNvZGUoKSB3cmFwcGVkLCBzbyB3ZSBuZWVkIHRvIHBhcnNlIHRoZSBhY3R1YWwgcG9saWN5IHJ1bGUgZnJvbSBwcm9wc1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ucHJvcHMucG9saWN5UnVsZS5pZi5hbGxPZikudG9IYXZlTGVuZ3RoKDIpO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ucHJvcHMucG9saWN5UnVsZS5pZi5hbGxPZlswXS5maWVsZCkudG9CZShcInR5cGVcIik7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wcm9wcy5wb2xpY3lSdWxlLmlmLmFsbE9mWzBdLmVxdWFscykudG9CZShcbiAgICAgICAgXCJNaWNyb3NvZnQuU3RvcmFnZS9zdG9yYWdlQWNjb3VudHNcIixcbiAgICAgICk7XG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wcm9wcy5wb2xpY3lSdWxlLmlmLmFsbE9mWzFdLmZpZWxkKS50b0JlKFxuICAgICAgICBcIk1pY3Jvc29mdC5TdG9yYWdlL3N0b3JhZ2VBY2NvdW50cy9uZXR3b3JrQWNscy5kZWZhdWx0QWN0aW9uXCIsXG4gICAgICApO1xuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24ucHJvcHMucG9saWN5UnVsZS5pZi5hbGxPZlsxXS5ub3RFcXVhbHMpLnRvQmUoXG4gICAgICAgIFwiRGVueVwiLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnByb3BzLnBvbGljeVJ1bGUudGhlbi5lZmZlY3QpLnRvQmUoXCJhdWRpdFwiKTtcblxuICAgICAgLy8gVmVyaWZ5IHRoZSBzeW50aGVzaXplZCBjb25maWcgaGFzIHRoZSBib2R5IHByb3BlcnR5IHNldFxuICAgICAgZXhwZWN0KGF6YXBpUmVzb3VyY2UuYm9keSkudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIHByZXNlcnZlIEF6dXJlIFBvbGljeSBleHByZXNzaW9ucyB3aXRob3V0IGNvbnZlcnRpbmcgdGhlbVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBydWxlID0ge1xuICAgICAgICBpZjoge1xuICAgICAgICAgIGZpZWxkOiBcImxvY2F0aW9uXCIsXG4gICAgICAgICAgbm90SW46IFwiW3BhcmFtZXRlcnMoJ2FsbG93ZWRMb2NhdGlvbnMnKV1cIixcbiAgICAgICAgfSxcbiAgICAgICAgdGhlbjoge1xuICAgICAgICAgIGVmZmVjdDogXCJbcGFyYW1ldGVycygnZWZmZWN0JyldXCIsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJBenVyZVBvbGljeUV4cHJlc3Npb25zXCIsIHtcbiAgICAgICAgbmFtZTogXCJhenVyZS1leHByZXNzaW9ucy1wb2xpY3lcIixcbiAgICAgICAgcG9saWN5UnVsZTogcnVsZSxcbiAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgIGFsbG93ZWRMb2NhdGlvbnM6IHsgdHlwZTogXCJBcnJheVwiIH0sXG4gICAgICAgICAgZWZmZWN0OiB7IHR5cGU6IFwiU3RyaW5nXCIgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzeW50aGVzaXplZCA9IFRlc3Rpbmcuc3ludGgoc3RhY2spO1xuICAgICAgY29uc3Qgc3RhY2tDb25maWcgPSBKU09OLnBhcnNlKHN5bnRoZXNpemVkKTtcbiAgICAgIGNvbnN0IGF6YXBpUmVzb3VyY2UgPSBPYmplY3QudmFsdWVzKFxuICAgICAgICBzdGFja0NvbmZpZy5yZXNvdXJjZS5hemFwaV9yZXNvdXJjZSxcbiAgICAgIClbMF0gYXMgYW55O1xuXG4gICAgICAvLyBWZXJpZnkgQXp1cmUgUG9saWN5IGV4cHJlc3Npb25zIGFyZSBwcmVzZXJ2ZWQgaW4gdGhlIGNvbnN0cnVjdCdzIHByb3BzXG4gICAgICBleHBlY3QocnVsZS5pZi5ub3RJbikudG9CZShcIltwYXJhbWV0ZXJzKCdhbGxvd2VkTG9jYXRpb25zJyldXCIpO1xuICAgICAgZXhwZWN0KHJ1bGUudGhlbi5lZmZlY3QpLnRvQmUoXCJbcGFyYW1ldGVycygnZWZmZWN0JyldXCIpO1xuXG4gICAgICAvLyBWZXJpZnkgdGhlIHN5bnRoZXNpemVkIGNvbmZpZyBoYXMgdGhlIGJvZHkgcHJvcGVydHkgc2V0XG4gICAgICBleHBlY3QoYXphcGlSZXNvdXJjZS5ib2R5KS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgcHJlc2VydmUgRGVwbG95SWZOb3RFeGlzdHMgcG9saWN5IHdpdGggQVJNIHRlbXBsYXRlXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGNvbXBsZXhSdWxlID0ge1xuICAgICAgICBpZjoge1xuICAgICAgICAgIGZpZWxkOiBcInR5cGVcIixcbiAgICAgICAgICBlcXVhbHM6IFwiTWljcm9zb2Z0Lk5ldHdvcmsvdmlydHVhbE5ldHdvcmtzXCIsXG4gICAgICAgIH0sXG4gICAgICAgIHRoZW46IHtcbiAgICAgICAgICBlZmZlY3Q6IFwiRGVwbG95SWZOb3RFeGlzdHNcIixcbiAgICAgICAgICBkZXRhaWxzOiB7XG4gICAgICAgICAgICB0eXBlOiBcIk1pY3Jvc29mdC5OZXR3b3JrL25ldHdvcmtNYW5hZ2Vycy9uZXR3b3JrR3JvdXBzL3N0YXRpY01lbWJlcnNcIixcbiAgICAgICAgICAgIGRlcGxveW1lbnRTY29wZTogXCJzdWJzY3JpcHRpb25cIixcbiAgICAgICAgICAgIGV4aXN0ZW5jZVNjb3BlOiBcInN1YnNjcmlwdGlvblwiLFxuICAgICAgICAgICAgcm9sZURlZmluaXRpb25JZHM6IFtcbiAgICAgICAgICAgICAgXCIvcHJvdmlkZXJzL01pY3Jvc29mdC5BdXRob3JpemF0aW9uL3JvbGVEZWZpbml0aW9ucy9iMjQ5ODhhYy02MTgwLTQyYTAtYWI4OC0yMGY3MzgyZGQyNGNcIixcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBkZXBsb3ltZW50OiB7XG4gICAgICAgICAgICAgIGxvY2F0aW9uOiBcIltmaWVsZCgnbG9jYXRpb24nKV1cIixcbiAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIG1vZGU6IFwiaW5jcmVtZW50YWxcIixcbiAgICAgICAgICAgICAgICByZXNvdXJjZUdyb3VwOiBcIlt2YXJpYWJsZXMoJ2F2bm1SZXNvdXJjZUdyb3VwJyldXCIsXG4gICAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uSWQ6IFwiW3BhcmFtZXRlcnMoJ2F2bm1TdWJzY3JpcHRpb25JZCcpXVwiLFxuICAgICAgICAgICAgICAgIHRlbXBsYXRlOiB7XG4gICAgICAgICAgICAgICAgICAkc2NoZW1hOlxuICAgICAgICAgICAgICAgICAgICBcImh0dHBzOi8vc2NoZW1hLm1hbmFnZW1lbnQuYXp1cmUuY29tL3NjaGVtYXMvMjAxOS0wNC0wMS9kZXBsb3ltZW50VGVtcGxhdGUuanNvbiNcIixcbiAgICAgICAgICAgICAgICAgIGNvbnRlbnRWZXJzaW9uOiBcIjEuMC4wLjBcIixcbiAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgdm5ldElkOiB7XG4gICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdGljTWVtYmVyTmFtZTogXCJbZ3VpZChwYXJhbWV0ZXJzKCd2bmV0SWQnKSldXCIsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcIk1pY3Jvc29mdC5OZXR3b3JrL25ldHdvcmtNYW5hZ2Vycy9uZXR3b3JrR3JvdXBzL3N0YXRpY01lbWJlcnNcIixcbiAgICAgICAgICAgICAgICAgICAgICBhcGlWZXJzaW9uOiBcIjIwMjMtMDQtMDFcIixcbiAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBcIltjb25jYXQocGFyYW1ldGVycygnYXZubUlkJyksICcvJywgdmFyaWFibGVzKCdzdGF0aWNNZW1iZXJOYW1lJykpXVwiLFxuICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc291cmNlSWQ6IFwiW3BhcmFtZXRlcnMoJ3ZuZXRJZCcpXVwiLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgICAgb3V0cHV0czoge1xuICAgICAgICAgICAgICAgICAgICBtZW1iZXJJZDoge1xuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgICAgICAgICAgdmFsdWU6XG4gICAgICAgICAgICAgICAgICAgICAgICBcIltyZXNvdXJjZUlkKCdNaWNyb3NvZnQuTmV0d29yay9uZXR3b3JrTWFuYWdlcnMvbmV0d29ya0dyb3Vwcy9zdGF0aWNNZW1iZXJzJywgdmFyaWFibGVzKCdzdGF0aWNNZW1iZXJOYW1lJykpXVwiLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgICAgIHZuZXRJZDoge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogXCJbZmllbGQoJ2lkJyldXCIsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oXG4gICAgICAgIHN0YWNrLFxuICAgICAgICBcIkRlcGxveUlmTm90RXhpc3RzUG9saWN5XCIsXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcImRlcGxveS1pZi1ub3QtZXhpc3RzLXBvbGljeVwiLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiBcIkRlcGxveSBJZiBOb3QgRXhpc3RzIHdpdGggQVJNIFRlbXBsYXRlXCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogY29tcGxleFJ1bGUsXG4gICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgYXZubVN1YnNjcmlwdGlvbklkOiB7IHR5cGU6IFwiU3RyaW5nXCIgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KHBvbGljeURlZmluaXRpb24pLnRvQmVEZWZpbmVkKCk7XG5cbiAgICAgIGNvbnN0IHN5bnRoZXNpemVkID0gVGVzdGluZy5zeW50aChzdGFjayk7XG4gICAgICBjb25zdCBzdGFja0NvbmZpZyA9IEpTT04ucGFyc2Uoc3ludGhlc2l6ZWQpO1xuICAgICAgY29uc3QgYXphcGlSZXNvdXJjZSA9IE9iamVjdC52YWx1ZXMoXG4gICAgICAgIHN0YWNrQ29uZmlnLnJlc291cmNlLmF6YXBpX3Jlc291cmNlLFxuICAgICAgKVswXSBhcyBhbnk7XG5cbiAgICAgIGNvbnN0IGRldGFpbHMgPSBwb2xpY3lEZWZpbml0aW9uLnByb3BzLnBvbGljeVJ1bGUudGhlbi5kZXRhaWxzO1xuXG4gICAgICAvLyBWZXJpZnkgZGVwbG95bWVudCBzdHJ1Y3R1cmUgaXMgcHJlc2VydmVkIChub3QgY29udmVydGVkIHRvIG51bGwpXG4gICAgICBleHBlY3QoZGV0YWlscy5kZXBsb3ltZW50KS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KGRldGFpbHMuZGVwbG95bWVudC5sb2NhdGlvbikudG9CZShcIltmaWVsZCgnbG9jYXRpb24nKV1cIik7XG4gICAgICBleHBlY3QoZGV0YWlscy5kZXBsb3ltZW50LnByb3BlcnRpZXMpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoZGV0YWlscy5kZXBsb3ltZW50LnByb3BlcnRpZXMubW9kZSkudG9CZShcImluY3JlbWVudGFsXCIpO1xuICAgICAgZXhwZWN0KGRldGFpbHMuZGVwbG95bWVudC5wcm9wZXJ0aWVzLnJlc291cmNlR3JvdXApLnRvQmUoXG4gICAgICAgIFwiW3ZhcmlhYmxlcygnYXZubVJlc291cmNlR3JvdXAnKV1cIixcbiAgICAgICk7XG4gICAgICBleHBlY3QoZGV0YWlscy5kZXBsb3ltZW50LnByb3BlcnRpZXMuc3Vic2NyaXB0aW9uSWQpLnRvQmUoXG4gICAgICAgIFwiW3BhcmFtZXRlcnMoJ2F2bm1TdWJzY3JpcHRpb25JZCcpXVwiLFxuICAgICAgKTtcblxuICAgICAgLy8gVmVyaWZ5IEFSTSB0ZW1wbGF0ZSBpcyBmdWxseSBwcmVzZXJ2ZWQgKG5vdCBjb252ZXJ0ZWQgdG8gbnVsbClcbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gZGV0YWlscy5kZXBsb3ltZW50LnByb3BlcnRpZXMudGVtcGxhdGU7XG4gICAgICBleHBlY3QodGVtcGxhdGUpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QodGVtcGxhdGUuJHNjaGVtYSkudG9CZShcbiAgICAgICAgXCJodHRwczovL3NjaGVtYS5tYW5hZ2VtZW50LmF6dXJlLmNvbS9zY2hlbWFzLzIwMTktMDQtMDEvZGVwbG95bWVudFRlbXBsYXRlLmpzb24jXCIsXG4gICAgICApO1xuICAgICAgZXhwZWN0KHRlbXBsYXRlLmNvbnRlbnRWZXJzaW9uKS50b0JlKFwiMS4wLjAuMFwiKTtcbiAgICAgIGV4cGVjdCh0ZW1wbGF0ZS5wYXJhbWV0ZXJzKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHRlbXBsYXRlLnBhcmFtZXRlcnMudm5ldElkKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHRlbXBsYXRlLnZhcmlhYmxlcykudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdCh0ZW1wbGF0ZS52YXJpYWJsZXMuc3RhdGljTWVtYmVyTmFtZSkudG9CZShcbiAgICAgICAgXCJbZ3VpZChwYXJhbWV0ZXJzKCd2bmV0SWQnKSldXCIsXG4gICAgICApO1xuICAgICAgZXhwZWN0KHRlbXBsYXRlLnJlc291cmNlcykudG9IYXZlTGVuZ3RoKDEpO1xuICAgICAgZXhwZWN0KHRlbXBsYXRlLnJlc291cmNlc1swXS5uYW1lKS50b0JlKFxuICAgICAgICBcIltjb25jYXQocGFyYW1ldGVycygnYXZubUlkJyksICcvJywgdmFyaWFibGVzKCdzdGF0aWNNZW1iZXJOYW1lJykpXVwiLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdCh0ZW1wbGF0ZS5vdXRwdXRzKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHRlbXBsYXRlLm91dHB1dHMubWVtYmVySWQudmFsdWUpLnRvQmUoXG4gICAgICAgIFwiW3Jlc291cmNlSWQoJ01pY3Jvc29mdC5OZXR3b3JrL25ldHdvcmtNYW5hZ2Vycy9uZXR3b3JrR3JvdXBzL3N0YXRpY01lbWJlcnMnLCB2YXJpYWJsZXMoJ3N0YXRpY01lbWJlck5hbWUnKSldXCIsXG4gICAgICApO1xuXG4gICAgICAvLyBWZXJpZnkgQVJNIHRlbXBsYXRlIHBhcmFtZXRlcnMgYXJlIHByZXNlcnZlZFxuICAgICAgY29uc3QgZGVwbG95bWVudFBhcmFtcyA9IGRldGFpbHMuZGVwbG95bWVudC5wcm9wZXJ0aWVzLnBhcmFtZXRlcnM7XG4gICAgICBleHBlY3QoZGVwbG95bWVudFBhcmFtcykudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChkZXBsb3ltZW50UGFyYW1zLnZuZXRJZC52YWx1ZSkudG9CZShcIltmaWVsZCgnaWQnKV1cIik7XG5cbiAgICAgIC8vIFZlcmlmeSBzY2hlbWEgdmFsaWRhdGlvbiBpcyBkaXNhYmxlZCB0byBhbGxvdyBjb21wbGV4IG5lc3RlZCBzdHJ1Y3R1cmVzXG4gICAgICBleHBlY3QoYXphcGlSZXNvdXJjZS5zY2hlbWFfdmFsaWRhdGlvbl9lbmFibGVkKS50b0JlKGZhbHNlKTtcbiAgICAgIGV4cGVjdChhemFwaVJlc291cmNlLmlnbm9yZV9taXNzaW5nX3Byb3BlcnR5KS50b0JlKHRydWUpO1xuXG4gICAgICAvLyBWZXJpZnkgdGhlIHN5bnRoZXNpemVkIGNvbmZpZyBoYXMgdGhlIGJvZHkgcHJvcGVydHkgc2V0XG4gICAgICBleHBlY3QoYXphcGlSZXNvdXJjZS5ib2R5KS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgcHJlc2VydmUgZGVlcGx5IG5lc3RlZCBsb2dpY2FsIG9wZXJhdG9yc1wiLCAoKSA9PiB7XG4gICAgICBjb25zdCBjb21wbGV4UnVsZSA9IHtcbiAgICAgICAgaWY6IHtcbiAgICAgICAgICBhbGxPZjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmaWVsZDogXCJ0eXBlXCIsXG4gICAgICAgICAgICAgIGVxdWFsczogXCJNaWNyb3NvZnQuTmV0d29yay92aXJ0dWFsTmV0d29ya3NcIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFueU9mOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZmllbGQ6XG4gICAgICAgICAgICAgICAgICAgIFwiTWljcm9zb2Z0Lk5ldHdvcmsvdmlydHVhbE5ldHdvcmtzL2VuYWJsZURkb3NQcm90ZWN0aW9uXCIsXG4gICAgICAgICAgICAgICAgICBlcXVhbHM6IFwiZmFsc2VcIixcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIG5vdDoge1xuICAgICAgICAgICAgICAgICAgICBmaWVsZDpcbiAgICAgICAgICAgICAgICAgICAgICBcIk1pY3Jvc29mdC5OZXR3b3JrL3ZpcnR1YWxOZXR3b3Jrcy9zdWJuZXRzWypdLnNlcnZpY2VFbmRwb2ludHNbKl0uc2VydmljZVwiLFxuICAgICAgICAgICAgICAgICAgICBjb250YWluczogXCJNaWNyb3NvZnQuU3RvcmFnZVwiLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICB0aGVuOiB7XG4gICAgICAgICAgZWZmZWN0OiBcImF1ZGl0XCIsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiRGVlcGx5TmVzdGVkXCIsIHtcbiAgICAgICAgbmFtZTogXCJkZWVwbHktbmVzdGVkLXBvbGljeVwiLFxuICAgICAgICBwb2xpY3lSdWxlOiBjb21wbGV4UnVsZSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wcm9wcy5wb2xpY3lSdWxlKS50b0VxdWFsKGNvbXBsZXhSdWxlKTtcblxuICAgICAgY29uc3Qgc3ludGhlc2l6ZWQgPSBUZXN0aW5nLnN5bnRoKHN0YWNrKTtcbiAgICAgIGNvbnN0IHN0YWNrQ29uZmlnID0gSlNPTi5wYXJzZShzeW50aGVzaXplZCk7XG4gICAgICBjb25zdCBhemFwaVJlc291cmNlID0gT2JqZWN0LnZhbHVlcyhcbiAgICAgICAgc3RhY2tDb25maWcucmVzb3VyY2UuYXphcGlfcmVzb3VyY2UsXG4gICAgICApWzBdIGFzIGFueTtcblxuICAgICAgLy8gVmVyaWZ5IHRoZSBkZWVwbHkgbmVzdGVkIHN0cnVjdHVyZSBpcyBwcmVzZXJ2ZWQgaW4gdGhlIGNvbnN0cnVjdCdzIHByb3BzXG4gICAgICBleHBlY3QoXG4gICAgICAgIHBvbGljeURlZmluaXRpb24ucHJvcHMucG9saWN5UnVsZS5pZi5hbGxPZlsxXS5hbnlPZlsxXS5ub3QsXG4gICAgICApLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoXG4gICAgICAgIHBvbGljeURlZmluaXRpb24ucHJvcHMucG9saWN5UnVsZS5pZi5hbGxPZlsxXS5hbnlPZlsxXS5ub3QuZmllbGQsXG4gICAgICApLnRvQmUoXG4gICAgICAgIFwiTWljcm9zb2Z0Lk5ldHdvcmsvdmlydHVhbE5ldHdvcmtzL3N1Ym5ldHNbKl0uc2VydmljZUVuZHBvaW50c1sqXS5zZXJ2aWNlXCIsXG4gICAgICApO1xuXG4gICAgICAvLyBWZXJpZnkgdGhlIHN5bnRoZXNpemVkIGNvbmZpZyBoYXMgdGhlIGJvZHkgcHJvcGVydHkgc2V0XG4gICAgICBleHBlY3QoYXphcGlSZXNvdXJjZS5ib2R5KS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcIkVycm9yIEhhbmRsaW5nXCIsICgpID0+IHtcbiAgICBpdChcInNob3VsZCBoYW5kbGUgaW52YWxpZCBBUEkgdmVyc2lvbnMgZ3JhY2VmdWxseVwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJJbnZhbGlkQVBJXCIsIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICAgICAgYXBpVmVyc2lvbjogXCJpbnZhbGlkLXZlcnNpb25cIixcbiAgICAgICAgfSk7XG4gICAgICB9KS50b1Rocm93KFwiVW5zdXBwb3J0ZWQgQVBJIHZlcnNpb24gJ2ludmFsaWQtdmVyc2lvbidcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBoYW5kbGUgdmFsaWRhdGlvbiBlcnJvcnMgd2hlbiB2YWxpZGF0aW9uIGlzIGVuYWJsZWRcIiwgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiVmFsaWRhdGlvbkVycm9yXCIsIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogdW5kZWZpbmVkIGFzIGFueSwgLy8gTWlzc2luZyByZXF1aXJlZCBwb2xpY3lSdWxlXG4gICAgICAgICAgZW5hYmxlVmFsaWRhdGlvbjogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICB9KS50b1Rocm93KFwiUmVxdWlyZWQgcHJvcGVydHkgJ3BvbGljeVJ1bGUnIGlzIG1pc3NpbmdcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBoYW5kbGUgc2NoZW1hIHJlZ2lzdHJhdGlvbiBlcnJvcnMgZ3JhY2VmdWxseVwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJTY2hlbWFUZXN0XCIsIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcG9saWN5XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICAgIH0pO1xuICAgICAgfSkubm90LnRvVGhyb3coKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJKU0lJIENvbXBsaWFuY2VcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIGhhdmUgSlNJSS1jb21wbGlhbnQgY29uc3RydWN0b3JcIiwgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiSnNpaVRlc3RcIiwge1xuICAgICAgICAgIG5hbWU6IFwianNpaS10ZXN0XCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICAgIH0pO1xuICAgICAgfSkubm90LnRvVGhyb3coKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIGhhdmUgSlNJSS1jb21wbGlhbnQgcHJvcGVydGllc1wiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiSnNpaVByb3BzXCIsIHtcbiAgICAgICAgbmFtZTogXCJqc2lpLXByb3BzXCIsXG4gICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJkZW55XCIgfSB9LFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdCh0eXBlb2YgcG9saWN5RGVmaW5pdGlvbi5pZCkudG9CZShcInN0cmluZ1wiKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgcG9saWN5RGVmaW5pdGlvbi5uYW1lKS50b0JlKFwic3RyaW5nXCIpO1xuICAgICAgZXhwZWN0KHR5cGVvZiBwb2xpY3lEZWZpbml0aW9uLnJlc29sdmVkQXBpVmVyc2lvbikudG9CZShcInN0cmluZ1wiKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgcG9saWN5RGVmaW5pdGlvbi5wb2xpY3lUeXBlKS50b0JlKFwic3RyaW5nXCIpO1xuICAgICAgZXhwZWN0KHR5cGVvZiBwb2xpY3lEZWZpbml0aW9uLnBvbGljeU1vZGUpLnRvQmUoXCJzdHJpbmdcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBoYXZlIEpTSUktY29tcGxpYW50IG1ldGhvZHNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKHN0YWNrLCBcIkpzaWlNZXRob2RzXCIsIHtcbiAgICAgICAgbmFtZTogXCJqc2lpLW1ldGhvZHNcIixcbiAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9IH0sXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KHR5cGVvZiBwb2xpY3lEZWZpbml0aW9uLmxhdGVzdFZlcnNpb24pLnRvQmUoXCJmdW5jdGlvblwiKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgcG9saWN5RGVmaW5pdGlvbi5zdXBwb3J0ZWRWZXJzaW9ucykudG9CZShcImZ1bmN0aW9uXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzaG91bGQgc2VyaWFsaXplIGNvbXBsZXggb2JqZWN0cyBjb3JyZWN0bHlcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5RGVmaW5pdGlvbiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgXCJKc2lpU2VyaWFsaXphdGlvblwiLFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJqc2lpLXNlcmlhbGl6YXRpb25cIixcbiAgICAgICAgICBwb2xpY3lSdWxlOiB7XG4gICAgICAgICAgICBpZjogeyBmaWVsZDogXCJsb2NhdGlvblwiLCBlcXVhbHM6IFwiZWFzdHVzXCIgfSxcbiAgICAgICAgICAgIHRoZW46IHsgZWZmZWN0OiBcImRlbnlcIiB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgdGVzdFBhcmFtOiB7XG4gICAgICAgICAgICAgIHR5cGU6IFwiU3RyaW5nXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgSlNPTi5zdHJpbmdpZnkocG9saWN5RGVmaW5pdGlvbi52YWxpZGF0aW9uUmVzdWx0KSxcbiAgICAgICkubm90LnRvVGhyb3coKTtcbiAgICAgIGV4cGVjdCgoKSA9PiBKU09OLnN0cmluZ2lmeShwb2xpY3lEZWZpbml0aW9uLnNjaGVtYSkpLm5vdC50b1Rocm93KCk7XG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgSlNPTi5zdHJpbmdpZnkocG9saWN5RGVmaW5pdGlvbi52ZXJzaW9uQ29uZmlnKSxcbiAgICAgICkubm90LnRvVGhyb3coKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJDREsgVGVycmFmb3JtIEludGVncmF0aW9uXCIsICgpID0+IHtcbiAgICBpdChcInNob3VsZCBzeW50aGVzaXplIHRvIHZhbGlkIFRlcnJhZm9ybSBjb25maWd1cmF0aW9uXCIsICgpID0+IHtcbiAgICAgIG5ldyBQb2xpY3lEZWZpbml0aW9uKHN0YWNrLCBcIlN5bnRoVGVzdFwiLCB7XG4gICAgICAgIG5hbWU6IFwic3ludGgtdGVzdFwiLFxuICAgICAgICBwb2xpY3lSdWxlOiB7XG4gICAgICAgICAgaWY6IHtcbiAgICAgICAgICAgIGZpZWxkOiBcInR5cGVcIixcbiAgICAgICAgICAgIGVxdWFsczogXCJNaWNyb3NvZnQuQ29tcHV0ZS92aXJ0dWFsTWFjaGluZXNcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHRoZW46IHtcbiAgICAgICAgICAgIGVmZmVjdDogXCJhdWRpdFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgc3ludGhlc2l6ZWQgPSBUZXN0aW5nLnN5bnRoKHN0YWNrKTtcbiAgICAgIGV4cGVjdChzeW50aGVzaXplZCkudG9CZURlZmluZWQoKTtcblxuICAgICAgY29uc3Qgc3RhY2tDb25maWcgPSBKU09OLnBhcnNlKHN5bnRoZXNpemVkKTtcbiAgICAgIGV4cGVjdChzdGFja0NvbmZpZy5yZXNvdXJjZSkudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIHdvcmsgaW4gY29tcGxleCBDREsgY29uc3RydWN0c1wiLCAoKSA9PiB7XG4gICAgICBjbGFzcyBDb21wbGV4Q29uc3RydWN0IGV4dGVuZHMgY2RrdGYuVGVycmFmb3JtU3RhY2sge1xuICAgICAgICBjb25zdHJ1Y3RvcihzY29wZTogY2RrdGYuQXBwLCBpZDogc3RyaW5nKSB7XG4gICAgICAgICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgICAgICAgIGNvbnN0IHBvbGljeTEgPSBuZXcgUG9saWN5RGVmaW5pdGlvbih0aGlzLCBcIlBvbGljeTFcIiwge1xuICAgICAgICAgICAgbmFtZTogXCJwb2xpY3ktMVwiLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6IFwiRmlyc3QgUG9saWN5XCIsXG4gICAgICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiYXVkaXRcIiB9IH0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb25zdCBwb2xpY3kyID0gbmV3IFBvbGljeURlZmluaXRpb24odGhpcywgXCJQb2xpY3kyXCIsIHtcbiAgICAgICAgICAgIG5hbWU6IFwicG9saWN5LTJcIixcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiBcIlNlY29uZCBQb2xpY3lcIixcbiAgICAgICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJkZW55XCIgfSB9LFxuICAgICAgICAgICAgYXBpVmVyc2lvbjogXCIyMDIxLTA2LTAxXCIsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBuZXcgY2RrdGYuVGVycmFmb3JtT3V0cHV0KHRoaXMsIFwiUG9saWN5MUlkXCIsIHtcbiAgICAgICAgICAgIHZhbHVlOiBwb2xpY3kxLmlkLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgbmV3IGNka3RmLlRlcnJhZm9ybU91dHB1dCh0aGlzLCBcIlBvbGljeTJJZFwiLCB7XG4gICAgICAgICAgICB2YWx1ZTogcG9saWN5Mi5pZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgQ29tcGxleENvbnN0cnVjdChhcHAsIFwiQ29tcGxleFN0YWNrXCIpO1xuICAgICAgfSkubm90LnRvVGhyb3coKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIGhhbmRsZSBtdWx0aXBsZSBwb2xpY3kgZGVmaW5pdGlvbnMgaW4gdGhlIHNhbWUgc3RhY2tcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcG9saWN5MSA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKHN0YWNrLCBcIlBvbGljeURlZmluaXRpb24xXCIsIHtcbiAgICAgICAgbmFtZTogXCJwb2xpY3ktMVwiLFxuICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiYXVkaXRcIiB9IH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcG9saWN5MiA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKHN0YWNrLCBcIlBvbGljeURlZmluaXRpb24yXCIsIHtcbiAgICAgICAgbmFtZTogXCJwb2xpY3ktMlwiLFxuICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiZGVueVwiIH0gfSxcbiAgICAgICAgYXBpVmVyc2lvbjogXCIyMDIxLTA2LTAxXCIsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KHBvbGljeTEucmVzb2x2ZWRBcGlWZXJzaW9uKS50b0JlKFwiMjAyMS0wNi0wMVwiKTtcbiAgICAgIGV4cGVjdChwb2xpY3kyLnJlc29sdmVkQXBpVmVyc2lvbikudG9CZShcIjIwMjEtMDYtMDFcIik7XG5cbiAgICAgIGNvbnN0IHN5bnRoZXNpemVkID0gVGVzdGluZy5zeW50aChzdGFjayk7XG4gICAgICBleHBlY3Qoc3ludGhlc2l6ZWQpLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiUG9saWN5IERlZmluaXRpb24gVHlwZXNcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIHN1cHBvcnQgQnVpbHRJbiBwb2xpY3kgdHlwZVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwb2xpY3lEZWZpbml0aW9uID0gbmV3IFBvbGljeURlZmluaXRpb24oc3RhY2ssIFwiQnVpbHRJblBvbGljeVwiLCB7XG4gICAgICAgIG5hbWU6IFwiYnVpbHRpbi1wb2xpY3lcIixcbiAgICAgICAgcG9saWN5VHlwZTogXCJCdWlsdEluXCIsXG4gICAgICAgIHBvbGljeVJ1bGU6IHsgaWY6IHt9LCB0aGVuOiB7IGVmZmVjdDogXCJhdWRpdFwiIH0gfSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QocG9saWN5RGVmaW5pdGlvbi5wb2xpY3lUeXBlKS50b0JlKFwiQnVpbHRJblwiKTtcbiAgICB9KTtcblxuICAgIGl0KFwic2hvdWxkIHN1cHBvcnQgU3RhdGljIHBvbGljeSB0eXBlXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHBvbGljeURlZmluaXRpb24gPSBuZXcgUG9saWN5RGVmaW5pdGlvbihzdGFjaywgXCJTdGF0aWNQb2xpY3lcIiwge1xuICAgICAgICBuYW1lOiBcInN0YXRpYy1wb2xpY3lcIixcbiAgICAgICAgcG9saWN5VHlwZTogXCJTdGF0aWNcIixcbiAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImF1ZGl0XCIgfSB9LFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChwb2xpY3lEZWZpbml0aW9uLnBvbGljeVR5cGUpLnRvQmUoXCJTdGF0aWNcIik7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBzdXBwb3J0IGRpZmZlcmVudCBwb2xpY3kgbW9kZXNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgaW5kZXhlZFBvbGljeSA9IG5ldyBQb2xpY3lEZWZpbml0aW9uKHN0YWNrLCBcIkluZGV4ZWRQb2xpY3lcIiwge1xuICAgICAgICBuYW1lOiBcImluZGV4ZWQtcG9saWN5XCIsXG4gICAgICAgIG1vZGU6IFwiSW5kZXhlZFwiLFxuICAgICAgICBwb2xpY3lSdWxlOiB7IGlmOiB7fSwgdGhlbjogeyBlZmZlY3Q6IFwiYXVkaXRcIiB9IH0sXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KGluZGV4ZWRQb2xpY3kucG9saWN5TW9kZSkudG9CZShcIkluZGV4ZWRcIik7XG5cbiAgICAgIGNvbnN0IHJlc291cmNlUHJvdmlkZXJQb2xpY3kgPSBuZXcgUG9saWN5RGVmaW5pdGlvbihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgIFwiUmVzb3VyY2VQcm92aWRlclBvbGljeVwiLFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJyZXNvdXJjZS1wcm92aWRlci1wb2xpY3lcIixcbiAgICAgICAgICBtb2RlOiBcIk1pY3Jvc29mdC5LZXlWYXVsdC5EYXRhXCIsXG4gICAgICAgICAgcG9saWN5UnVsZTogeyBpZjoge30sIHRoZW46IHsgZWZmZWN0OiBcImF1ZGl0XCIgfSB9LFxuICAgICAgICB9LFxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KHJlc291cmNlUHJvdmlkZXJQb2xpY3kucG9saWN5TW9kZSkudG9CZShcIk1pY3Jvc29mdC5LZXlWYXVsdC5EYXRhXCIpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|