diff --git a/changelog.md b/changelog.md index 26becb8..c8d4069 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # Changelog +## 8.3.0 + +- Support a default value for cf.findInMap (Fn::FindInMap). + ## 8.2.0 - Add `LogRetentionInDays` option to Lambda shortcuts diff --git a/lib/intrinsic.js b/lib/intrinsic.js index abf0230..d157358 100644 --- a/lib/intrinsic.js +++ b/lib/intrinsic.js @@ -48,10 +48,16 @@ intrinsic.cidr = (ipBlock, count, cidrBits) => { * key-value pairs. * @param {string} attr - The second-level key name, which is set to one of the * keys from the list assigned to key. + * @param {string} defaultValue - The value that will resolve to if the key and/or attr can not be found from the mapping map. + * This field is optional and requires AWS::LanguageExtensions to be defined in the template. * @returns The value that is assigned to SecondLevelKey. */ -intrinsic.findInMap = (mapping, key, attr) => { - return { 'Fn::FindInMap': [mapping, key, attr] }; +intrinsic.findInMap = (mapping, key, attr, defaultValue) => { + const lookup = [mapping, key, attr]; + if (defaultValue) { + lookup.push({ DefaultValue: defaultValue }); + } + return { 'Fn::FindInMap': lookup }; }; /** diff --git a/package-lock.json b/package-lock.json index dc2bcf6..c0e9454 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@mapbox/cloudfriend", - "version": "8.2.0", + "version": "8.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@mapbox/cloudfriend", - "version": "8.2.0", + "version": "8.3.0", "license": "ISC", "dependencies": { "aws-sdk": "^2.1425.0", diff --git a/package.json b/package.json index 0a43091..a6a3d15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mapbox/cloudfriend", - "version": "8.2.0", + "version": "8.3.0", "description": "Helper functions for assembling CloudFormation templates in JavaScript", "main": "index.js", "engines": { @@ -11,6 +11,7 @@ "lint": "eslint index.js test lib bin cloudformation", "lint:fix": "npm run lint -- --fix", "test": "nyc tape test/*.test.js | tap-spec", + "test:update": "UPDATE=1 npm run test", "coverage": "nyc --reporter html tape test/*.test.js && opener coverage/index.html", "build-ci-template": "bin/build-template.js cloudformation/ci.template.js > cloudformation/ci.template.json", "shortcuts-api-doc": "jsdoc2md lib/shortcuts/*.js > lib/shortcuts/api.md" diff --git a/test/fixtures/shortcuts/hookshot-github-secret-ref.json b/test/fixtures/shortcuts/hookshot-github-secret-ref.json index 86c3813..7ace2aa 100644 --- a/test/fixtures/shortcuts/hookshot-github-secret-ref.json +++ b/test/fixtures/shortcuts/hookshot-github-secret-ref.json @@ -28,7 +28,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -47,7 +47,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-github-secret-string.json b/test/fixtures/shortcuts/hookshot-github-secret-string.json index 7676995..3ef715a 100644 --- a/test/fixtures/shortcuts/hookshot-github-secret-string.json +++ b/test/fixtures/shortcuts/hookshot-github-secret-string.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -43,7 +43,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-github.json b/test/fixtures/shortcuts/hookshot-github.json index 473dcc2..9ddd070 100644 --- a/test/fixtures/shortcuts/hookshot-github.json +++ b/test/fixtures/shortcuts/hookshot-github.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -43,7 +43,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-passthrough-access-log-format.json b/test/fixtures/shortcuts/hookshot-passthrough-access-log-format.json index 252f28f..86949c9 100644 --- a/test/fixtures/shortcuts/hookshot-passthrough-access-log-format.json +++ b/test/fixtures/shortcuts/hookshot-passthrough-access-log-format.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -52,7 +52,7 @@ } } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-passthrough-alarms.json b/test/fixtures/shortcuts/hookshot-passthrough-alarms.json index 76abefc..86ee1c1 100644 --- a/test/fixtures/shortcuts/hookshot-passthrough-alarms.json +++ b/test/fixtures/shortcuts/hookshot-passthrough-alarms.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -43,7 +43,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-passthrough-enhanced-logging.json b/test/fixtures/shortcuts/hookshot-passthrough-enhanced-logging.json index b5a321e..f3b6ecf 100644 --- a/test/fixtures/shortcuts/hookshot-passthrough-enhanced-logging.json +++ b/test/fixtures/shortcuts/hookshot-passthrough-enhanced-logging.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -43,7 +43,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-passthrough-full-blown-logging.json b/test/fixtures/shortcuts/hookshot-passthrough-full-blown-logging.json index 83f72b9..5c3dfea 100644 --- a/test/fixtures/shortcuts/hookshot-passthrough-full-blown-logging.json +++ b/test/fixtures/shortcuts/hookshot-passthrough-full-blown-logging.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -43,7 +43,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-passthrough-logging.json b/test/fixtures/shortcuts/hookshot-passthrough-logging.json index c50985b..611dd69 100644 --- a/test/fixtures/shortcuts/hookshot-passthrough-logging.json +++ b/test/fixtures/shortcuts/hookshot-passthrough-logging.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -43,7 +43,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/hookshot-passthrough.json b/test/fixtures/shortcuts/hookshot-passthrough.json index d1851c4..972b6c9 100644 --- a/test/fixtures/shortcuts/hookshot-passthrough.json +++ b/test/fixtures/shortcuts/hookshot-passthrough.json @@ -24,7 +24,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "PassDeploymentac7cb6b9" + "Ref": "PassDeployment2a35d33e" }, "StageName": "hookshot", "RestApiId": { @@ -43,7 +43,7 @@ ] } }, - "PassDeploymentac7cb6b9": { + "PassDeployment2a35d33e": { "Type": "AWS::ApiGateway::Deployment", "DependsOn": "PassMethod", "Properties": { diff --git a/test/fixtures/shortcuts/lambda-full.json b/test/fixtures/shortcuts/lambda-full.json index 5a5a480..3795c27 100644 --- a/test/fixtures/shortcuts/lambda-full.json +++ b/test/fixtures/shortcuts/lambda-full.json @@ -6,7 +6,10 @@ "Mappings": {}, "Conditions": { "Always": { - "Fn::Equals": ["1", "1"] + "Fn::Equals": [ + "1", + "1" + ] } }, "Resources": { @@ -49,7 +52,9 @@ "FunctionName": "my-function", "Handler": "index.something", "KmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/fake", - "Layers": ["arn:aws:fake:layer/abc"], + "Layers": [ + "arn:aws:fake:layer/abc" + ], "MemorySize": 512, "ReservedConcurrentExecutions": 10, "Runtime": "nodejs18.x", @@ -58,8 +63,12 @@ "Mode": "Active" }, "VpcConfig": { - "SecurityGroupIds": ["sg-12345"], - "SubnetIds": ["fake"] + "SecurityGroupIds": [ + "sg-12345" + ], + "SubnetIds": [ + "fake" + ] }, "Tags": [ { @@ -68,7 +77,10 @@ } ], "Role": { - "Fn::GetAtt": ["MyLambdaRole", "Arn"] + "Fn::GetAtt": [ + "MyLambdaRole", + "Arn" + ] } } }, @@ -78,7 +90,9 @@ "Properties": { "AlarmName": "my-alarm", "AlarmDescription": "some alarm", - "AlarmActions": ["devnull@mapbox.com"], + "AlarmActions": [ + "devnull@mapbox.com" + ], "Period": 120, "EvaluationPeriods": 2, "DatapointsToAlarm": 1, @@ -87,7 +101,9 @@ "ComparisonOperator": "LessThanThreshold", "TreatMissingData": "breaching", "EvaluateLowSampleCountPercentile": "ignore", - "OKActions": ["devnull@mapbox.com"], + "OKActions": [ + "devnull@mapbox.com" + ], "Namespace": "AWS/Lambda", "Dimensions": [ { @@ -118,7 +134,10 @@ "Effect": "Allow", "Action": "logs:*", "Resource": { - "Fn::GetAtt": ["MyLambdaLogs", "Arn"] + "Fn::GetAtt": [ + "MyLambdaLogs", + "Arn" + ] } } ] @@ -161,4 +180,4 @@ } }, "Outputs": {} -} +} \ No newline at end of file diff --git a/test/fixtures/shortcuts/stream-lambda-no-defaults.json b/test/fixtures/shortcuts/stream-lambda-no-defaults.json index 8375289..b84d471 100644 --- a/test/fixtures/shortcuts/stream-lambda-no-defaults.json +++ b/test/fixtures/shortcuts/stream-lambda-no-defaults.json @@ -167,21 +167,21 @@ "Properties": { "BatchSize": 10000, "MaximumBatchingWindowInSeconds": 300, + "Enabled": false, + "EventSourceArn": "arn:aws:kinesis:us-east-1:123456789012:stream/fake", + "FunctionName": { + "Ref": "MyLambda" + }, + "StartingPosition": "TRIM_HORIZON", "FilterCriteria": { "Filters": [ { "Pattern": "{\"eventName\":[\"INSERT\",\"MODIFY\"]}" } ] - }, - "Enabled": false, - "EventSourceArn": "arn:aws:kinesis:us-east-1:123456789012:stream/fake", - "FunctionName": { - "Ref": "MyLambda" - }, - "StartingPosition": "TRIM_HORIZON" + } } } }, "Outputs": {} -} +} \ No newline at end of file diff --git a/test/index.test.js b/test/index.test.js index 883dc69..f6f8f1d 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -11,6 +11,7 @@ test('intrinsic functions', (assert) => { assert.deepEqual(cloudfriend.base64('secret'), { 'Fn::Base64': 'secret' }, 'base64'); assert.deepEqual(cloudfriend.cidr('ipBlock', 1, 2), { 'Fn::Cidr': ['ipBlock', 1, 2] }, 'cidr'); assert.deepEqual(cloudfriend.findInMap('mapping', 'key', 'value'), { 'Fn::FindInMap': ['mapping', 'key', 'value'] }, 'lookup'); + assert.deepEqual(cloudfriend.findInMap('mapping', 'key', 'value', 'hello-world'), { 'Fn::FindInMap': ['mapping', 'key', 'value', { DefaultValue: 'hello-world' }] }, 'lookup with default value'); assert.deepEqual( cloudfriend.forEach('somethings', 'topic', ['abra', 'cadabra'], 'magic', { Type: 'AWS::SNS::Topic',