Skip to content

Commit

Permalink
chore: cover all known permutations of ALB template in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
eoinsha committed Oct 12, 2022
1 parent e3ac727 commit 93141b1
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 9 deletions.
2 changes: 1 addition & 1 deletion core/cf-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const logger = getLogger()
* @param {object} compiledTemplate The compiled CloudFormation template
* @param {object} additionalResources Directly-provided CloudFormation resources which are not expected to be included in `compiledTemplate`
*/
module.exports = function CloudFormationTemplate (compiledTemplate, additionalResources) {
module.exports = function CloudFormationTemplate (compiledTemplate, additionalResources = {}) {
/**
* Take a CloudFormation reference to a Lambda Function name and attempt to resolve this function's
* CloudFormation logical ID from within this stack
Expand Down
22 changes: 22 additions & 0 deletions core/tests/cf-template.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ test('Resource can be resolved by type from compiled template', (t) => {
t.end()
})

test('Resource can be resolved by type from template with additional resource ', (t) => {
const compiledTemplate = {
Resources: {
a: { Type: 'AWS::DynamoDB::Table' }
}
}
const template = CloudFormationTemplate(compiledTemplate, {
b: { Type: 'AWS::SQS::Queue' }
}, sls)

const tableResources = template.getResourcesByType('AWS::DynamoDB::Table')
t.equal(Object.keys(tableResources).length, 1)
t.equal(Object.values(tableResources)[0].Type, 'AWS::DynamoDB::Table')
const queueResources = template.getResourcesByType('AWS::SQS::Queue')
t.equal(Object.keys(queueResources).length, 1)
t.equal(Object.values(queueResources)[0].Type, 'AWS::SQS::Queue')

const queueResource = template.getResourceByName('b')
t.equal(queueResource.Type, 'AWS::SQS::Queue')
t.end()
})

test('Resource can be resolved by type from service resources', (t) => {
const compiledTemplate = {}
const serviceResources = {
Expand Down
17 changes: 17 additions & 0 deletions core/tests/dashboard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,23 @@ test('A dashboard includes metrics for ALB', (t) => {
t.same(actualTitles, expectedTitles)
t.end()
})

test('No widgets are created if all ALB metrics are disabled', (t) => {
const services = ['Lambda', 'ApiGateway', 'States', 'DynamoDB', 'SQS', 'Kinesis', 'ECS', 'SNS', 'Events', 'ApplicationELB', 'ApplicationELBTarget']
const dashConfig = cloneDeep(defaultConfig.dashboard)
for (const service of services) {
for (const metricConfig of Object.values(dashConfig.widgets[service])) {
metricConfig.enabled = false
}
}
const dash = dashboard(dashConfig, emptyFuncConfigs, context)
const cfTemplate = createTestCloudFormationTemplate(albCfTemplate)
dash.addDashboard(cfTemplate)
const dashResources = cfTemplate.getResourcesByType('AWS::CloudWatch::Dashboard')
t.same(dashResources, {})
t.end()
})

t.end()
})

Expand Down
200 changes: 195 additions & 5 deletions core/tests/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,201 @@ const { albCfTemplate } = require('./testing-utils')
const CloudFormationTemplate = require('../cf-template')
const albCfTemp = CloudFormationTemplate(albCfTemplate)

test(' finds the associated Load Balancer if it exist in the CloudFormation template for the Target Group', (t) => {
const targetGroupLogicalId = 'AlbEventAlbTargetGrouphttpListener'
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup(targetGroupLogicalId, albCfTemp)
t.equal(loadBalancerLogicalIds.length, 1)
t.equal(loadBalancerLogicalIds[0], 'alb')
test('findLoadBalancersForTargetGroup', (t) => {
test('finds the associated Load Balancer if it exists in the CloudFormation template for the Target Group', (t) => {
const targetGroupLogicalId = 'AlbEventAlbTargetGrouphttpListener'
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup(targetGroupLogicalId, albCfTemp)
t.same(loadBalancerLogicalIds, ['alb'])
t.end()
})

test('returns empty list for non-existent listener', (t) => {
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('fakeListener', CloudFormationTemplate({}))
t.equal(loadBalancerLogicalIds.length, 0)
t.end()
})

test('includes an ALB from the DefaultActions', (t) => {
const template = CloudFormationTemplate({
Resources: {
listener: {
Type: 'AWS::ElasticLoadBalancingV2::Listener',
Properties: {
DefaultActions: [
{
TargetGroupArn: { Ref: 'tg' }
}
],
LoadBalancerArn: { Ref: 'alb' }
}
},
tg: {
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
},
alb: {}
}
})

const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tg', template)
t.same(loadBalancerLogicalIds, ['alb'])
t.end()
})

test('excludes DefaultActions with a literal load balancer ARN', (t) => {
const template = CloudFormationTemplate({
Resources: {
listener: {
Type: 'AWS::ElasticLoadBalancingV2::Listener',
Properties: {
DefaultActions: [
{
TargetGroupArn: { Ref: 'tg' }
}
],
LoadBalancerArn: 'arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188'
}
},
tg: {
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
},
alb: {}
}
})

const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tg', template)
t.equal(loadBalancerLogicalIds.length, 0)
t.end()
})
test('finds load balancers through listener rule target groups', (t) => {
const template = CloudFormationTemplate({
Resources: {
listenerRuleA: {
Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
Properties: {
Actions: [{ TargetGroupArn: { Ref: 'tgA' } }],
ListenerArn: { Ref: 'listener' }
}
},
listenerRuleB: {
Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
Properties: {
Actions: [{ TargetGroupArn: { Ref: 'tgB' } }],
ListenerArn: { Ref: 'listener' }
}
},
listener: {
Type: 'AWS::ElasticLoadBalancingV2::Listener',
Properties: {
LoadBalancerArn: { Ref: 'alb' }
}
}
}
})
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tgA', template)
t.same(loadBalancerLogicalIds, ['alb'])
t.end()
})

test('omits listener rules with no load balancer', (t) => {
const template = CloudFormationTemplate({
Resources: {
listenerRule: {
Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
Properties: {
Actions: [{ TargetGroupArn: { Ref: 'tg' } }],
ListenerArn: { Ref: 'listener' }
}
},
listener: {
Type: 'AWS::ElasticLoadBalancingV2::Listener',
Properties: {}
}
}
})
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tg', template)
t.equal(loadBalancerLogicalIds.length, 0)
t.end()
})

test('omits listener rules with no actions', (t) => {
const template = CloudFormationTemplate({
Resources: {
listenerRule: {
Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
Properties: {
ListenerArn: { Ref: 'listener' }
}
}
}
})
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tg', template)
t.equal(loadBalancerLogicalIds.length, 0)
t.end()
})

test('omits listener rules a literal listener ARN', (t) => {
const template = CloudFormationTemplate({
Resources: {
listenerRule: {
Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
Properties: {
Actions: [{ TargetGroupArn: { Ref: 'tgA' } }],
ListenerArn: 'arn:aws:elasticloadbalancing:us-west-2:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/f2f7dc8efc522ab2'
}
}
}
})
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tgA', template)
t.equal(loadBalancerLogicalIds.length, 0)
t.end()
})

test('omits listeners with a literal load balancer ARN', (t) => {
const template = CloudFormationTemplate({
Resources: {
listenerRuleA: {
Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
Properties: {
Actions: [{ TargetGroupArn: { Ref: 'tgA' } }],
ListenerArn: { Ref: 'listener' }
}
},
listener: {
Type: 'AWS::ElasticLoadBalancingV2::Listener',
Properties: {
LoadBalancerArn: 'arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188'
}
}
}
})
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tgA', template)
t.equal(loadBalancerLogicalIds.length, 0)
t.end()
})

test('omits listener rules referencing a listener that cannot be found', (t) => {
const template = CloudFormationTemplate({
Resources: {
listenerRuleA: {
Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
Properties: {
Actions: [{ TargetGroupArn: { Ref: 'tgA' } }],
ListenerArn: { Ref: 'listenerX' }
}
},
listener: {
Type: 'AWS::ElasticLoadBalancingV2::Listener',
Properties: {
LoadBalancerArn: { Ref: 'alb' }
}
}
}
})
const loadBalancerLogicalIds = findLoadBalancersForTargetGroup('tgA', template)
t.equal(loadBalancerLogicalIds.length, 0)
t.end()
})

t.end()
})

Expand Down
6 changes: 3 additions & 3 deletions core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ function findLoadBalancersForTargetGroup (targetGroupLogicalId, cfTemplate) {
// First, find Listeners with _default actions_ referencing the target group
for (const listener of Object.values(listenerResources)) {
for (const action of listener.Properties.DefaultActions || []) {
const targetGroupArn = action.TargetGroupArn
const targetGroupArn = action?.TargetGroupArn
if (targetGroupArn?.Ref === targetGroupLogicalId) {
const loadBalancerLogicalId = listener.Properties.LoadBalancerArn.Ref
const loadBalancerLogicalId = listener.Properties.LoadBalancerArn?.Ref
if (loadBalancerLogicalId) {
allLoadBalancerLogicalIds.add(loadBalancerLogicalId)
}
Expand All @@ -114,7 +114,7 @@ function findLoadBalancersForTargetGroup (targetGroupLogicalId, cfTemplate) {
if (listenerLogicalId) {
const listener = cfTemplate.getResourceByName(listenerLogicalId)
if (listener) {
const loadBalancerLogicalId = listener.Properties.LoadBalancerArn.Ref
const loadBalancerLogicalId = listener.Properties.LoadBalancerArn?.Ref
if (loadBalancerLogicalId) {
allLoadBalancerLogicalIds.add(loadBalancerLogicalId)
}
Expand Down

0 comments on commit 93141b1

Please sign in to comment.