cfoo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.simplecov +4 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +676 -0
- data/README.md +166 -0
- data/Rakefile +10 -0
- data/TODO +29 -0
- data/bin/cfoo +26 -0
- data/cfoo.gemspec +35 -0
- data/features/attribute_expansion.feature +43 -0
- data/features/convert_yaml_to_json.feature +69 -0
- data/features/el_escaping.feature +21 -0
- data/features/map_reference_expansion.feature +68 -0
- data/features/modules.feature +101 -0
- data/features/parse_files.feature +46 -0
- data/features/reference_expansion.feature +49 -0
- data/features/step_definitions/cfoo_steps.rb +107 -0
- data/features/support/env.rb +5 -0
- data/features/yamly_shortcuts.feature +132 -0
- data/lib/cfoo.rb +11 -0
- data/lib/cfoo/cfoo.rb +15 -0
- data/lib/cfoo/el_parser.rb +105 -0
- data/lib/cfoo/file_system.rb +28 -0
- data/lib/cfoo/module.rb +25 -0
- data/lib/cfoo/parser.rb +82 -0
- data/lib/cfoo/processor.rb +38 -0
- data/lib/cfoo/project.rb +16 -0
- data/lib/cfoo/renderer.rb +9 -0
- data/lib/cfoo/version.rb +3 -0
- data/lib/cfoo/yaml.rb +34 -0
- data/lib/cfoo/yaml_parser.rb +16 -0
- data/spec/cfoo/cfoo_spec.rb +31 -0
- data/spec/cfoo/el_parser_spec.rb +47 -0
- data/spec/cfoo/file_system_spec.rb +61 -0
- data/spec/cfoo/module_spec.rb +16 -0
- data/spec/cfoo/parser_spec.rb +148 -0
- data/spec/cfoo/processor_spec.rb +52 -0
- data/spec/cfoo/project_spec.rb +16 -0
- data/spec/cfoo/renderer_spec.rb +19 -0
- data/spec/cfoo/yaml_parser_spec.rb +79 -0
- data/spec/spec_helper.rb +2 -0
- metadata +235 -0
data/README.md
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
# Cfoo
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/drrb/cfoo.png?branch=master)](https://travis-ci.org/drrb/cfoo)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/drrb/cfoo/badge.png?branch=master)](https://coveralls.io/r/drrb/cfoo)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/drrb/cfoo.png)](https://codeclimate.com/github/drrb/cfoo)
|
6
|
+
|
7
|
+
Write your CloudFormation templates in a YAML-based markup language
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Cfoo can be installed as a Ruby Gem
|
12
|
+
|
13
|
+
$ gem install cfoo
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Process some Cfoo templates from the command line
|
18
|
+
|
19
|
+
$ cfoo web-server-template.yml database_template.yml
|
20
|
+
|
21
|
+
## Templates
|
22
|
+
|
23
|
+
### Comparison with standard CloudFormation templates
|
24
|
+
|
25
|
+
Snippet from a CloudFormation template (based on [this example](https://s3.amazonaws.com/cloudformation-templates-us-east-1/Rails_Single_Instance.template)):
|
26
|
+
|
27
|
+
```json
|
28
|
+
"Properties": {
|
29
|
+
"ImageId" : { "Fn::FindInMap" : [ "AWSRegion2AMI", { "Ref" : "AWS::Region" }, "AMI" ] },
|
30
|
+
"InstanceType" : { "Ref" : "InstanceType" },
|
31
|
+
"SecurityGroups" : [ {"Ref" : "FrontendGroup"} ],
|
32
|
+
"KeyName" : { "Ref" : "KeyName" },
|
33
|
+
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
|
34
|
+
"#!/bin/bash -v\n",
|
35
|
+
"yum update -y aws-cfn-bootstrap\n",
|
36
|
+
|
37
|
+
"function error_exit\n",
|
38
|
+
"{\n",
|
39
|
+
" /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "WaitHandle" }, "'\n",
|
40
|
+
" exit 1\n",
|
41
|
+
"}\n",
|
42
|
+
|
43
|
+
"/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServer ",
|
44
|
+
" --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n",
|
45
|
+
|
46
|
+
"/opt/aws/bin/cfn-signal -e 0 -r \"cfn-init complete\" '", { "Ref" : "WaitHandle" }, "'\n"
|
47
|
+
]]}}
|
48
|
+
}
|
49
|
+
```
|
50
|
+
|
51
|
+
Equivalent Cfoo template snippet:
|
52
|
+
|
53
|
+
```yaml
|
54
|
+
Properties:
|
55
|
+
ImageId : AWSRegion2AMI[$(AWS::Region)][AMI]
|
56
|
+
InstanceType: $(InstanceType)
|
57
|
+
SecurityGroups:
|
58
|
+
- $(FrontendGroup)
|
59
|
+
KeyName: $(KeyName)
|
60
|
+
UserData: !Base64 |
|
61
|
+
#!/bin/bash -v
|
62
|
+
yum update -y aws-cfn-bootstrap
|
63
|
+
|
64
|
+
function error_exit
|
65
|
+
{
|
66
|
+
/opt/aws/bin/cfn-signal -e 1 -r "$1" '$(WaitHandle)'
|
67
|
+
exit 1
|
68
|
+
}
|
69
|
+
|
70
|
+
/opt/aws/bin/cfn-init -s $(AWS::StackId) -r WebServer --region $(AWS::Region) || error_exit 'Failed to run cfn-init'
|
71
|
+
|
72
|
+
/opt/aws/bin/cfn-signal -e 0 -r "cfn-init completed" '$(WaitHandle)'
|
73
|
+
```
|
74
|
+
|
75
|
+
### Shortcuts
|
76
|
+
|
77
|
+
Cfoo allows you to simplify CloudFormation [intrinsic function](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)
|
78
|
+
references using its own shorthand
|
79
|
+
|
80
|
+
##### Reference
|
81
|
+
|
82
|
+
CloudFormation: `{ "Ref" : "InstanceType" }`
|
83
|
+
|
84
|
+
Cfoo Shortcut: `$(InstanceType)`
|
85
|
+
|
86
|
+
##### Mapping Reference
|
87
|
+
|
88
|
+
CloudFormation: `{ "FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ] }`
|
89
|
+
|
90
|
+
Cfoo Shortcut: `$(SubnetConfig[VPC][CIDR])`
|
91
|
+
|
92
|
+
##### Attribute Reference
|
93
|
+
|
94
|
+
CloudFormation: `{ "Fn::GetAtt" : [ "Ec2Instance", "PublicIp" ] }`
|
95
|
+
|
96
|
+
Cfoo Shortcut: `$(Ec2Instance.PublicIp)`
|
97
|
+
|
98
|
+
Other Shortcut: `$(Ec2Instance[PublicIp])`
|
99
|
+
|
100
|
+
##### Embedded Reference
|
101
|
+
|
102
|
+
CloudFormation: `{ "Fn::Join" : [ "", [{"Ref" : "HostedZone"}, "." ]]}`
|
103
|
+
|
104
|
+
Cfoo Shortcut: `$(HostedZone).`
|
105
|
+
|
106
|
+
### YAML Types
|
107
|
+
|
108
|
+
Cfoo gives you the option of using YAML custom data-types where it helps to make your templates easier to read.
|
109
|
+
The table below uses inline YAML lists, but multiline lists can also be used.
|
110
|
+
|
111
|
+
##### Reference
|
112
|
+
|
113
|
+
CloudFormation: `{ "Ref" : "InstanceType" }`
|
114
|
+
|
115
|
+
YAML Type: `!Ref InstanceType`
|
116
|
+
|
117
|
+
##### Mapping Reference
|
118
|
+
|
119
|
+
CloudFormation: `{ "FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ] }`
|
120
|
+
|
121
|
+
YAML Type: `!FindInMap [ SubnetConfig, VPC, CIDR ]`
|
122
|
+
|
123
|
+
##### Attribute Reference
|
124
|
+
|
125
|
+
CloudFormation: `{ "Fn::GetAtt" : [ "Ec2Instance", "PublicIp" ] }`
|
126
|
+
|
127
|
+
YAML Type: `!GetAtt [ Ec2Instance, PublicIp ]`
|
128
|
+
|
129
|
+
##### Base64 String
|
130
|
+
|
131
|
+
CloudFormation: `{ "Fn::Base64" : "#!/bin/bash\necho 'Running script...'" }`
|
132
|
+
|
133
|
+
YAML Type: `!Base64 "#!/bin/bash\necho 'running script...'"`
|
134
|
+
|
135
|
+
## Goals
|
136
|
+
|
137
|
+
### Primary Goals
|
138
|
+
|
139
|
+
Cfoo aims to let developers simplify CloudFormation templates by:
|
140
|
+
|
141
|
+
- allowing them to write templates in YAML
|
142
|
+
- providing an expression language to simplify CF Ref/Attr/etc expressions
|
143
|
+
- allowing templates to be split up into logical components (to simplify and share)
|
144
|
+
|
145
|
+
### Secondary Goals
|
146
|
+
|
147
|
+
Cfoo aims (subject to Primary Goals) to:
|
148
|
+
|
149
|
+
- allow all aspects of CloudFormation templates to be expressed in YAML (so you don't need to use JSON)
|
150
|
+
- allow inclusion existing JSON templates (so you don't have to switch all at once)
|
151
|
+
|
152
|
+
### Non-goals
|
153
|
+
|
154
|
+
Cfoo does not (yet) aim to:
|
155
|
+
|
156
|
+
- provide commandline utilities for interacting directly with CloudFormation (it just generates the templates for now)
|
157
|
+
- resolve/validate references (the CloudFormation API already does this)
|
158
|
+
|
159
|
+
## Contributing
|
160
|
+
|
161
|
+
1. Fork it
|
162
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
163
|
+
3. Make your changes (with tests please)
|
164
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
165
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
166
|
+
6. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'cucumber/rake/task'
|
4
|
+
require 'coveralls/rake/task'
|
5
|
+
|
6
|
+
Coveralls::RakeTask.new
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
Cucumber::Rake::Task.new(:features)
|
9
|
+
|
10
|
+
task :default => [:spec, :features, 'coveralls:push']
|
data/TODO
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Features
|
2
|
+
----------
|
3
|
+
More tests for EL parsing
|
4
|
+
Spaces in EL?
|
5
|
+
More than [A-Za-z:] in EL identifiers?
|
6
|
+
Shorthand for AWS variables (e.g. { "Ref" : "AWS::StackId" } )
|
7
|
+
Shorthand for Fn::GetAZs
|
8
|
+
Better errors when parsing fails
|
9
|
+
Split into resources/mappings/parameters/etc by putting templates into directories with those names
|
10
|
+
Allow directory for raw templates
|
11
|
+
Allow traditional JSON CloudFormation templates (including modules, splitting, etc)
|
12
|
+
Vim highlighting
|
13
|
+
Use multi-json instead of json gem (spec.add_dependency 'multi_json', '~> 1.0')
|
14
|
+
Disablable warnings about naming conventions
|
15
|
+
Allow module references to remote templates (inc. Git repositories) (auto-included)
|
16
|
+
Allow rendering only part of the project (in case part of the infrastructure already exists)
|
17
|
+
Render templates with ERB to allow extra flexibility/substitution
|
18
|
+
Resolve EL and complain/fail if targets don't exist
|
19
|
+
Unit testing for templates
|
20
|
+
|
21
|
+
Tests
|
22
|
+
----------
|
23
|
+
|
24
|
+
Tasks
|
25
|
+
----------
|
26
|
+
Refactor EL parser
|
27
|
+
|
28
|
+
Bugs
|
29
|
+
----------
|
data/bin/cfoo
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib_path = File.expand_path('../../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include? lib_path
|
5
|
+
require 'cfoo'
|
6
|
+
|
7
|
+
if ARGV.include? "--help"
|
8
|
+
STDERR.puts "Usage: #{File.basename $0} [filename...]"
|
9
|
+
exit 1
|
10
|
+
end
|
11
|
+
|
12
|
+
filenames = ARGV
|
13
|
+
|
14
|
+
yaml_parser = Cfoo::YamlParser.new
|
15
|
+
file_system = Cfoo::FileSystem.new(".", yaml_parser)
|
16
|
+
project = Cfoo::Project.new(file_system)
|
17
|
+
parser = Cfoo::Parser.new(file_system)
|
18
|
+
processor = Cfoo::Processor.new(parser, project)
|
19
|
+
renderer = Cfoo::Renderer.new
|
20
|
+
cfoo = Cfoo::Cfoo.new(processor, renderer, STDOUT)
|
21
|
+
|
22
|
+
if filenames.empty?
|
23
|
+
cfoo.build_project
|
24
|
+
else
|
25
|
+
cfoo.process *filenames
|
26
|
+
end
|
data/cfoo.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cfoo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "cfoo"
|
8
|
+
gem.version = Cfoo::VERSION
|
9
|
+
gem.authors = ["drrb"]
|
10
|
+
gem.email = ["drrrrrrrrrrrb@gmail.com"]
|
11
|
+
gem.license = "GPL-3"
|
12
|
+
gem.description = "Cfoo: CloudFormation master"
|
13
|
+
gem.summary = <<-EOF
|
14
|
+
Cfoo (pronounced 'sifu') allows you to write your CloudFormation templates in a
|
15
|
+
YAML-based markup language, and organise it into modules to make it easier to
|
16
|
+
maintain.
|
17
|
+
EOF
|
18
|
+
gem.homepage = "https://github.com/drrb/cfoo"
|
19
|
+
|
20
|
+
gem.files = `git ls-files`.split($/)
|
21
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
22
|
+
gem.test_files = gem.files.grep(%r{^(spec|features)/})
|
23
|
+
gem.require_paths = ["lib"]
|
24
|
+
|
25
|
+
gem.add_dependency "json"
|
26
|
+
gem.add_dependency "parslet"
|
27
|
+
|
28
|
+
gem.add_development_dependency "bundler", "~> 1.3"
|
29
|
+
gem.add_development_dependency "rake"
|
30
|
+
gem.add_development_dependency "rspec"
|
31
|
+
gem.add_development_dependency "cucumber"
|
32
|
+
gem.add_development_dependency "simplecov"
|
33
|
+
gem.add_development_dependency "coveralls", ">= 0.6.3"
|
34
|
+
gem.add_development_dependency "json" # Coveralls needs it
|
35
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
Feature: Expand EL Attribute References
|
2
|
+
As a CloudFormation user
|
3
|
+
I want to use an expression language as a shorthand for references
|
4
|
+
So that I my templates are easier to read
|
5
|
+
|
6
|
+
Scenario: Attribute expansion
|
7
|
+
Given I have a file "outputs.yml" containing
|
8
|
+
"""
|
9
|
+
EntryPoint:
|
10
|
+
Description: IP address of the Bastion Host
|
11
|
+
Value: $(BastionHost.PublicIp)
|
12
|
+
"""
|
13
|
+
When I process "outputs.yml"
|
14
|
+
Then the output should match JSON
|
15
|
+
"""
|
16
|
+
{
|
17
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
18
|
+
"EntryPoint" : {
|
19
|
+
"Description" : "IP address of the Bastion Host",
|
20
|
+
"Value" : { "Fn::GetAtt" : [ "BastionHost", "PublicIp" ]}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
"""
|
24
|
+
|
25
|
+
Scenario: Embedded attribute expansion
|
26
|
+
Given I have a file "outputs.yml" containing
|
27
|
+
"""
|
28
|
+
WebSite:
|
29
|
+
Description: URL of the website
|
30
|
+
Value: http://$(PublicElasticLoadBalancer.DNSName)/index.html
|
31
|
+
"""
|
32
|
+
When I process "outputs.yml"
|
33
|
+
Then the output should match JSON
|
34
|
+
"""
|
35
|
+
{
|
36
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
37
|
+
"WebSite" : {
|
38
|
+
"Description" : "URL of the website",
|
39
|
+
"Value" : { "Fn::Join" : [ "", [ "http://", { "Fn::GetAtt" : [ "PublicElasticLoadBalancer", "DNSName" ]}, "/index.html"]]}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
"""
|
43
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
Feature: Convert YAML to JSON
|
2
|
+
As a JSON provider
|
3
|
+
I want to generate my JSON from YAML
|
4
|
+
So that it's easier to read
|
5
|
+
|
6
|
+
Scenario: Basic array conversion
|
7
|
+
Given I have a file "list.yml" containing
|
8
|
+
"""
|
9
|
+
list:
|
10
|
+
- One
|
11
|
+
- 2
|
12
|
+
- "3"
|
13
|
+
"""
|
14
|
+
When I process "list.yml"
|
15
|
+
Then the output should match JSON
|
16
|
+
"""
|
17
|
+
{
|
18
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
19
|
+
"list" : ["One", 2, "3"]
|
20
|
+
}
|
21
|
+
"""
|
22
|
+
|
23
|
+
Scenario: Basic map conversion
|
24
|
+
Given I have a file "map.yml" containing
|
25
|
+
"""
|
26
|
+
1: One
|
27
|
+
2: Two
|
28
|
+
3: Three
|
29
|
+
"""
|
30
|
+
When I process "map.yml"
|
31
|
+
Then the output should match JSON
|
32
|
+
"""
|
33
|
+
{
|
34
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
35
|
+
"1" : "One",
|
36
|
+
"2" : "Two",
|
37
|
+
"3" : "Three"
|
38
|
+
}
|
39
|
+
"""
|
40
|
+
|
41
|
+
Scenario: Embedded map structure
|
42
|
+
Given I have a file "embeddedmap.yml" containing
|
43
|
+
"""
|
44
|
+
Fruit:
|
45
|
+
- Apples: [ red, green ]
|
46
|
+
- Bananas
|
47
|
+
- Grapes: [ seeded, seedless ]
|
48
|
+
Vegetables:
|
49
|
+
- Beans: [ red, black ]
|
50
|
+
- Sweet Corn
|
51
|
+
- Mirleton
|
52
|
+
"""
|
53
|
+
When I process "embeddedmap.yml"
|
54
|
+
Then the output should match JSON
|
55
|
+
"""
|
56
|
+
{
|
57
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
58
|
+
"Fruit": [
|
59
|
+
{ "Apples": [ "red", "green" ] },
|
60
|
+
"Bananas",
|
61
|
+
{ "Grapes": [ "seeded", "seedless" ] }
|
62
|
+
],
|
63
|
+
"Vegetables": [
|
64
|
+
{ "Beans": [ "red", "black" ] },
|
65
|
+
"Sweet Corn",
|
66
|
+
"Mirleton"
|
67
|
+
]
|
68
|
+
}
|
69
|
+
"""
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature: EL escaping
|
2
|
+
As a CloudFormation user
|
3
|
+
I want to to be able to escape the EL
|
4
|
+
So that I can type whatever text I want
|
5
|
+
|
6
|
+
Scenario: Escape EL
|
7
|
+
Given I have a file "outputs.yml" containing
|
8
|
+
"""
|
9
|
+
EntryPoint:
|
10
|
+
Value: \$(BastionHost.PublicIp)
|
11
|
+
"""
|
12
|
+
When I process "outputs.yml"
|
13
|
+
Then the output should match JSON
|
14
|
+
"""
|
15
|
+
{
|
16
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
17
|
+
"EntryPoint" : {
|
18
|
+
"Value" : "$(BastionHost.PublicIp)"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
"""
|
@@ -0,0 +1,68 @@
|
|
1
|
+
Feature: Expand EL Mapping References
|
2
|
+
As a CloudFormation user
|
3
|
+
I want to use an expression language as a shorthand for mapping references
|
4
|
+
So that I my templates are easier to read
|
5
|
+
|
6
|
+
Scenario: Map reference expansion
|
7
|
+
Given I have a file "outputs.yml" containing
|
8
|
+
"""
|
9
|
+
EntryPoint:
|
10
|
+
Description: IP address of the Bastion Host
|
11
|
+
Value: $(SubnetConfig[VPC][CIDR])
|
12
|
+
"""
|
13
|
+
When I process "outputs.yml"
|
14
|
+
Then the output should match JSON
|
15
|
+
"""
|
16
|
+
{
|
17
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
18
|
+
"EntryPoint" : {
|
19
|
+
"Description" : "IP address of the Bastion Host",
|
20
|
+
"Value" : { "Fn::FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ]}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
"""
|
24
|
+
|
25
|
+
Scenario: Embedded map reference expansion
|
26
|
+
Given I have a file "outputs.yml" containing
|
27
|
+
"""
|
28
|
+
WebSite:
|
29
|
+
Description: URL of the website
|
30
|
+
Value: http://$(Network[Dns][LoadBalancerDnsName])/index.html
|
31
|
+
"""
|
32
|
+
When I process "outputs.yml"
|
33
|
+
Then the output should match JSON
|
34
|
+
"""
|
35
|
+
{
|
36
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
37
|
+
"WebSite" : {
|
38
|
+
"Description" : "URL of the website",
|
39
|
+
"Value" : { "Fn::Join" : [ "", [ "http://", { "Fn::FindInMap" : [ "Network", "Dns", "LoadBalancerDnsName" ]}, "/index.html"]]}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
"""
|
43
|
+
|
44
|
+
Scenario: Map key is reference
|
45
|
+
Given I have a file "nat.yml" containing
|
46
|
+
"""
|
47
|
+
Resources:
|
48
|
+
NATDevice:
|
49
|
+
Type: AWS::EC2::Instance
|
50
|
+
Properties:
|
51
|
+
ImageId: $(AWSNATAMI[$(AWS::Region)][AMI])
|
52
|
+
"""
|
53
|
+
When I process "nat.yml"
|
54
|
+
Then the output should match JSON
|
55
|
+
"""
|
56
|
+
{
|
57
|
+
"AWSTemplateFormatVersion" : "2010-09-09",
|
58
|
+
"Resources" : {
|
59
|
+
"NATDevice" : {
|
60
|
+
"Type" : "AWS::EC2::Instance",
|
61
|
+
"Properties" : {
|
62
|
+
"ImageId" : { "Fn::FindInMap" : [ "AWSNATAMI" , { "Ref" : "AWS::Region" } , "AMI" ] }
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
"""
|
68
|
+
|