aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
679 lines • 72.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable import/order */
const aws = require("aws-sdk");
const AWS = require("aws-sdk-mock");
const vpcs_1 = require("../../lib/context-providers/vpcs");
const mock_sdk_1 = require("../util/mock-sdk");
// If the 'aws-sdk' package imported here and the 'aws-sdk' package imported by 'aws-sdk-mock' aren't
// the same physical package on disk (if version mismatches cause hoisting/deduping to not happen),
// the type check here takes too long and makes the TypeScript compiler fail.
// Suppress the type check using 'as any' to make this more robust.
AWS.setSDKInstance(aws);
afterEach(done => {
AWS.restore();
done();
});
const mockSDK = new mock_sdk_1.MockSdkProvider();
test('looks up the requested (symmetric) VPC', async () => {
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: true, CidrBlock: '1.1.1.1/24' },
{ SubnetId: 'sub-789012', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false, CidrBlock: '1.1.2.1/24' },
],
routeTables: [
{
Associations: [{ SubnetId: 'sub-123456' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '1.1.1.1/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
GatewayId: 'igw-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
{
Associations: [{ SubnetId: 'sub-789012' }],
RouteTableId: 'rtb-789012',
Routes: [
{
DestinationCidrBlock: '1.1.2.1/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
NatGatewayId: 'nat-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
vpnGateways: [{ VpnGatewayId: 'gw-abcdef' }],
});
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
subnetGroups: [
{
name: 'Public',
type: 'Public',
subnets: [
{
subnetId: 'sub-123456',
availabilityZone: 'bermuda-triangle-1337',
routeTableId: 'rtb-123456',
cidr: '1.1.1.1/24',
},
],
},
{
name: 'Private',
type: 'Private',
subnets: [
{
subnetId: 'sub-789012',
availabilityZone: 'bermuda-triangle-1337',
routeTableId: 'rtb-789012',
cidr: '1.1.2.1/24',
},
],
},
],
vpcId: 'vpc-1234567',
vpnGatewayId: 'gw-abcdef',
});
});
test('throws when no such VPC is found', async () => {
AWS.mock('EC2', 'describeVpcs', (params, cb) => {
expect(params.Filters).toEqual([{ Name: 'foo', Values: ['bar'] }]);
return cb(null, {});
});
await expect(new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
})).rejects.toThrow(/Could not find any VPCs matching/);
});
test('throws when multiple VPCs are found', async () => {
// GIVEN
AWS.mock('EC2', 'describeVpcs', (params, cb) => {
expect(params.Filters).toEqual([{ Name: 'foo', Values: ['bar'] }]);
return cb(null, { Vpcs: [{ VpcId: 'vpc-1' }, { VpcId: 'vpc-2' }] });
});
// WHEN
await expect(new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
})).rejects.toThrow(/Found 2 VPCs matching/);
});
test('uses the VPC main route table when a subnet has no specific association', async () => {
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: true, CidrBlock: '1.1.1.1/24' },
{ SubnetId: 'sub-789012', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false, CidrBlock: '1.1.2.1/24' },
],
routeTables: [
{
Associations: [{ SubnetId: 'sub-123456' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '1.1.1.1/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
GatewayId: 'igw-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
{
Associations: [{ Main: true }],
RouteTableId: 'rtb-789012',
Routes: [
{
DestinationCidrBlock: '1.1.2.1/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
NatGatewayId: 'nat-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
vpnGateways: [{ VpnGatewayId: 'gw-abcdef' }],
});
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
subnetGroups: [
{
name: 'Public',
type: 'Public',
subnets: [
{
subnetId: 'sub-123456',
availabilityZone: 'bermuda-triangle-1337',
routeTableId: 'rtb-123456',
cidr: '1.1.1.1/24',
},
],
},
{
name: 'Private',
type: 'Private',
subnets: [
{
subnetId: 'sub-789012',
availabilityZone: 'bermuda-triangle-1337',
routeTableId: 'rtb-789012',
cidr: '1.1.2.1/24',
},
],
},
],
vpcId: 'vpc-1234567',
vpnGatewayId: 'gw-abcdef',
});
});
test('Recognize public subnet by route table', async () => {
// GIVEN
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false },
],
routeTables: [
{
Associations: [{ SubnetId: 'sub-123456' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '10.0.2.0/26',
Origin: 'CreateRoute',
State: 'active',
VpcPeeringConnectionId: 'pcx-xxxxxx',
},
{
DestinationCidrBlock: '1.1.1.1/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
GatewayId: 'igw-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
});
// WHEN
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
subnetGroups: [
{
name: 'Public',
type: 'Public',
subnets: [
{
subnetId: 'sub-123456',
availabilityZone: 'bermuda-triangle-1337',
routeTableId: 'rtb-123456',
cidr: undefined,
},
],
},
],
vpcId: 'vpc-1234567',
vpnGatewayId: undefined,
});
});
test('Recognize isolated subnet by route table', async () => {
// GIVEN
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false },
],
routeTables: [
{
Associations: [{ SubnetId: 'sub-123456' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '1.1.2.1/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
],
},
],
});
// WHEN
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
subnetGroups: [
{
name: 'Isolated',
type: 'Isolated',
subnets: [
{
subnetId: 'sub-123456',
availabilityZone: 'bermuda-triangle-1337',
routeTableId: 'rtb-123456',
cidr: undefined,
},
],
},
],
vpcId: 'vpc-1234567',
vpnGatewayId: undefined,
});
});
test('Recognize private subnet by route table', async () => {
// GIVEN
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false },
],
routeTables: [
{
Associations: [{ SubnetId: 'sub-123456' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '10.0.2.0/26',
Origin: 'CreateRoute',
State: 'active',
VpcPeeringConnectionId: 'pcx-xxxxxx',
},
{
DestinationCidrBlock: '1.1.2.1/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
NatGatewayId: 'nat-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
});
// WHEN
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
subnetGroups: [
{
name: 'Private',
type: 'Private',
subnets: [
{
subnetId: 'sub-123456',
availabilityZone: 'bermuda-triangle-1337',
routeTableId: 'rtb-123456',
cidr: undefined,
},
],
},
],
vpcId: 'vpc-1234567',
vpnGatewayId: undefined,
});
});
test('works for asymmetric subnets (not spanning the same Availability Zones)', async () => {
// GIVEN
mockVpcLookup({
subnets: [
{ SubnetId: 'pri-sub-in-1b', AvailabilityZone: 'us-west-1b', MapPublicIpOnLaunch: false, CidrBlock: '1.1.1.1/24' },
{ SubnetId: 'pub-sub-in-1c', AvailabilityZone: 'us-west-1c', MapPublicIpOnLaunch: true, CidrBlock: '1.1.2.1/24' },
{ SubnetId: 'pub-sub-in-1b', AvailabilityZone: 'us-west-1b', MapPublicIpOnLaunch: true, CidrBlock: '1.1.3.1/24' },
{ SubnetId: 'pub-sub-in-1a', AvailabilityZone: 'us-west-1a', MapPublicIpOnLaunch: true, CidrBlock: '1.1.4.1/24' },
],
routeTables: [
{
Associations: [{ SubnetId: 'pri-sub-in-1b' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '0.0.0.0/0',
NatGatewayId: 'nat-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
{
Associations: [{ Main: true }],
RouteTableId: 'rtb-789012',
Routes: [
{
DestinationCidrBlock: '0.0.0.0/0',
GatewayId: 'igw-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
});
// WHEN
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
subnetGroups: [
{
name: 'Private',
type: 'Private',
subnets: [
{
subnetId: 'pri-sub-in-1b',
availabilityZone: 'us-west-1b',
routeTableId: 'rtb-123456',
cidr: '1.1.1.1/24',
},
],
},
{
name: 'Public',
type: 'Public',
subnets: [
{
subnetId: 'pub-sub-in-1a',
availabilityZone: 'us-west-1a',
routeTableId: 'rtb-789012',
cidr: '1.1.4.1/24',
},
{
subnetId: 'pub-sub-in-1b',
availabilityZone: 'us-west-1b',
routeTableId: 'rtb-789012',
cidr: '1.1.3.1/24',
},
{
subnetId: 'pub-sub-in-1c',
availabilityZone: 'us-west-1c',
routeTableId: 'rtb-789012',
cidr: '1.1.2.1/24',
},
],
},
],
vpcId: 'vpc-1234567',
vpnGatewayId: undefined,
});
});
test('allows specifying the subnet group name tag', async () => {
// GIVEN
mockVpcLookup({
subnets: [
{
SubnetId: 'pri-sub-in-1b',
AvailabilityZone: 'us-west-1b',
MapPublicIpOnLaunch: false,
Tags: [
{ Key: 'Tier', Value: 'restricted' },
],
},
{
SubnetId: 'pub-sub-in-1c',
AvailabilityZone: 'us-west-1c',
MapPublicIpOnLaunch: true,
Tags: [
{ Key: 'Tier', Value: 'connectivity' },
],
},
{
SubnetId: 'pub-sub-in-1b',
AvailabilityZone: 'us-west-1b',
MapPublicIpOnLaunch: true,
Tags: [
{ Key: 'Tier', Value: 'connectivity' },
],
},
{
SubnetId: 'pub-sub-in-1a',
AvailabilityZone: 'us-west-1a',
MapPublicIpOnLaunch: true,
Tags: [
{ Key: 'Tier', Value: 'connectivity' },
],
},
],
routeTables: [
{
Associations: [{ SubnetId: 'pri-sub-in-1b' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '0.0.0.0/0',
NatGatewayId: 'nat-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
{
Associations: [{ Main: true }],
RouteTableId: 'rtb-789012',
Routes: [
{
DestinationCidrBlock: '0.0.0.0/0',
GatewayId: 'igw-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
});
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '1234',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
subnetGroupNameTag: 'Tier',
});
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
subnetGroups: [
{
name: 'restricted',
type: 'Private',
subnets: [
{
subnetId: 'pri-sub-in-1b',
availabilityZone: 'us-west-1b',
routeTableId: 'rtb-123456',
cidr: undefined,
},
],
},
{
name: 'connectivity',
type: 'Public',
subnets: [
{
subnetId: 'pub-sub-in-1a',
availabilityZone: 'us-west-1a',
routeTableId: 'rtb-789012',
cidr: undefined,
},
{
subnetId: 'pub-sub-in-1b',
availabilityZone: 'us-west-1b',
routeTableId: 'rtb-789012',
cidr: undefined,
},
{
subnetId: 'pub-sub-in-1c',
availabilityZone: 'us-west-1c',
routeTableId: 'rtb-789012',
cidr: undefined,
},
],
},
],
vpcId: 'vpc-1234567',
vpnGatewayId: undefined,
});
});
function mockVpcLookup(options) {
const VpcId = 'vpc-1234567';
AWS.mock('EC2', 'describeVpcs', (params, cb) => {
expect(params.Filters).toEqual([{ Name: 'foo', Values: ['bar'] }]);
return cb(null, { Vpcs: [{ VpcId, CidrBlock: '1.1.1.1/16' }] });
});
AWS.mock('EC2', 'describeSubnets', (params, cb) => {
expect(params.Filters).toEqual([{ Name: 'vpc-id', Values: [VpcId] }]);
return cb(null, { Subnets: options.subnets });
});
AWS.mock('EC2', 'describeRouteTables', (params, cb) => {
expect(params.Filters).toEqual([{ Name: 'vpc-id', Values: [VpcId] }]);
return cb(null, { RouteTables: options.routeTables });
});
AWS.mock('EC2', 'describeVpnGateways', (params, cb) => {
expect(params.Filters).toEqual([
{ Name: 'attachment.vpc-id', Values: [VpcId] },
{ Name: 'attachment.state', Values: ['attached'] },
{ Name: 'state', Values: ['available'] },
]);
return cb(null, { VpnGateways: options.vpnGateways });
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bW1ldHJpYy12cGNzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJhc3ltbWV0cmljLXZwY3MudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFpQztBQUNqQywrQkFBK0I7QUFDL0Isb0NBQW9DO0FBQ3BDLDJEQUFtRjtBQUNuRiwrQ0FBbUQ7QUFFbkQscUdBQXFHO0FBQ3JHLG1HQUFtRztBQUNuRyw2RUFBNkU7QUFDN0UsbUVBQW1FO0FBQ25FLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBVSxDQUFDLENBQUM7QUFFL0IsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFO0lBQ2YsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2QsSUFBSSxFQUFFLENBQUM7QUFDVCxDQUFDLENBQUMsQ0FBQztBQUVILE1BQU0sT0FBTyxHQUFHLElBQUksMEJBQWUsRUFBRSxDQUFDO0FBSXRDLElBQUksQ0FBQyx3Q0FBd0MsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN4RCxhQUFhLENBQUM7UUFDWixPQUFPLEVBQUU7WUFDUCxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsdUJBQXVCLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUU7WUFDekgsRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLGdCQUFnQixFQUFFLHVCQUF1QixFQUFFLG1CQUFtQixFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFO1NBQzNIO1FBQ0QsV0FBVyxFQUFFO1lBQ1g7Z0JBQ0UsWUFBWSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLENBQUM7Z0JBQzFDLFlBQVksRUFBRSxZQUFZO2dCQUMxQixNQUFNLEVBQUU7b0JBQ047d0JBQ0Usb0JBQW9CLEVBQUUsWUFBWTt3QkFDbEMsU0FBUyxFQUFFLE9BQU87d0JBQ2xCLE1BQU0sRUFBRSxrQkFBa0I7d0JBQzFCLEtBQUssRUFBRSxR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b3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGstbW9jayc7XG5pbXBvcnQgeyBWcGNOZXR3b3JrQ29udGV4dFByb3ZpZGVyUGx1Z2luIH0gZnJvbSAnLi4vLi4vbGliL2NvbnRleHQtcHJvdmlkZXJzL3ZwY3MnO1xuaW1wb3J0IHsgTW9ja1Nka1Byb3ZpZGVyIH0gZnJvbSAnLi4vdXRpbC9tb2NrLXNkayc7XG5cbi8vIElmIHRoZSAnYXdzLXNkaycgcGFja2FnZSBpbXBvcnRlZCBoZXJlIGFuZCB0aGUgJ2F3cy1zZGsnIHBhY2thZ2UgaW1wb3J0ZWQgYnkgJ2F3cy1zZGstbW9jaycgYXJlbid0XG4vLyB0aGUgc2FtZSBwaHlzaWNhbCBwYWNrYWdlIG9uIGRpc2sgKGlmIHZlcnNpb24gbWlzbWF0Y2hlcyBjYXVzZSBob2lzdGluZy9kZWR1cGluZyB0byBub3QgaGFwcGVuKSxcbi8vIHRoZSB0eXBlIGNoZWNrIGhlcmUgdGFrZXMgdG9vIGxvbmcgYW5kIG1ha2VzIHRoZSBUeXBlU2NyaXB0IGNvbXBpbGVyIGZhaWwuXG4vLyBTdXBwcmVzcyB0aGUgdHlwZSBjaGVjayB1c2luZyAnYXMgYW55JyB0byBtYWtlIHRoaXMgbW9yZSByb2J1c3QuXG5BV1Muc2V0U0RLSW5zdGFuY2UoYXdzIGFzIGFueSk7XG5cbmFmdGVyRWFjaChkb25lID0+IHtcbiAgQVdTLnJlc3RvcmUoKTtcbiAgZG9uZSgpO1xufSk7XG5cbmNvbnN0IG1vY2tTREsgPSBuZXcgTW9ja1Nka1Byb3ZpZGVyKCk7XG5cbnR5cGUgQXdzQ2FsbGJhY2s8VD4gPSAoZXJyOiBFcnJvciB8IG51bGwsIHZhbDogVCkgPT4gdm9pZDtcblxudGVzdCgnbG9va3MgdXAgdGhlIHJlcXVlc3RlZCAoc3ltbWV0cmljKSBWUEMnLCBhc3luYyAoKSA9PiB7XG4gIG1vY2tWcGNMb29rdXAoe1xuICAgIHN1Ym5ldHM6IFtcbiAgICAgIHsgU3VibmV0SWQ6ICdzdWItMTIzNDU2JywgQXZhaWxhYmlsaXR5Wm9uZTogJ2Jlcm11ZGEtdHJpYW5nbGUtMTMzNycsIE1hcFB1YmxpY0lwT25MYXVuY2g6IHRydWUsIENpZHJCbG9jazogJzEuMS4xLjEvMjQnIH0sXG4gICAgICB7IFN1Ym5ldElkOiAnc3ViLTc4OTAxMicsIEF2YWlsYWJpbGl0eVpvbmU6ICdiZXJtdWRhLXRyaWFuZ2xlLTEzMzcnLCBNYXBQdWJsaWNJcE9uTGF1bmNoOiBmYWxzZSwgQ2lkckJsb2NrOiAnMS4xLjIuMS8yNCcgfSxcbiAgICBdLFxuICAgIHJvdXRlVGFibGVzOiBbXG4gICAgICB7XG4gICAgICAgIEFzc29jaWF0aW9uczogW3sgU3VibmV0SWQ6ICdzdWItMTIzNDU2JyB9XSxcbiAgICAgICAgUm91dGVUYWJsZUlkOiAncnRiLTEyMzQ1NicsXG4gICAgICAgIFJvdXRlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIERlc3RpbmF0aW9uQ2lkckJsb2NrOiAnMS4xLjEuMS8yNCcsXG4gICAgICAgICAgICBHYXRld2F5SWQ6ICdsb2NhbCcsXG4gICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZVRhYmxlJyxcbiAgICAgICAgICAgIFN0YXRlOiAnYWN0aXZlJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIERlc3RpbmF0aW9uQ2lkckJsb2NrOiAnMC4wLjAuMC8wJyxcbiAgICAgICAgICAgIEdhdGV3YXlJZDogJ2lndy14eHh4eHgnLFxuICAgICAgICAgICAgT3JpZ2luOiAnQ3JlYXRlUm91dGUnLFxuICAgICAgICAgICAgU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBBc3NvY2lhdGlvbnM6IFt7IFN1Ym5ldElkOiAnc3ViLTc4OTAxMicgfV0sXG4gICAgICAgIFJvdXRlVGFibGVJZDogJ3J0Yi03ODkwMTInLFxuICAgICAgICBSb3V0ZXM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBEZXN0aW5hdGlvbkNpZHJCbG9jazogJzEuMS4yLjEvMjQnLFxuICAgICAgICAgICAgR2F0ZXdheUlkOiAnbG9jYWwnLFxuICAgICAgICAgICAgT3JpZ2luOiAnQ3JlYXRlUm91dGVUYWJsZScsXG4gICAgICAgICAgICBTdGF0ZTogJ2FjdGl2ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBEZXN0aW5hdGlvbkNpZHJCbG9jazogJzAuMC4wLjAvMCcsXG4gICAgICAgICAgICBOYXRHYXRld2F5SWQ6ICduYXQteHh4eHh4JyxcbiAgICAgICAgICAgIE9yaWdpbjogJ0NyZWF0ZVJvdXRlJyxcbiAgICAgICAgICAgIFN0YXRlOiAnYWN0aXZlJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICBdLFxuICAgIHZwbkdhdGV3YXlzOiBbeyBWcG5HYXRld2F5SWQ6ICdndy1hYmNkZWYnIH1dLFxuXG4gIH0pO1xuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG5ldyBWcGNOZXR3b3JrQ29udGV4dFByb3ZpZGVyUGx1Z2luKG1vY2tTREspLmdldFZhbHVlKHtcbiAgICBhY2NvdW50OiAnMTIzNCcsXG4gICAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgICBmaWx0ZXI6IHsgZm9vOiAnYmFyJyB9LFxuICAgIHJldHVybkFzeW1tZXRyaWNTdWJuZXRzOiB0cnVlLFxuICB9KTtcblxuICBleHBlY3QocmVzdWx0KS50b0VxdWFsKHtcbiAgICBhdmFpbGFiaWxpdHlab25lczogW10sXG4gICAgdnBjQ2lkckJsb2NrOiAnMS4xLjEuMS8xNicsXG4gICAgaXNvbGF0ZWRTdWJuZXRJZHM6IHVuZGVmaW5lZCxcbiAgICBpc29sYXRlZFN1Ym5ldE5hbWVzOiB1bmRlZmluZWQsXG4gICAgaXNvbGF0ZWRTdWJuZXRSb3V0ZVRhYmxlSWRzOiB1bmRlZmluZWQsXG4gICAgcHJpdmF0ZVN1Ym5ldElkczogdW5kZWZpbmVkLFxuICAgIHByaXZhdGVTdWJuZXROYW1lczogdW5kZWZpbmVkLFxuICAgIHByaXZhdGVTdWJuZXRSb3V0ZVRhYmxlSWRzOiB1bmRlZmluZWQsXG4gICAgcHVibGljU3VibmV0SWRzOiB1bmRlZmluZWQsXG4gICAgcHVibGljU3VibmV0TmFtZXM6IHVuZGVmaW5lZCxcbiAgICBwdWJsaWNTdWJuZXRSb3V0ZVRhYmxlSWRzOiB1bmRlZmluZWQsXG4gICAgc3VibmV0R3JvdXBzOiBbXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICdQdWJsaWMnLFxuICAgICAgICB0eXBlOiAnUHVibGljJyxcbiAgICAgICAgc3VibmV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHN1Ym5ldElkOiAnc3ViLTEyMzQ1NicsXG4gICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lOiAnYmVybXVkYS10cmlhbmdsZS0xMzM3JyxcbiAgICAgICAgICAgIHJvdXRlVGFibGVJZDogJ3J0Yi0xMjM0NTYnLFxuICAgICAgICAgICAgY2lkcjogJzEuMS4xLjEvMjQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnUHJpdmF0ZScsXG4gICAgICAgIHR5cGU6ICdQcml2YXRlJyxcbiAgICAgICAgc3VibmV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHN1Ym5ldElkOiAnc3ViLTc4OTAxMicsXG4gICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lOiAnYmVybXVkYS10cmlhbmdsZS0xMzM3JyxcbiAgICAgICAgICAgIHJvdXRlVGFibGVJZDogJ3J0Yi03ODkwMTInLFxuICAgICAgICAgICAgY2lkcjogJzEuMS4yLjEvMjQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIF0sXG4gICAgdnBjSWQ6ICd2cGMtMTIzNDU2NycsXG4gICAgdnBuR2F0ZXdheUlkOiAnZ3ctYWJjZGVmJyxcbiAgfSk7XG59KTtcblxudGVzdCgndGhyb3dzIHdoZW4gbm8gc3VjaCBWUEMgaXMgZm91bmQnLCBhc3luYyAoKSA9PiB7XG4gIEFXUy5tb2NrKCdFQzInLCAnZGVzY3JpYmVWcGNzJywgKHBhcmFtczogYXdzLkVDMi5EZXNjcmliZVZwY3NSZXF1ZXN0LCBjYjogQXdzQ2FsbGJhY2s8YXdzLkVDMi5EZXNjcmliZVZwY3NSZXN1bHQ+KSA9PiB7XG4gICAgZXhwZWN0KHBhcmFtcy5GaWx0ZXJzKS50b0VxdWFsKFt7IE5hbWU6ICdmb28nLCBWYWx1ZXM6IFsnYmFyJ10gfV0pO1xuICAgIHJldHVybiBjYihudWxsLCB7fSk7XG4gIH0pO1xuXG4gIGF3YWl0IGV4cGVjdChuZXcgVnBjTmV0d29ya0NvbnRleHRQcm92aWRlclBsdWdpbihtb2NrU0RLKS5nZXRWYWx1ZSh7XG4gICAgYWNjb3VudDogJzEyMzQnLFxuICAgIHJlZ2lvbjogJ3VzLWVhc3QtMScsXG4gICAgZmlsdGVyOiB7IGZvbzogJ2JhcicgfSxcbiAgICByZXR1cm5Bc3ltbWV0cmljU3VibmV0czogdHJ