aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
739 lines • 89.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema");
const client_elastic_load_balancing_v2_1 = require("@aws-sdk/client-elastic-load-balancing-v2");
const api_1 = require("../../lib/api");
const load_balancers_1 = require("../../lib/context-providers/load-balancers");
const mock_sdk_1 = require("../util/mock-sdk");
const mockSDK = new (class extends mock_sdk_1.MockSdkProvider {
forEnvironment() {
return Promise.resolve({ sdk: new api_1.SDK(mock_sdk_1.FAKE_CREDENTIAL_CHAIN, mockSDK.defaultRegion, {}), didAssumeRole: false });
}
})();
beforeEach(() => {
(0, mock_sdk_1.restoreSdkMocksToDefault)();
});
describe('load balancer context provider plugin', () => {
test('errors when no matches are found', async () => {
// GIVEN
const provider = new load_balancers_1.LoadBalancerContextProviderPlugin(mockSDK);
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerArn: 'arn:load-balancer1',
})).rejects.toThrow('No load balancers found matching {"account":"1234","region":"us-east-1","loadBalancerType":"application","loadBalancerArn":"arn:load-balancer1"}');
});
test('errors when multiple load balancers match', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer1',
DNSName: 'dns1.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
Type: 'application',
},
{
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer2',
DNSName: 'dns2.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer1',
Tags: [{ Key: 'some', Value: 'tag' }],
},
{
ResourceArn: 'arn:load-balancer2',
Tags: [{ Key: 'some', Value: 'tag' }],
},
],
});
const provider = new load_balancers_1.LoadBalancerContextProviderPlugin(mockSDK);
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerTags: [{ key: 'some', value: 'tag' }],
})).rejects.toThrow('Multiple load balancers found matching {"account":"1234","region":"us-east-1","loadBalancerType":"application","loadBalancerTags":[{"key":"some","value":"tag"}]} - please provide more specific criteria');
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeTagsCommand, {
ResourceArns: ['arn:load-balancer1', 'arn:load-balancer2'],
});
});
test('looks up by arn', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand).resolves({
LoadBalancers: [
{
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer1',
DNSName: 'dns.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
Type: 'application',
},
],
});
const provider = new load_balancers_1.LoadBalancerContextProviderPlugin(mockSDK);
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerArn: 'arn:load-balancer1',
});
// THEN
expect(result.ipAddressType).toEqual('ipv4');
expect(result.loadBalancerArn).toEqual('arn:load-balancer1');
expect(result.loadBalancerCanonicalHostedZoneId).toEqual('Z1234');
expect(result.loadBalancerDnsName).toEqual('dns.example.com');
expect(result.securityGroupIds).toEqual(['sg-1234']);
expect(result.vpcId).toEqual('vpc-1234');
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand, {
LoadBalancerArns: ['arn:load-balancer1'],
});
});
test('looks up by tags', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer1',
DNSName: 'dns1.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
Type: 'application',
},
{
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer2',
DNSName: 'dns2.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer1',
Tags: [{ Key: 'some', Value: 'tag' }],
},
{
ResourceArn: 'arn:load-balancer2',
Tags: [
{ Key: 'some', Value: 'tag' },
{ Key: 'second', Value: 'tag2' },
],
},
],
});
const provider = new load_balancers_1.LoadBalancerContextProviderPlugin(mockSDK);
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerTags: [
{ key: 'some', value: 'tag' },
{ key: 'second', value: 'tag2' },
],
});
expect(result.loadBalancerArn).toEqual('arn:load-balancer2');
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeTagsCommand, {
ResourceArns: ['arn:load-balancer1', 'arn:load-balancer2'],
});
});
test('looks up by tags - query by subset', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer2',
DNSName: 'dns2.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer2',
Tags: [
// Load balancer has two tags...
{ Key: 'some', Value: 'tag' },
{ Key: 'second', Value: 'tag2' },
],
},
],
});
const provider = new load_balancers_1.LoadBalancerContextProviderPlugin(mockSDK);
// WHEN
const result = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerTags: [
// ...but we are querying for only one of them
{ key: 'second', value: 'tag2' },
],
});
expect(result.loadBalancerArn).toEqual('arn:load-balancer2');
});
test('filters by type', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
IpAddressType: 'ipv4',
Type: 'network',
LoadBalancerArn: 'arn:load-balancer1',
DNSName: 'dns1.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
},
{
IpAddressType: 'ipv4',
Type: 'application',
LoadBalancerArn: 'arn:load-balancer2',
DNSName: 'dns2.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer1',
Tags: [{ Key: 'some', Value: 'tag' }],
},
{
ResourceArn: 'arn:load-balancer2',
Tags: [{ Key: 'some', Value: 'tag' }],
},
],
});
const provider = new load_balancers_1.LoadBalancerContextProviderPlugin(mockSDK);
// WHEN
const loadBalancer = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerTags: [{ key: 'some', value: 'tag' }],
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
});
expect(loadBalancer.loadBalancerArn).toEqual('arn:load-balancer2');
});
});
describe('load balancer listener context provider plugin', () => {
test('errors when no associated load balancers match', async () => {
// GIVEN
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerTags: [{ key: 'some', value: 'tag' }],
})).rejects.toThrow('No associated load balancers found for load balancer listener query {"account":"1234","region":"us-east-1","loadBalancerType":"application","loadBalancerTags":[{"key":"some","value":"tag"}]}');
});
test('errors when no listeners match', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
LoadBalancerArn: 'arn:load-balancer',
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolves({
Listeners: [
{
LoadBalancerArn: 'arn:load-balancer',
ListenerArn: 'arn:listener',
Port: 80,
Protocol: 'HTTP',
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerArn: 'arn:load-balancer',
listenerPort: 443,
listenerProtocol: cloud_assembly_schema_1.LoadBalancerListenerProtocol.HTTPS,
})).rejects.toThrow('No load balancer listeners found matching {"account":"1234","region":"us-east-1","loadBalancerType":"application","loadBalancerArn":"arn:load-balancer","listenerPort":443,"listenerProtocol":"HTTPS"}');
});
test('errors when multiple listeners match', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
LoadBalancerArn: 'arn:load-balancer',
Type: 'application',
},
{
LoadBalancerArn: 'arn:load-balancer2',
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer',
Tags: [{ Key: 'some', Value: 'tag' }],
},
{
ResourceArn: 'arn:load-balancer2',
Tags: [{ Key: 'some', Value: 'tag' }],
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolves({
Listeners: [
{
LoadBalancerArn: 'arn:load-balancer',
ListenerArn: 'arn:listener',
Port: 80,
Protocol: 'HTTP',
},
{
LoadBalancerArn: 'arn:load-balancer2',
ListenerArn: 'arn:listener2',
Port: 80,
Protocol: 'HTTP',
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerTags: [{ key: 'some', value: 'tag' }],
listenerPort: 80,
listenerProtocol: cloud_assembly_schema_1.LoadBalancerListenerProtocol.HTTP,
})).rejects.toThrow('Multiple load balancer listeners found matching {"account":"1234","region":"us-east-1","loadBalancerType":"application","loadBalancerTags":[{"key":"some","value":"tag"}],"listenerPort":80,"listenerProtocol":"HTTP"} - please provide more specific criteria');
});
test('looks up by listener arn', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
LoadBalancerArn: 'arn:load-balancer-arn',
SecurityGroups: ['sg-1234', 'sg-2345'],
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolves({
Listeners: [
{
ListenerArn: 'arn:listener-arn',
LoadBalancerArn: 'arn:load-balancer-arn',
Port: 999,
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
const listener = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
listenerArn: 'arn:listener-arn',
});
// THEN
expect(listener.listenerArn).toEqual('arn:listener-arn');
expect(listener.listenerPort).toEqual(999);
expect(listener.securityGroupIds).toEqual(['sg-1234', 'sg-2345']);
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand, {
LoadBalancerArns: ['arn:load-balancer-arn'],
});
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeListenersCommand, {
ListenerArns: ['arn:listener-arn'],
});
});
test('looks up by associated load balancer arn', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
LoadBalancerArn: 'arn:load-balancer-arn1',
SecurityGroups: ['sg-1234'],
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolves({
Listeners: [
{
// This one
ListenerArn: 'arn:listener-arn1',
LoadBalancerArn: 'arn:load-balancer-arn1',
Port: 80,
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
const listener = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerArn: 'arn:load-balancer-arn1',
});
// THEN
expect(listener.listenerArn).toEqual('arn:listener-arn1');
expect(listener.listenerPort).toEqual(80);
expect(listener.securityGroupIds).toEqual(['sg-1234']);
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand, {
LoadBalancerArns: ['arn:load-balancer-arn1'],
});
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeListenersCommand, {
LoadBalancerArn: 'arn:load-balancer-arn1',
});
});
test('looks up by associated load balancer tags', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
// This one should have the wrong tags
LoadBalancerArn: 'arn:load-balancer-arn1',
SecurityGroups: ['sg-1234', 'sg-2345'],
Type: 'application',
},
{
// Expecting this one
LoadBalancerArn: 'arn:load-balancer-arn2',
SecurityGroups: ['sg-3456', 'sg-4567'],
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolves({
Listeners: [
{
// This one
ListenerArn: 'arn:listener-arn1',
LoadBalancerArn: 'arn:load-balancer-arn2',
Port: 80,
},
{
ListenerArn: 'arn:listener-arn2',
LoadBalancerArn: 'arn:load-balancer-arn2',
Port: 999,
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer-arn1',
Tags: [],
},
{
// Expecting this one
ResourceArn: 'arn:load-balancer-arn2',
Tags: [{ Key: 'some', Value: 'tag' }],
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
const listener = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerTags: [{ key: 'some', value: 'tag' }],
listenerPort: 999,
});
// THEN
expect(listener.listenerArn).toEqual('arn:listener-arn2');
expect(listener.listenerPort).toEqual(999);
expect(listener.securityGroupIds).toEqual(['sg-3456', 'sg-4567']);
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand, {
LoadBalancerArns: undefined,
});
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeListenersCommand, {
LoadBalancerArn: 'arn:load-balancer-arn2',
});
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeTagsCommand, {
ResourceArns: ['arn:load-balancer-arn1', 'arn:load-balancer-arn2'],
});
});
test('looks up by listener port and protocol', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
// Shouldn't have any matching listeners
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer1',
DNSName: 'dns1.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-1234'],
VpcId: 'vpc-1234',
Type: 'application',
},
{
// Should have a matching listener
IpAddressType: 'ipv4',
LoadBalancerArn: 'arn:load-balancer2',
DNSName: 'dns2.example.com',
CanonicalHostedZoneId: 'Z1234',
SecurityGroups: ['sg-2345'],
VpcId: 'vpc-1234',
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer1',
Tags: [{ Key: 'some', Value: 'tag' }],
},
{
ResourceArn: 'arn:load-balancer2',
Tags: [{ Key: 'some', Value: 'tag' }],
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolvesOnce({
Listeners: [
{
// Wrong port, wrong protocol => no match
ListenerArn: 'arn:listener-arn1',
LoadBalancerArn: 'arn:load-balancer1',
Protocol: 'HTTP',
Port: 80,
},
{
// Wrong protocol, right port => no match
ListenerArn: 'arn:listener-arn3',
LoadBalancerArn: 'arn:load-balancer1',
Protocol: 'HTTPS',
Port: 443,
},
{
// Wrong port, right protocol => no match
ListenerArn: 'arn:listener-arn4',
LoadBalancerArn: 'arn:load-balancer1',
Protocol: 'TCP',
Port: 999,
},
],
})
.resolvesOnce({
Listeners: [
{
// Wrong port, wrong protocol => no match
ListenerArn: 'arn:listener-arn5',
LoadBalancerArn: 'arn:load-balancer2',
Protocol: 'HTTP',
Port: 80,
},
{
// Right port, right protocol => match
ListenerArn: 'arn:listener-arn6',
LoadBalancerArn: 'arn:load-balancer2',
Port: 443,
Protocol: 'TCP',
},
],
});
mock_sdk_1.mockElasticLoadBalancingV2Client.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand).resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer1',
Tags: [{ Key: 'some', Value: 'tag' }],
},
{
ResourceArn: 'arn:load-balancer2',
Tags: [{ Key: 'some', Value: 'tag' }],
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
const listener = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.APPLICATION,
loadBalancerTags: [{ key: 'some', value: 'tag' }],
listenerProtocol: cloud_assembly_schema_1.LoadBalancerListenerProtocol.TCP,
listenerPort: 443,
});
// THEN
expect(listener.listenerArn).toEqual('arn:listener-arn6');
expect(listener.listenerPort).toEqual(443);
expect(listener.securityGroupIds).toEqual(['sg-2345']);
});
test('filters by associated load balancer type', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
// This one has wrong type => no match
LoadBalancerArn: 'arn:load-balancer-arn1',
SecurityGroups: [],
Type: 'application',
},
{
// Right type => match
LoadBalancerArn: 'arn:load-balancer-arn2',
SecurityGroups: [],
Type: 'network',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolves({
Listeners: [
{
ListenerArn: 'arn:listener-arn2',
LoadBalancerArn: 'arn:load-balancer-arn2',
Port: 443,
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeTagsCommand)
.resolves({
TagDescriptions: [
{
ResourceArn: 'arn:load-balancer-arn1',
Tags: [{ Key: 'some', Value: 'tag' }],
},
{
ResourceArn: 'arn:load-balancer-arn2',
Tags: [{ Key: 'some', Value: 'tag' }],
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
const listener = await provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.NETWORK,
loadBalancerTags: [{ key: 'some', value: 'tag' }],
listenerPort: 443,
});
// THEN
expect(listener.listenerArn).toEqual('arn:listener-arn2');
expect(listener.listenerPort).toEqual(443);
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand, {
LoadBalancerArns: undefined,
});
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeListenersCommand, {
LoadBalancerArn: 'arn:load-balancer-arn2',
});
});
test('errors when associated load balancer is wrong type', async () => {
// GIVEN
mock_sdk_1.mockElasticLoadBalancingV2Client
.on(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand)
.resolves({
LoadBalancers: [
{
// This one has wrong type => no match
LoadBalancerArn: 'arn:load-balancer-arn1',
SecurityGroups: [],
Type: 'application',
},
],
})
.on(client_elastic_load_balancing_v2_1.DescribeListenersCommand)
.resolves({
Listeners: [
{
ListenerArn: 'arn:listener-arn1',
LoadBalancerArn: 'arn:load-balancer-arn1',
Port: 443,
},
],
});
const provider = new load_balancers_1.LoadBalancerListenerContextProviderPlugin(mockSDK);
// WHEN
await expect(provider.getValue({
account: '1234',
region: 'us-east-1',
loadBalancerType: cloud_assembly_schema_1.LoadBalancerType.NETWORK,
listenerArn: 'arn:listener-arn1',
})).rejects.toThrow('No associated load balancer found for listener arn arn:listener-arn1');
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand, {
LoadBalancerArns: ['arn:load-balancer-arn1'],
});
expect(mock_sdk_1.mockElasticLoadBalancingV2Client).toHaveReceivedCommandWith(client_elastic_load_balancing_v2_1.DescribeListenersCommand, {
ListenerArns: ['arn:listener-arn1'],
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZC1iYWxhbmNlcnMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImxvYWQtYmFsYW5jZXJzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwwRUFBZ0c7QUFDaEcsZ0dBSW1EO0FBQ25ELHVDQUF1RDtBQUN2RCwrRUFHb0Q7QUFDcEQsK0NBSzBCO0FBRTFCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFNLFNBQVEsMEJBQWU7SUFDekMsY0FBYztRQUNuQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxTQUFHLENBQUMsZ0NBQXFCLEVBQUUsT0FBTyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNuSCxDQUFDO0NBQ0YsQ0FBQyxFQUFFLENBQUM7QUFFTCxVQUFVLENBQUMsR0FBRyxFQUFFO0lBQ2QsSUFBQSxtQ0FBd0IsR0FBRSxDQUFDO0FBQzdCLENBQUMsQ0FBQyxDQUFDO0FBRUgsUUFBUSxDQUFDLHVDQUF1QyxFQUFFLEdBQUcsRUFBRTtJQUNyRCxJQUFJLENBQUMsa0NBQWtDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDbEQsUUFBUTtRQUNSLE1BQU0sUUFBUSxHQUFHLElBQUksa0RBQWlDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFaEUsT0FBTztRQUNQLE1BQU0sTUFBTSxDQUNWLFFBQVEsQ0FBQyxRQUFRLENBQUM7WUFDaEIsT0FBTyxFQUFFLE1BQU07WUFDZixNQUFNLEVBQUUsV0FBVztZQUNuQixnQkFBZ0IsRUFBRSx3Q0FBZ0IsQ0FBQyxXQUFXO1lBQzlDLGVBQWUsRUFBRSxvQkFBb0I7U0FDdEMsQ0FBQyxDQUNILENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FDZixrSkFBa0osQ0FDbkosQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLDJDQUEyQyxFQUFFLEtBQUssSUFBSSxFQUFF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