1 | # magic-cfn-resources
|
2 |
|
3 | [![Build Status](https://travis-ci.org/mapbox/magic-cfn-resources.svg?branch=master)](https://travis-ci.org/mapbox/magic-cfn-resources)
|
4 |
|
5 | ![](./assets/magicspaghetti.gif)
|
6 |
|
7 | Builds [Lambda-backed custom Cloudformation resources](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html). When you use `magic-cfn-resources`'s `build` method, a Lambda function is created in your stack and used to build a custom resource. Resources that can be built with `magic-cfn-resources` are: `SnsSubscription`, `DynamoDBStreamLabel`, `StackOutputs`, and `SpotFleet`.
|
8 |
|
9 | ## Provided resources in detail:
|
10 |
|
11 | ### SNS Subscriptions
|
12 |
|
13 | This allows you to manage SNS subscriptions as though they are first-class CloudFormation resources.
|
14 |
|
15 | ### DynamoDB Stream Labels
|
16 |
|
17 | This does not actually create any backend resource, but looks up the label for the stream associated with a DynamoDB table.
|
18 |
|
19 | This resource will use the stream's label as its PhysicalResourceId, so you can then access the label itself in your template via:
|
20 |
|
21 | ```json
|
22 | { "Ref": "LogicalNameOfYourCustomResource" }
|
23 | ```
|
24 |
|
25 | ### CloudFormation StackOutputs
|
26 |
|
27 | Looks up the Outputs for an existing CloudFormation stack.
|
28 |
|
29 | You can access the values of the stack's outputs with `Fn::GetAtt`
|
30 |
|
31 | ```json
|
32 | { "Fn::GetAtt": ["LogicalNameOfYourCustomResource", "LogicalNameOfStackOutput"] }
|
33 | ```
|
34 |
|
35 | ### SpotFleet
|
36 |
|
37 | Makes [SpotFleet requests](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-requests.html).
|
38 |
|
39 | ### DefaultVpc
|
40 |
|
41 | Looks up the default VPC in the region you've launched your stack in, and provides information about the VPC via `Fn::GetAtt`.
|
42 |
|
43 | ```json
|
44 | { "Fn::GetAtt": ["LogicalNameOfYourCustomResource", "VpcId"] }
|
45 | ```
|
46 |
|
47 | You can use `Fn::GetAtt` to obtain the following data:
|
48 |
|
49 | - VpcId: the default VPC's ID
|
50 | - AvailabilityZones: an array of strings representing the VPC's availability zones
|
51 | - AvailabilityZoneCount: the number of availability zones
|
52 | - PublicSubnets: an array of strings representing the VPC's public subnets
|
53 | - RouteTable: the ID for the first route table in the VPC
|
54 | - RouteTables: IDs of all of the route tables in the VPC
|
55 |
|
56 | ### S3NotificationTopicConfig
|
57 |
|
58 | Creates a notification topic configuration on an S3 bucket.
|
59 |
|
60 | ### S3Inventory
|
61 |
|
62 | Creates an [InventoryConfiguration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-inventoryconfiguration.html) for **an existing** S3 bucket that is not defined in CloudFormation. If you are defining an S3 bucket in CloudFormation, you can use the native CloudFormation support for this configuration.
|
63 |
|
64 | ## To create a magical resource in your own CloudFormation template:
|
65 | #### In an existing script or in a new script (i.e. `sns-subscription.js`):
|
66 | ```js
|
67 | // Purpose: create a handler for your Lambda function to reference
|
68 |
|
69 | const magicCfnResources = require('@mapbox/magic-cfn-resources');
|
70 | // export the custom function needed for your stack.
|
71 | module.exports.SnsSubscription = magicCfnResources.SnsSubscription;
|
72 | ```
|
73 | *Another example: `module.exports.SpotFleet = magicCfnResources.SpotFleet;`*
|
74 |
|
75 | #### In the CloudFormation template of your stack:
|
76 | ```js
|
77 | const magicCfnResources = require('@mapbox/magic-cfn-resources');
|
78 | ```
|
79 | #### Then, pass in the necessary parameters to `magicCfnResources.build`. These are the parameters needed for each resource:
|
80 |
|
81 | *SnsSubscription*
|
82 | ```js
|
83 | const SnsSubscription = magicCfnResources.build({
|
84 | CustomResourceName: 'SnsSubscription',
|
85 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
86 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
87 | S3Key: 'Key', // the S3 key for where the handler lives
|
88 | Handler: 'sns-subscription.SnsSubscription', // references the handler created in the repository
|
89 | Properties: {
|
90 | SnsTopicArn: 'Topic Arn', // the ARN of the SNS Topic you are subscribing to
|
91 | Protocol: 'Protocol', // the SNS protocol, i.e. 'sqs', 'email'
|
92 | Endpoint: 'Endpoint' // the endpoint you are subscribing
|
93 | }
|
94 | });
|
95 | ```
|
96 |
|
97 | *DynamoDBStreamLabel*
|
98 | ```js
|
99 | const DynamoDBStreamLabel = magicCfnResources.build({
|
100 | CustomResourceName: 'DynamoDBStreamLabel',
|
101 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
102 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
103 | S3Key: 'Key', // the S3 key for where the handler lives
|
104 | Handler: 'dynamodb-stream-label.DynamoDBStreamLabel', // references the handler created in the repository
|
105 | Properties: {
|
106 | TableName: 'Name of Table', // the name of the DynamoDB table
|
107 | TableRegion: 'Region' // the region of the DynamoDB table i.e.: 'us-east-1'
|
108 | }
|
109 | });
|
110 | ```
|
111 |
|
112 | *StackOutputs*
|
113 | ```js
|
114 | const StackOutputs = magicCfnResources.build({
|
115 | CustomResourceName: 'StackOutputs',
|
116 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
117 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
118 | S3Key: 'Key', // the S3 key for where the handler lives
|
119 | Handler: 'stack-outputs.StackOutputs', // references the handler created in the repository
|
120 | Properties: {
|
121 | StackName: 'Name', // name of the CloudFormation stack
|
122 | StackRegion: 'region' // region of the CloudFormation stack i.e.: 'us-east-1'
|
123 | }
|
124 | });
|
125 | ```
|
126 |
|
127 | *SpotFleet*
|
128 | ```js
|
129 | const SpotFleet = magicCfnResources.build({
|
130 | CustomResourceName: 'SpotFleet',
|
131 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
132 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
133 | S3Key: 'Key', // the S3 key for where the handler lives
|
134 | Handler: 'spot-fleet.SpotFleet', // references the handler created in the repository
|
135 | Properties: {
|
136 | SpotFleetRequestConfigData: { }, // object with SpotFleet configuration specifics
|
137 | Region: 'region', // region of the SpotFleet i.e.: 'us-east-1'
|
138 | }
|
139 | });
|
140 | ```
|
141 |
|
142 | *DefaultVpc*
|
143 | ```js
|
144 | const DefaultVpd = magicCfnResources.build({
|
145 | CustomResourceName: 'DefaultVpc',
|
146 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
147 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
148 | S3Key: 'Key', // the S3 key for where the handler lives
|
149 | Handler: 'index.DefaultVpc', // references the handler created in the repository
|
150 | Properties: {}
|
151 | });
|
152 | ```
|
153 |
|
154 | *S3NotificationTopicConfig*
|
155 | ```js
|
156 | const S3TopicConfig = magicCfnResources.build({
|
157 | CustomResourceName: 'S3NotificationTopicConfig',
|
158 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
159 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
160 | S3Key: 'Key', // the S3 key for where the handler lives
|
161 | Handler: 'index.DefaultVpc', // references the handler created in the repository
|
162 | Properties: {
|
163 | Id: 'notif-id', // an id to identify your notification config
|
164 | SnsTopicArn: 'topic arn', // topic arn to subscribe (must be in the same region as bucket)
|
165 | Bucket: 'bucket name', // name of bucket configuration is placed on,
|
166 | BucketRegion: 'us-east-1', // the region the bucket is in
|
167 | EventTypes: ['s3:ObjectCreated:*'], // the types of event to notify about
|
168 | PrefixFilter: 'prefix', // a prefix to filter notifications on (optional)
|
169 | SuffixFilter: '.jpg', // a suffix to filter notifications on (optional)
|
170 | BucketNotificationResources: [ 'bucket Arn' ]
|
171 | // if Bucket permissions need to be scoped, default is access to all resources (optional)
|
172 | }
|
173 | });
|
174 | ```
|
175 |
|
176 | *S3Inventory*
|
177 |
|
178 | ```js
|
179 | const S3InventoryConfig = magic.build({
|
180 | CustomResourceName: 'S3Inventory',
|
181 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
182 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
183 | S3Key: 'Key', // the S3 key for where the handler lives
|
184 | Handler: 'index.S3Inventory', // references the handler created in the repository
|
185 | Properties: { // Properties here are identical to those in the CloudFormation-native InventoryConfiguration
|
186 | BucketRegion: 'us-east-1', // the only additional property required
|
187 | Bucket: 'my-bucket',
|
188 | Id: 'my-inventory-id',
|
189 | InventoryConfiguration: {
|
190 | Schedule: { Frequency: 'Daily' },
|
191 | IsEnabled: true,
|
192 | Destination: {
|
193 | S3BucketDestination: {
|
194 | Bucket: cf.getAtt('my-inventory-bucket', 'Arn'),
|
195 | Format: 'ORC'
|
196 | }
|
197 | },
|
198 | OptionalFields: ['Size', 'LastModifiedDate', 'EncryptionStatus'],
|
199 | IncludedObjectVersions: 'Current',
|
200 | Id: 'my-inventory-id'
|
201 | }
|
202 | }
|
203 | });
|
204 | ```
|
205 |
|
206 | #### Optional Condition
|
207 | A [Condition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) from your template can also be passed into `build`.
|
208 | i.e.:
|
209 | ```
|
210 | const SpotFleet = magicCfnResources.build({
|
211 | CustomResourceName: 'SpotFleet',
|
212 | LogicalName: 'Logical Name', // a name to refer to the custom resource being built
|
213 | S3Bucket: 'Bucket Name', // the S3 bucket the code for the handler lives in
|
214 | S3Key: 'Key', // the S3 key for where the handler lives
|
215 | Handler: 'spot-fleet.SpotFleet', // references the handler created in the repository
|
216 | Properties: {
|
217 | SpotFleetRequestConfigData: { }, // object with SpotFleet configuration specifics
|
218 | Region: 'region', // region of the SpotFleet i.e.: 'us-east-1'
|
219 | },
|
220 | Condition: 'Condition' // the Logical ID of a condition
|
221 | });
|
222 | ```
|
223 | #### Merge the resources created with `build` with the resources already in the stack's template:. i.e.:
|
224 | ```js
|
225 | const cloudfriend = require('@mapbox/cloudfriend');
|
226 | const magicCfnResources = require('@mapbox/magic-cfn-resources');
|
227 |
|
228 | module.exports = cloudfriend.merge(SnsSubscription, <Stack Resources>);
|
229 | ```
|
230 |
|
231 | ## To build new functions
|
232 |
|
233 | Check out [contributing.md](https://github.com/mapbox/magic-cfn-resources/blob/master/contributing.md) for a discussion of the framework this library provides for writing other functions.
|