aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
573 lines • 65.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const AWS = require("aws-sdk-mock");
const vpcs_1 = require("../../lib/context-providers/vpcs");
const mock_sdk_1 = require("../util/mock-sdk");
AWS.setSDK(require.resolve('aws-sdk'));
const mockSDK = new mock_sdk_1.MockSdkProvider();
afterEach(done => {
AWS.restore();
done();
});
test('looks up the requested VPC', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: true },
{ SubnetId: 'sub-789012', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false },
],
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' }],
});
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
});
// THEN
expect(result).toEqual({
vpcId: 'vpc-1234567',
vpcCidrBlock: '1.1.1.1/16',
ownerAccountId: '123456789012',
availabilityZones: ['bermuda-triangle-1337'],
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: ['sub-789012'],
privateSubnetNames: ['Private'],
privateSubnetRouteTableIds: ['rtb-789012'],
publicSubnetIds: ['sub-123456'],
publicSubnetNames: ['Public'],
publicSubnetRouteTableIds: ['rtb-123456'],
vpnGatewayId: 'gw-abcdef',
subnetGroups: undefined,
});
});
test('throws when no such VPC is found', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
AWS.mock('EC2', 'describeVpcs', (params, cb) => {
expect(params.Filters).toEqual([{ Name: 'foo', Values: ['bar'] }]);
return cb(null, {});
});
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
})).rejects.toThrow(/Could not find any VPCs matching/);
});
test('throws when subnet with subnetGroupNameTag not found', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: true },
{ SubnetId: 'sub-789012', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false },
],
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' }],
});
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
subnetGroupNameTag: 'DOES_NOT_EXIST',
filter,
})).rejects.toThrow(/Invalid subnetGroupNameTag: Subnet .* does not have an associated tag with Key='DOES_NOT_EXIST'/);
});
test('does not throw when subnet with subnetGroupNameTag is found', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: true, Tags: [{ Key: 'DOES_EXIST', Value: 'SubnetName1' }] },
{ SubnetId: 'sub-789012', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false, Tags: [{ Key: 'DOES_EXIST', Value: 'SubnetName2' }] },
],
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' }],
});
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
subnetGroupNameTag: 'DOES_EXIST',
filter,
});
// THEN
expect(result).toEqual({
vpcId: 'vpc-1234567',
vpcCidrBlock: '1.1.1.1/16',
ownerAccountId: '123456789012',
availabilityZones: ['bermuda-triangle-1337'],
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: ['sub-789012'],
privateSubnetNames: ['SubnetName2'],
privateSubnetRouteTableIds: ['rtb-789012'],
publicSubnetIds: ['sub-123456'],
publicSubnetNames: ['SubnetName1'],
publicSubnetRouteTableIds: ['rtb-123456'],
vpnGatewayId: 'gw-abcdef',
subnetGroups: undefined,
});
});
test('throws when multiple VPCs are found', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
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(provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
})).rejects.toThrow(/Found 2 VPCs matching/);
});
test('uses the VPC main route table when a subnet has no specific association', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: true },
{ SubnetId: 'sub-789012', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false },
],
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' }],
});
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
});
// THEN
expect(result).toEqual({
vpcId: 'vpc-1234567',
vpcCidrBlock: '1.1.1.1/16',
ownerAccountId: '123456789012',
availabilityZones: ['bermuda-triangle-1337'],
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: ['sub-789012'],
privateSubnetNames: ['Private'],
privateSubnetRouteTableIds: ['rtb-789012'],
publicSubnetIds: ['sub-123456'],
publicSubnetNames: ['Public'],
publicSubnetRouteTableIds: ['rtb-123456'],
vpnGatewayId: 'gw-abcdef',
subnetGroups: undefined,
});
});
test('Recognize public subnet by route table', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
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: '10.0.1.0/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
GatewayId: 'igw-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
});
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
});
// THEN
expect(result).toEqual({
vpcId: 'vpc-1234567',
vpcCidrBlock: '1.1.1.1/16',
ownerAccountId: '123456789012',
availabilityZones: ['bermuda-triangle-1337'],
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: ['sub-123456'],
publicSubnetNames: ['Public'],
publicSubnetRouteTableIds: ['rtb-123456'],
vpnGatewayId: undefined,
subnetGroups: undefined,
});
});
test('Recognize private subnet by route table with NAT Gateway', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
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: '10.0.1.0/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
NatGatewayId: 'nat-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
});
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
});
// THEN
expect(result).toEqual({
vpcId: 'vpc-1234567',
vpcCidrBlock: '1.1.1.1/16',
ownerAccountId: '123456789012',
availabilityZones: ['bermuda-triangle-1337'],
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: ['sub-123456'],
privateSubnetNames: ['Private'],
privateSubnetRouteTableIds: ['rtb-123456'],
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
vpnGatewayId: undefined,
subnetGroups: undefined,
});
});
test('Recognize private subnet by route table with Transit Gateway', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
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: '10.0.1.0/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
{
DestinationCidrBlock: '0.0.0.0/0',
TransitGatewayId: 'tgw-xxxxxx',
Origin: 'CreateRoute',
State: 'active',
},
],
},
],
});
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
});
// THEN
expect(result).toEqual({
vpcId: 'vpc-1234567',
vpcCidrBlock: '1.1.1.1/16',
ownerAccountId: '123456789012',
availabilityZones: ['bermuda-triangle-1337'],
isolatedSubnetIds: undefined,
isolatedSubnetNames: undefined,
isolatedSubnetRouteTableIds: undefined,
privateSubnetIds: ['sub-123456'],
privateSubnetNames: ['Private'],
privateSubnetRouteTableIds: ['rtb-123456'],
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
vpnGatewayId: undefined,
subnetGroups: undefined,
});
});
test('Recognize isolated subnet by route table', async () => {
// GIVEN
const filter = { foo: 'bar' };
const provider = new vpcs_1.VpcNetworkContextProviderPlugin(mockSDK);
mockVpcLookup({
subnets: [
{ SubnetId: 'sub-123456', AvailabilityZone: 'bermuda-triangle-1337', MapPublicIpOnLaunch: false },
],
routeTables: [
{
Associations: [{ SubnetId: 'sub-123456' }],
RouteTableId: 'rtb-123456',
Routes: [
{
DestinationCidrBlock: '10.0.1.0/24',
GatewayId: 'local',
Origin: 'CreateRouteTable',
State: 'active',
},
],
},
],
});
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
filter,
});
// THEN
expect(result).toEqual({
vpcId: 'vpc-1234567',
vpcCidrBlock: '1.1.1.1/16',
ownerAccountId: '123456789012',
availabilityZones: ['bermuda-triangle-1337'],
isolatedSubnetIds: ['sub-123456'],
isolatedSubnetNames: ['Isolated'],
isolatedSubnetRouteTableIds: ['rtb-123456'],
privateSubnetIds: undefined,
privateSubnetNames: undefined,
privateSubnetRouteTableIds: undefined,
publicSubnetIds: undefined,
publicSubnetNames: undefined,
publicSubnetRouteTableIds: undefined,
vpnGatewayId: undefined,
subnetGroups: 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', OwnerId: '123456789012' }] });
});
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidnBjcy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidnBjcy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBRUEsb0NBQW9DO0FBQ3BDLDJEQUFtRjtBQUNuRiwrQ0FBbUQ7QUFFbkQsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7QUFFdkMsTUFBTSxPQUFPLEdBQUcsSUFBSSwwQkFBZSxFQUFFLENBQUM7QUFJdEMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFO0lBQ2YsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2QsSUFBSSxFQUFFLENBQUM7QUFDVCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLElBQUksRUFBRTtJQUM1QyxRQUFRO0lBQ1IsTUFBTSxNQUFNLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDOUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxzQ0FBK0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUU5RCxhQUFhLENBQUM7UUFDWixPQUFPLEVBQUU7WUFDUCxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsdUJBQXVCLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFO1lBQ2hHLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBRSxtQkFBbUIsRUFBRSxLQUFLLEVBQUU7U0FDbEc7UUFDRCxXQUFXLEVBQUU7WUFDWDtnQkFDRSxZQUFZLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsQ0FBQztnQkFDMUMsWUFBWSxFQUFFLFlBQVk7Z0JBQzFCLE1BQU0sRUFBRTtvQkFDTjt3QkFDRSxvQkFBb0IsRUFBRSxZQUFZO3dCQUNsQyxTQUFTLEVBQUUsT0FBTzt3QkFDbEIsTUFBTSxFQUFFLGtCQUFrQjt3QkFDMUIsS0FBSyxFQUFFLFFB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QUFDLEVBQUU7U0FDekMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3hELENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9vcmRlciAqL1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGstbW9jayc7XG5pbXBvcnQgeyBWcGNOZXR3b3JrQ29udGV4dFByb3ZpZGVyUGx1Z2luIH0gZnJvbSAnLi4vLi4vbGliL2NvbnRleHQtcHJvdmlkZXJzL3ZwY3MnO1xuaW1wb3J0IHsgTW9ja1Nka1Byb3ZpZGVyIH0gZnJvbSAnLi4vdXRpbC9tb2NrLXNkayc7XG5cbkFXUy5zZXRTREsocmVxdWlyZS5yZXNvbHZlKCdhd3Mtc2RrJykpO1xuXG5jb25zdCBtb2NrU0RLID0gbmV3IE1vY2tTZGtQcm92aWRlcigpO1xuXG50eXBlIEF3c0NhbGxiYWNrPFQ+ID0gKGVycjogRXJyb3IgfCBudWxsLCB2YWw6IFQpID0+IHZvaWQ7XG5cbmFmdGVyRWFjaChkb25lID0+IHtcbiAgQVdTLnJlc3RvcmUoKTtcbiAgZG9uZSgpO1xufSk7XG5cbnRlc3QoJ2xvb2tzIHVwIHRoZSByZXF1ZXN0ZWQgVlBDJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25zdCBmaWx0ZXIgPSB7IGZvbzogJ2JhcicgfTtcbiAgY29uc3QgcHJvdmlkZXIgPSBuZXcgVnBjTmV0d29ya0NvbnRleHRQcm92aWRlclBsdWdpbihtb2NrU0RLKTtcblxuICBtb2NrVnBjTG9va3VwKHtcbiAgICBzdWJuZXRzOiBbXG4gICAgICB7IFN1Ym5ldElkOiAnc3ViLTEyMzQ1NicsIEF2YWlsYWJpbGl0eVpvbmU6ICdiZXJtdWRhLXRyaWFuZ2xlLTEzMzcnLCBNYXBQdWJsaWNJcE9uTGF1bmNoOiB0cnVlIH0sXG4gICAgICB7IFN1Ym5ldElkOiAnc3ViLTc4OTAxMicsIEF2YWlsYWJpbGl0eVpvbmU6ICdiZXJtdWRhLXRyaWFuZ2xlLTEzMzcnLCBNYXBQdWJsaWNJcE9uTGF1bmNoOiBmYWxzZSB9LFxuICAgIF0sXG4gICAgcm91dGVUYWJsZXM6IFtcbiAgICAgIHtcbiAgICAgICAgQXNzb2NpYXRpb25zOiBbeyBTdWJuZXRJZDogJ3N1Yi0xMjM0NTYnIH1dLFxuICAgICAgICBSb3V0ZVRhYmxlSWQ6ICdydGItMTIzNDU2JyxcbiAgICAgICAgUm91dGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcxLjEuMS4xLzI0JyxcbiAgICAgICAgICAgIEdhdGV3YXlJZDogJ2xvY2FsJyxcbiAgICAgICAgICAgIE9yaWdpbjogJ0NyZWF0ZVJvdXRlVGFibGUnLFxuICAgICAgICAgICAgU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgR2F0ZXdheUlkOiAnaWd3LXh4eHh4eCcsXG4gICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZScsXG4gICAgICAgICAgICBTdGF0ZTogJ2FjdGl2ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIEFzc29jaWF0aW9uczogW3sgU3VibmV0SWQ6ICdzdWItNzg5MDEyJyB9XSxcbiAgICAgICAgUm91dGVUYWJsZUlkOiAncnRiLTc4OTAxMicsXG4gICAgICAgIFJvdXRlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIERlc3RpbmF0aW9uQ2lkckJsb2NrOiAnMS4xLjIuMS8yNCcsXG4gICAgICAgICAgICBHYXRld2F5SWQ6ICdsb2NhbCcsXG4gICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZVRhYmxlJyxcbiAgICAgICAgICAgIFN0YXRlOiAnYWN0aXZlJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIERlc3RpbmF0aW9uQ2lkckJsb2NrOiAnMC4wLjAuMC8wJyxcbiAgICAgICAgICAgIE5hdEdhdGV3YXlJZDogJ25hdC14eHh4eHgnLFxuICAgICAgICAgICAgT3JpZ2luOiAnQ3JlYXRlUm91dGUnLFxuICAgICAgICAgICAgU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIF0sXG4gICAgdnBuR2F0ZXdheXM6IFt7IFZwbkdhdGV3YXlJZDogJ2d3LWFiY2RlZicgfV0sXG5cbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm92aWRlci5nZXRWYWx1ZSh7XG4gICAgYWNjb3VudDogJzEyMzQnLFxuICAgIHJlZ2lvbjogJ3VzLWVhc3QtMScsXG4gICAgZmlsdGVyLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChyZXN1bHQpLnRvRXF1YWwoe1xuICAgIHZwY0lkOiAndnBjLTEyMzQ1NjcnLFxuICAgIHZwY0NpZHJCbG9jazogJzEuMS4xLjEvMTYnLFxuICAgIG93bmVyQWNjb3VudElkOiAnMTIzNDU2Nzg5MDEyJyxcbiAgICBhdmFpbGFiaWxpdHlab25lczogWydiZXJtdWRhLXRyaWFuZ2xlLTEzMzcnXSxcbiAgICBpc29sYXRlZFN1Ym5ldElkczogdW5kZWZpbmVkLFxuICAgIGlzb2xhdGVkU3VibmV0TmFtZXM6IHVuZGVmaW5lZCxcbiAgICBpc29sYXRlZFN1Ym5ldFJvdXRlVGFibGVJZHM6IHVuZGVmaW5lZCxcbiAgICBwcml2YXRlU3VibmV0SWRzOiBbJ3N1Yi03ODkwMTInXSxcbiAgICBwcml2YXRlU3VibmV0TmFtZXM6IFsnUHJpdmF0ZSddLFxuICAgIHByaXZhdGVTdWJuZXRSb3V0ZVRhYmxlSWRzOiBbJ3J0Yi03ODkwMTInXSxcbiAgICBwdWJsaWNTdWJuZXRJZHM6IFsnc3ViLTEyMzQ1NiddLFxuICAgIHB1YmxpY1N1Ym5ldE5hbWVzOiBbJ1B1YmxpYyddLFxuICAgIHB1YmxpY1N1Ym5ldFJvdXRlVGFibGVJZHM6IFsncnRiLTEyMzQ1NiddLFxuICAgIHZwbkdhdGV3YXlJZDogJ2d3LWFiY2RlZicsXG4gICAgc3VibmV0R3JvdXBzOiB1bmRlZmluZWQsXG4gIH0pO1xufSk7XG5cbnRlc3QoJ3Rocm93cyB3aGVuIG5vIHN1Y2ggVlBDIGlzIGZvdW5kJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25zdCBmaWx0ZXIgPSB7IGZvbzogJ2JhcicgfTtcbiAgY29uc3QgcHJvdmlkZXIgPSBuZXcgVnBjTmV0d29ya0NvbnRleHRQcm92aWRlclBsdWdpbihtb2NrU0RLKTtcblxuICBBV1MubW9jaygnRUMyJywgJ2Rlc2NyaWJlVnBjcycsIChwYXJhbXM6IGF3cy5FQzIuRGVzY3JpYmVWcGNzUmVxdWVzdCwgY2I6IEF3c0NhbGxiYWNrPGF3cy5FQzIuRGVzY3JpYmVWcGNzUmVzdWx0PikgPT4ge1xuICAgIGV4cGVjdChwYXJhbXMuRmlsdGVycykudG9FcXVhbChbeyBOYW1lOiAnZm9vJywgVmFsdWVzOiBbJ2JhciddIH1dKTtcbiAgICByZXR1cm4gY2IobnVsbCwge30pO1xuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGV4cGVjdChwcm92aWRlci5nZXRWYWx1ZSh7XG4gICAgYWNjb3VudDogJzEyMzQnLFxuICAgIHJlZ2lvbjogJ3VzLWVhc3QtMScsXG4gICAgZmlsdGVyLFxuICB9KSkucmVqZWN0cy50b1Rocm93KC9Db3VsZCBub3QgZmluZCBhbnkgVlBDcyBtYXRjaGluZy8pO1xufSk7XG5cbnRlc3QoJ3Rocm93cyB3aGVuIHN1Ym5ldCB3aXRoIHN1Ym5ldEdyb3VwTmFtZVRhZyBub3QgZm91bmQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGNvbnN0IGZpbHRlciA9IHsgZm9vOiAnYmFyJyB9O1xuICBjb25zdCBwcm92aWRlciA9IG5ldyBWcGNOZXR3b3JrQ29udGV4dFByb3ZpZGVyUGx1Z2luKG1vY2tTREspO1xuXG4gIG1vY2tWcGNMb29rdXAoe1xuICAgIHN1Ym5ldHM6IFtcbiAgICAgIHsgU3VibmV0SWQ6ICdzdWItMTIzNDU2JywgQXZhaWxhYmlsaXR5Wm9uZTogJ2Jlcm11ZGEtdHJpYW5nbGUtMTMzNycsIE1hcFB1YmxpY0lwT25MYXVuY2g6IHRydWUgfSxcbiAgICAgIHsgU3VibmV0SWQ6ICdzdWItNzg5MDEyJywgQXZhaWxhYmlsaXR5Wm9uZTogJ2Jlcm11ZGEtdHJpYW5nbGUtMTMzNycsIE1hcFB1YmxpY0lwT25MYXVuY2g6IGZhbHNlIH0sXG4gICAgXSxcbiAgICByb3V0ZVRhYmxlczogW1xuICAgICAge1xuICAgICAgICBBc3NvY2lhdGlvbnM6IFt7IFN1Ym5ldElkOiAnc3ViLTEyMzQ1NicgfV0sXG4gICAgICAgIFJvdXRlVGFibGVJZDogJ3J0Yi0xMjM0NTYnLFxuICAgICAgICBSb3V0ZXM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBEZXN0aW5hdGlvbkNpZHJCbG9jazogJzEuMS4xLjEvMjQnLFxuICAgICAgICAgICAgR2F0ZXdheUlkOiAnbG9jYWwnLFxuICAgICAgICAgICAgT3JpZ2luOiAnQ3JlYXRlUm91dGVUYWJsZScsXG4gICAgICAgICAgICBTdGF0ZTogJ2FjdGl2ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBEZXN0aW5hdGlvbkNpZHJCbG9jazogJzAuMC4wLjAvMCcsXG4gICAgICAgICAgICBHYXRld2F5SWQ6ICdpZ3cteHh4eHh4JyxcbiAgICAgICAgICAgIE9yaWdpbjogJ0NyZWF0ZVJvdXRlJyxcbiAgICAgICAgICAgIFN0YXRlOiAnYWN0aXZlJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgQXNzb2NpYXRpb25zOiBbeyBTdWJuZXRJZDogJ3N1Yi03ODkwMTInIH1dLFxuICAgICAgICBSb3V0ZVRhYmxlSWQ6ICdydGItNzg5MDEyJyxcbiAgICAgICAgUm91dGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcxLjEuMi4xLzI0JyxcbiAgICAgICAgICAgIEdhdGV3YXlJZDogJ2xvY2FsJyxcbiAgICAgICAgICAgIE9yaWdpbjogJ0NyZWF0ZVJvdXRlVGFibGUnLFxuICAgICAgICAgICAgU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgTmF0R2F0ZXdheUlkOiAnbmF0LXh4eHh4eCcsXG4gICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZScsXG4gICAgICAgICAgICBTdGF0ZTogJ2FjdGl2ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgXSxcbiAgICB2cG5HYXRld2F5czogW3sgVnBuR2F0ZXdheUlkOiAnZ3ctYWJjZGVmJyB9XSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBleHBlY3QocHJvdmlkZXIuZ2V0VmFsdWUoe1xuICAgIGFjY291bnQ6ICcxMjM0JyxcbiAgICByZWdpb246ICd1cy1lYXN0LTEnLFxuICAgIHN1Ym5ldEdyb3VwTmFtZVRhZzogJ0RPRVNfTk9UX0VYSVNUJyxcbiAgICBmaWx0ZXIsXG4gIH0pKS5yZWplY3RzLnRvVGhyb3coL0ludmFsaWQgc3VibmV0R3JvdXBOYW1lVGFnOiBTdWJuZXQgLiogZG9lcyBub3QgaGF2ZSBhbiBhc3NvY2lhdGVkIHRhZyB3aXRoIEtleT0nRE9FU19OT1RfRVhJU1QnLyk7XG59KTtcblxudGVzdCgnZG9lcyBub3QgdGhyb3cgd2hlbiBzdWJuZXQgd2l0aCBzdWJuZXRHcm91cE5hbWVUYWcgaXMgZm91bmQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGNvbnN0IGZpbHRlciA9IHsgZm9vOiAnYmFyJyB9O1xuICBjb25zdCBwcm92aWRlciA9IG5ldyBWcGNOZXR3b3JrQ29udGV4dFByb3ZpZGVyUGx1Z2luKG1vY2tTREspO1xuXG4gIG1vY2tWcGNMb29rdXAoe1xuICAgIHN1Ym5ldHM6IFtcbiAgICAgIHsgU3VibmV0SWQ6ICdzdWItMTIzNDU2JywgQXZhaWxhYmlsaXR5Wm9uZTogJ2Jlcm11ZGEtdHJpYW5nbGUtMTMzNycsIE1hcFB1YmxpY0lwT25MYXVuY2g6IHRydWUsIFRhZ3M6IFt7IEtleTogJ0RPRVNfRVhJU1QnLCBWYWx1ZTogJ1N1Ym5ldE5hbWUxJyB9XSB9LFxuICAgICAgeyBTdWJuZXRJZDogJ3N1Yi03ODkwMTInLCBBdmFpbGFiaWxpdHlab25lOiAnYmVybXVkYS10cmlhbmdsZS0xMzM3JywgTWFwUHVibGljSXBPbkxhdW5jaDogZmFsc2UsIFRhZ3M6IFt7IEtleTogJ0RPRVNfRVhJU1QnLCBWYWx1ZTogJ1N1Ym5ldE5hbWUyJyB9XSB9LFxuICAgIF0sXG4gICAgcm91dGVUYWJsZXM6IFtcbiAgICAgIHtcbiAgICAgICAgQXNzb2NpYXRpb25zOiBbeyBTdWJuZXRJZDogJ3N1Yi0xMjM0NTYnIH1dLFxuICAgICAgICBSb3V0ZVRhYmxlSWQ6ICdydGItMTIzNDU2JyxcbiAgICAgICAgUm91dGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcxLjEuMS4xLzI0JyxcbiAgICAgICAgICAgIEdhdGV3YXlJZDogJ2xvY2FsJyxcbiAgICAgICAgICAgIE9yaWdpbjogJ0NyZWF0ZVJvdXRlVGFibGUnLFxuICAgICAgICAgICAgU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgRGVzdGluYXRpb25DaWRyQmxvY2s6ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgR2F0ZXdheUlkOiAnaWd3LXh4eHh4eCcsXG4gICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZScsXG4gICAgICAgICAgICBTdGF0ZTogJ2FjdGl2ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIEFzc29jaWF0aW9uczogW3sgU3VibmV0SWQ6ICdzdWItNzg5MDEyJyB9XSxcbiAgICAgICAgUm91dGVUYWJsZUlkOiAncnRiLTc4OTAxMicsXG4gICAgICAgIFJvdXRlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIERlc3RpbmF0aW9uQ2lkckJsb2NrOiAnMS4xLjIuMS8yNCcsXG4gICAgICAgICAgICBHYXRld2F5SWQ6ICdsb2NhbCcsXG4gICAgICAgICAgICBPcmlnaW46ICdDcmVhdGVSb3V0ZVRhYmxlJyxcbiAgICAgICAgICAgIFN0YXRlOiAnYWN0aXZlJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIERlc3RpbmF0aW9uQ2lkckJsb2NrOiAnMC4wLjAuMC8wJyxcbiAgICAgICAgICAgIE5hdEdhdGV3YXlJZDogJ25hdC14eHh4eHgnLFxuICAgICAgICAgICAgT3JpZ2luOiAnQ3JlYXRlUm91dGUnLFxuICAgICAgICAgICAgU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIF0sXG4gICAgdnBuR2F0ZXdheXM6IFt7IFZwbkdhdGV3YXlJZDogJ2d3LWFiY2RlZicgfV0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcHJvdmlkZXIuZ2V0VmFsdWUoe1xuICAgIGFjY291bnQ6ICcxMjM0JyxcbiAgICByZWdpb246ICd1cy1lYXN0LTEnLFxuICAgIHN1Ym5ldEdyb3VwTmFtZVRhZzogJ0RPRVNfRVhJU1QnLFxuICAgIGZpbHRlcixcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QocmVzdWx0KS50b0VxdWFsKHtcbiAgICB2cGNJZDogJ3ZwYy0xMjM0NTY3JyxcbiAgICB2cGNDaWRyQmxvY2s6ICcxLjEuMS4xLzE2JyxcbiAgICBvd25lckFjY291bnRJZDogJzEyMzQ1Njc4OTAxMicsXG4gICAgYXZhaWxhYmlsaXR5Wm9uZXM6IFsnYmVybXVkYS10cmlhbmdsZS0xMzM3J10sXG4gICAgaXNvbGF0ZWRTdWJuZXRJZHM6IHVuZGVmaW5lZCxcbiAgICBpc29sYXRlZFN1Ym5ldE5hbWVzOiB1bmRlZmluZWQsXG4gICAgaXNvbGF0ZWRTdWJuZXRSb3V0ZVRhYmxlSWRzOiB1bmRlZmluZWQsXG4gICAgcHJpdmF0ZVN1