UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

679 lines 72.6 kB
"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