aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
691 lines • 71.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const client_ec2_1 = require("@aws-sdk/client-ec2");
const vpcs_1 = require("../../lib/context-providers/vpcs");
const mock_sdk_1 = require("../util/mock-sdk");
beforeEach(() => {
(0, mock_sdk_1.restoreSdkMocksToDefault)();
mock_sdk_1.mockEC2Client
.on(client_ec2_1.DescribeVpcsCommand)
.resolves({
Vpcs: [{ VpcId: 'vpc-1234567', CidrBlock: '1.1.1.1/16' }],
})
.on(client_ec2_1.DescribeSubnetsCommand)
.resolves({
Subnets: [{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false }],
})
.on(client_ec2_1.DescribeRouteTablesCommand)
.resolves({
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',
},
],
},
],
});
});
const mockSDK = new mock_sdk_1.MockSdkProvider();
test('looks up the requested (symmetric) VPC', async () => {
mock_sdk_1.mockEC2Client
.on(client_ec2_1.DescribeSubnetsCommand)
.resolves({
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',
},
],
})
.on(client_ec2_1.DescribeVpnGatewaysCommand)
.resolves({ VpnGateways: [{ VpnGatewayId: 'gw-abcdef' }] });
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpcsCommand, {
Filters: [{ Name: 'foo', Values: ['bar'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeSubnetsCommand, {
Filters: [{ Name: 'vpc-id', Values: ['vpc-1234567'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeRouteTablesCommand, {
Filters: [{ Name: 'vpc-id', Values: ['vpc-1234567'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpnGatewaysCommand, {
Filters: [
{ Name: 'attachment.vpc-id', Values: ['vpc-1234567'] },
{ Name: 'attachment.state', Values: ['attached'] },
{ Name: 'state', Values: ['available'] },
],
});
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
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 () => {
mock_sdk_1.mockEC2Client.on(client_ec2_1.DescribeVpcsCommand).resolves({});
await expect(new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
})).rejects.toThrow(/Could not find any VPCs matching/);
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpcsCommand, {
Filters: [{ Name: 'foo', Values: ['bar'] }],
});
});
test('throws when multiple VPCs are found', async () => {
// GIVEN
mock_sdk_1.mockEC2Client.on(client_ec2_1.DescribeVpcsCommand).resolves({
Vpcs: [{ VpcId: 'vpc-1' }, { VpcId: 'vpc-2' }],
});
// WHEN
await expect(new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
})).rejects.toThrow(/Found 2 VPCs matching/);
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpcsCommand, {
Filters: [{ Name: 'foo', Values: ['bar'] }],
});
});
test('uses the VPC main route table when a subnet has no specific association', async () => {
mock_sdk_1.mockEC2Client
.on(client_ec2_1.DescribeSubnetsCommand)
.resolves({
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',
},
],
})
.on(client_ec2_1.DescribeRouteTablesCommand)
.resolves({
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',
},
],
},
],
})
.on(client_ec2_1.DescribeVpnGatewaysCommand)
.resolves({
VpnGateways: [{ VpnGatewayId: 'gw-abcdef' }],
});
const result = await new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK).getValue({
account: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpcsCommand, {
Filters: [{ Name: 'foo', Values: ['bar'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeSubnetsCommand, {
Filters: [{ Name: 'vpc-id', Values: ['vpc-1234567'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeRouteTablesCommand, {
Filters: [{ Name: 'vpc-id', Values: ['vpc-1234567'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpnGatewaysCommand, {
Filters: [
{ Name: 'attachment.vpc-id', Values: ['vpc-1234567'] },
{ Name: 'attachment.state', Values: ['attached'] },
{ Name: 'state', Values: ['available'] },
],
});
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
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
mock_sdk_1.mockEC2Client.on(client_ec2_1.DescribeRouteTablesCommand).resolves({
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: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpcsCommand, {
Filters: [{ Name: 'foo', Values: ['bar'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeSubnetsCommand, {
Filters: [{ Name: 'vpc-id', Values: ['vpc-1234567'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeRouteTablesCommand, {
Filters: [{ Name: 'vpc-id', Values: ['vpc-1234567'] }],
});
expect(mock_sdk_1.mockEC2Client).toHaveReceivedCommandWith(client_ec2_1.DescribeVpnGatewaysCommand, {
Filters: [
{ Name: 'attachment.vpc-id', Values: ['vpc-1234567'] },
{ Name: 'attachment.state', Values: ['attached'] },
{ Name: 'state', Values: ['available'] },
],
});
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
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
mock_sdk_1.mockEC2Client.on(client_ec2_1.DescribeRouteTablesCommand).resolves({
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: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
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
mock_sdk_1.mockEC2Client.on(client_ec2_1.DescribeRouteTablesCommand).resolves({
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: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
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
mock_sdk_1.mockEC2Client
.on(client_ec2_1.DescribeSubnetsCommand)
.resolves({
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',
},
],
})
.on(client_ec2_1.DescribeRouteTablesCommand)
.resolves({
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: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
});
// THEN
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
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
mock_sdk_1.mockEC2Client
.on(client_ec2_1.DescribeSubnetsCommand)
.resolves({
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' }],
},
],
})
.on(client_ec2_1.DescribeRouteTablesCommand)
.resolves({
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: '123456789012',
region: 'us-east-1',
filter: { foo: 'bar' },
returnAsymmetricSubnets: true,
subnetGroupNameTag: 'Tier',
});
expect(result).toEqual({
availabilityZones: [],
vpcCidrBlock: '1.1.1.1/16',
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,
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bW1ldHJpYy12cGNzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJhc3ltbWV0cmljLXZwY3MudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLG9EQUs2QjtBQUM3QiwyREFBbUY7QUFDbkYsK0NBQTRGO0FBRTVGLFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDZCxJQUFBLG1DQUF3QixHQUFFLENBQUM7SUFDM0Isd0JBQWE7U0FDVixFQUFFLENBQUMsZ0NBQW1CLENBQUM7U0FDdkIsUUFBUSxDQUFDO1FBQ1IsSUFBSSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsQ0FBQztLQUMxRCxDQUFDO1NBQ0QsRUFBRSxDQUFDLG1DQUFzQixDQUFDO1NBQzFCLFFBQVEsQ0FBQztRQUNSLE9BQU8sRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBRSxtQkFBbUIsRUFBRSxLQUFLLEVBQUUsQ0FBQztLQUM3RyxDQUFDO1NBQ0QsRUFBRSxDQUFDLHVDQUEwQixDQUFDO1NBQzlCLFFBQVEsQ0FBQztRQUNSLFdBQVcsRUFBRTtZQUNYO2dCQUNFLFlBQVksRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxDQUFDO2dCQUMxQyxZQUFZLEVBQUUsWUFBWTtnQkFDMUIsTUFBTSxFQUFFO29CQUNOO3dCQUNFLG9CQUFvQixFQUFFLFlBQVk7d0JBQ2xDLFNBQVMsRUFBRSxPQUFPO3dCQUNsQixNQUFNLEVBQUUsa0JBQWtCO3dCQUMxQixLQUFLLEVBQUUsUUFBUTtxQkFDaEI7b0JBQ0Q7d0JBQ0Usb0JBQW9CLEVBQUUsV0FBVzt3QkFDakMsU0FBUyxFQUFFLFlBQVk7d0JBQ3ZCLE1BQU0sRUFBRSxhQUFhO3dCQUNyQixLQUFLLEVBQUUsUUFBUTtxQkFDaEI7aUJBQ0Y7YUFDRjtZQUNEO2dCQUNFLFlBQVksRUFBRSxDQUFDLEVB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LEVBQUU7b0JBQ1A7d0JBQ0UsUUFBUSxFQUFFLGVBQWU7d0JBQ3pCLGdCQUFnQixFQUFFLFlBQVk7d0JBQzlCLFlBQVksRUFBRSxZQUFZO3dCQUMxQixJQUFJLEVBQUUsU0FBUztxQkFDaEI7aUJBQ0Y7YUFDRjtZQUNEO2dCQUNFLElBQUksRUFBRSxjQUFjO2dCQUNwQixJQUFJLEVBQUUsUUFBUTtnQkFDZCxPQUFPLEVBQUU7b0JBQ1A7d0JBQ0UsUUFBUSxFQUFFLGVBQWU7d0JBQ3pCLGdCQUFnQixFQUFFLFlBQVk7d0JBQzlCLFlBQVksRUFBRSxZQUFZO3dCQUMxQixJQUFJLEVBQUUsU0FBUztxQkFDaEI7b0JBQ0Q7d0JBQ0UsUUFBUSxFQUFFLGVBQWU7d0JBQ3pCLGdCQUFnQixFQUFFLFlBQVk7d0JBQzlCLFlBQVksRUFBRSxZQUFZO3dCQUMxQixJQUFJLEVBQUUsU0FBUztxQkFDaEI7b0JBQ0Q7d0JBQ0UsUUFBUSxFQUFFLGVBQWU7d0JBQ3pCLGdCQUFnQixFQUFFLFlBQVk7d0JBQzlCLFlBQVksRUFBRSxZQUFZO3dCQUMxQixJQUFJLEVBQUUsU0FBUztxQkFDaEI7aUJBQ0Y7YUFDRjtTQUNGO1FBQ0QsS0FBSyxFQUFFLGFBQWE7UUFDcEIsWUFBWSxFQUFFLFNBQVM7S0FDeEIsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBEZXNjcmliZVJvdXRlVGFibGVzQ29tbWFuZCxcbiAgRGVzY3JpYmVTdWJuZXRzQ29tbWFuZCxcbiAgRGVzY3JpYmVWcGNzQ29tbWFuZCxcbiAgRGVzY3JpYmVWcG5HYXRld2F5c0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lYzInO1xuaW1wb3J0IHsgVnBjTmV0d29ya0NvbnRleHRQcm92aWRlclBsdWdpbiB9IGZyb20gJy4uLy4uL2xpYi9jb250ZXh0LXByb3ZpZGVycy92cGNzJztcbmltcG9ydCB7IE1vY2tTZGtQcm92aWRlciwgbW9ja0VDMkNsaWVudCwgcmVzdG9yZVNka01vY2tzVG9EZWZhdWx0IH0gZnJvbSAnLi4vdXRpbC9tb2NrLXNkayc7XG5cbmJlZm9yZUVhY2goKCkgPT4ge1xuICByZXN0b3JlU2RrTW9ja3NUb0RlZmF1bHQoKTtcbiAgbW9ja0VDMkNsaWVudFxuICAgIC5vbihEZXNjcmliZVZwY3NDb21tYW5kKVxuICAgIC5yZXNvbHZlcyh7XG4gICAgICBWcGNzOiBbeyBWcGNJZDogJ3ZwYy0xMjM0NTY3JywgQ2lkckJsb2NrOiAnMS4xLjEuMS8xNicgfV0sXG4gICAgfSlcbiAgICAub24oRGVzY3JpYmVTdWJuZXRzQ29tbWFuZClcbiAgICAucmVzb2x2ZXMoe1xuICAgICAgU3VibmV0czogW3sgU3VibmV0SWQ6ICdzdWItMTIzNDU2JywgQXZhaWxhYmlsaXR5Wm9uZTogJ2Jlcm11ZGEtdHJpYW5nbGUtMTMzNycsIE1hcFB1YmxpY0lwT25MYXVuY2g6IGZhbHNlIH1dLFxuICAgIH0pXG4gICAgLm9uKERlc2NyaWJlUm91dGVUYWJsZXNDb21tYW5kKVxuICAgIC5yZXNvbHZlcyh7XG4gICAgICBSb3V0ZVRhYmxlczogW1xuICAgICAgICB7XG4gICAgICAgICAgQXNzb2NpYXRpb25zOiBbeyBTdWJuZXRJZDogJ3N1Yi0xMjM0NTYnIH1dLFxuICAgICAgICAgIFJvdXRlVGFibGVJZDogJ3J0Yi0xMjM0NTYnLFxuICAgICAgICAgIFJvdXRlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBEZXN0aW5hdGlvbkNpZHJCbG9jazogJzEuMS4xLjEvMjQnLFxuICAgICAgICAgICAgICBHYXRld2F5SWQ6ICdsb2NhbCcsXG4gICAgICAgICAgICAgIE9yaWdpbjogJ0NyZWF0ZVJvdXRlVGFibGUnLFxuICAgICAgICAgICAgICBTdGF0ZTogJ2FjdGl2ZScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBEZXN0aW5hdGlvbkNpZHJCbG9jazogJzAuMC4wLjAvMCcsXG4gICAgICAgICAgICAgIEdhdGV3YXlJZDogJ2lndy14eHh4eHgnLFxuICAgICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZScsXG4gICAgICAgICAgICAgIFN0YXRlOiAnYWN0aXZlJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIEFzc29jaWF0aW9uczogW3sgU3VibmV0SWQ6ICdzdWItNzg5MDEyJyB9XSxcbiAgICAgICAgICBSb3V0ZVRhYmxlSWQ6ICdydGItNzg5MDEyJyxcbiAgICAgICAgICBSb3V0ZXM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcxLjEuMi4xLzI0JyxcbiAgICAgICAgICAgICAgR2F0ZXdheUlkOiAnbG9jYWwnLFxuICAgICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZVRhYmxlJyxcbiAgICAgICAgICAgICAgU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgICBOYXRHYXRld2F5SWQ6ICduYXQteHh4eHh4JyxcbiAgICAgICAgICAgICAgT3JpZ2luOiAnQ3JlYXRlUm91dGUnLFxuICAgICAgICAgICAgICBTdGF0ZTogJ2FjdGl2ZScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xufSk7XG5cbmNvbnN0IG1vY2tTREsgPSBuZXcgTW9ja1Nka1Byb3ZpZGVyKCk7XG5cbnRlc3QoJ2xvb2tzIHVwIHRoZSByZXF1ZXN0ZWQgKHN5bW1ldHJpYykgVlBDJywgYXN5bmMgKCkgPT4ge1xuICBtb2NrRUMyQ2xpZW50XG4gICAgLm9uKERlc2NyaWJlU3VibmV0c0NvbW1hbmQpXG4gICAgLnJlc29sdmVzKHtcbiAgICAgIFN1Ym5ldHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIFN1Ym5ldElkOiAnc3ViLTEyMzQ1NicsXG4gICAgICAgICAgQXZhaWxhYmlsaXR5Wm9uZTogJ2Jlcm11ZGEtdHJpYW5nbGUtMTMzNycsXG4gICAgICAgICAgTWFwUHVibGljSXBPbkxhdW5jaDogdHJ1ZSxcbiAgICAgICAgICBDaWRyQmxvY2s6ICcxLjEuMS4xLzI0JyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIFN1Ym5ldElkOiAnc3ViLTc4OTAxMicsXG4gICAgICAgICAgQXZhaWxhYmlsaXR5Wm9uZTogJ2Jlcm11ZGEtdHJpYW5nbGUtMTMzNycsXG4gICAgICAgICAgTWFwUHVibGljSXBPbkxhdW5jaDogZmFsc2UsXG4gICAgICAgICAgQ2lkckJsb2NrOiAnMS4xLjIuMS8yNCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pXG4gICAgLm9uKERlc2NyaWJlVnBuR2F0ZXdheXNDb21tYW5kKVxuICAgIC5yZXNvbHZlcyh7IFZwbkdhdGV3YXlzOiBbeyBWcG5HYXRld2F5SWQ6ICdndy1hYmNkZWYnIH1dIH0pO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBuZXcgVnBjTmV0d29ya0NvbnRleHRQcm92aWRlclBsdWdpbihtb2NrU0RLKS5nZXRWYWx1ZSh7XG4gICAgYWNjb3VudDogJzEyMzQ1Njc4OTAxMicsXG4gICAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgICBmaWx0ZXI6IHsgZm9vOiAnYmFyJyB9LFxuICAgIHJldHVybkFzeW1tZXRyaWNTdWJuZXRzOiB0cnVlLFxuICB9KTtcblxuICBleHBlY3QobW9ja0VDMkNsaWVudCkudG9IYXZlUmVjZWl2ZWRDb21tYW5kV2l0aChEZXNjcmliZVZwY3NDb21tYW5kLCB7XG4gICAgRmlsdGVyczogW3sgTmFtZTogJ2ZvbycsIFZhbHVlczogWydiYXInXSB9XSxcbiAgfSk7XG4gIGV4cGVjdChtb2NrRUMyQ2xpZW50KS50b0hhdmVSZWNlaXZlZENvbW1hbmRXaXRoKERlc2NyaWJlU3VibmV0c0NvbW1hbmQsIHtcbiAgICBGaWx0ZXJzOiBbeyBOYW1lOiAndnBjLWlkJywgVmFsdWVzOiBbJ3ZwYy0xMjM0NTY3J10gfV0sXG4gIH0pO1xuICBleHBlY3QobW9ja0VDMkNsaWVudCkudG9IYXZlUmVjZWl2ZWRDb21tYW5kV2l0aChEZXNjcmliZVJvdXRlVGFibGVzQ29tbWFuZCwge1xuICAgIEZpbHRlcnM6IFt7IE5hbWU6ICd2cGMtaWQnLCBWYWx1ZXM6IFsndnBjLTEyMzQ1NjcnXSB9XSxcbiAgfSk7XG4gIGV4cGVjdChtb2NrRUMyQ2xpZW50KS50b0hhdmVSZWNlaXZlZENvbW1hbmRXaXRoKERlc2NyaWJlVnBuR2F0ZXdheXNDb21tYW5kLCB7XG4gICAgRmlsdGVyczogW1xuICAgICAgeyBOYW1lOiAnYXR0YWNobWVudC52cGMtaWQnLCBWYWx1ZXM6IFsndnBjLTEyMzQ1NjcnXSB9LFxuICAgICAgeyBOYW1lOiAnYXR0YWNobWVudC5zdGF0ZScsIFZhbHVlczogWydhdHRhY2hlZCddIH0sXG4gICAgICB7IE5hbWU6ICdzdGF0ZScsIFZhbHVlczogWydhdmFpbGFibGUnXSB9LFxuICAgIF0sXG4gIH0pO1xuICBleHBlY3QocmVzdWx0KS50b0VxdWFsKHtcbiAgICBhdmFpbGFiaWxpdHlab25lczogW10sXG4gICAgdnBjQ2lkckJsb2NrOiAnMS4xLjEuMS8xNicsXG4gICAgc3VibmV0R3JvdXBzOiBbXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICdQdWJsaWMnLFxuICAgICAgICB0eXBlOiAnUHVibGljJyxcbiAgICAgICAgc3VibmV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHN1Ym5ldElkOiAnc3ViLTEyMzQ1NicsXG4gICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lOiAnYmVybXVkYS10cmlhbmdsZS0xMzM3JyxcbiAgICAgICAgICAgIHJvdXRlVGFibGVJZDogJ3J0Yi0xMjM0NTYnLFxuICAgICAgICAgICAgY2lkcjogJzEuMS4xLjEvMjQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnUHJpdmF0ZScsXG4gICAgICAgIHR5cGU6ICdQcml2YXRlJyxcbiAgICAgICAgc3VibmV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHN1Ym5ldElkOiAnc3ViLTc4OTAxMicsXG4gICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lOiAnYmVybXVkYS10cmlhbmdsZS0xMzM3JyxcbiAgICAgICAgICAgIHJvdXRlVGFibGVJZDogJ3J0Yi03ODkwMTInLFxuICAgICAgICAgICAgY2lkcjogJzEuMS4yLjEvMjQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIF0sXG4gICAgdnBjSWQ6ICd2cGMtMTIzNDU2NycsXG4gICAgdnBuR2F0ZXdheUlkOiAnZ3ctYWJjZGVmJ