aws-must-templates 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +390 -0
  3. data/lib/aws-must-templates.rb +2 -0
  4. data/lib/tasks/cross-ref.rb +78 -0
  5. data/lib/tasks/suite.rake +292 -0
  6. data/lib/test-suites/test_suites.rb +115 -0
  7. data/mustache/commonCfnSignal.mustache +34 -0
  8. data/mustache/commonCreationPolicy.mustache +33 -0
  9. data/mustache/commonDependsOn.mustache +25 -0
  10. data/mustache/commonInstanceType.mustache +27 -0
  11. data/mustache/commonKeyValue.mustache +28 -0
  12. data/mustache/commonStackRef.mustache +23 -0
  13. data/mustache/commonValue.mustache +34 -0
  14. data/mustache/initializeCFinit.mustache +27 -0
  15. data/mustache/initializeCFtools.mustache +27 -0
  16. data/mustache/initializeCfnInitHupFiles.mustache +85 -0
  17. data/mustache/initializeInstallAwsCli.mustache +32 -0
  18. data/mustache/initializeInstallChef.mustache +37 -0
  19. data/mustache/initializeProvisionChefZero.mustache +36 -0
  20. data/mustache/initializeStartCfnHup.mustache +25 -0
  21. data/mustache/mapping.mustache +27 -0
  22. data/mustache/mappingSubnetConfig.mustache +27 -0
  23. data/mustache/mappings.mustache +71 -0
  24. data/mustache/output.mustache +38 -0
  25. data/mustache/parameter.mustache +35 -0
  26. data/mustache/resource.mustache +51 -0
  27. data/mustache/resourceInstance.mustache +52 -0
  28. data/mustache/resourceInstanceInitialize.mustache +120 -0
  29. data/mustache/resourceInstanceMetadata.mustache +65 -0
  30. data/mustache/resourceInstanceProfile.mustache +34 -0
  31. data/mustache/resourceInternetGateway.mustache +87 -0
  32. data/mustache/resourcePolicy.mustache +50 -0
  33. data/mustache/resourceProvisionChef.mustache +38 -0
  34. data/mustache/resourceRole.mustache +40 -0
  35. data/mustache/resourceS3Bucket.mustache +39 -0
  36. data/mustache/resourceSecurityGroup.mustache +46 -0
  37. data/mustache/resourceStack.mustache +45 -0
  38. data/mustache/resourceSubnet.mustache +41 -0
  39. data/mustache/resourceUser.mustache +58 -0
  40. data/mustache/resourceVPC.mustache +44 -0
  41. data/mustache/resourceWait.mustache +39 -0
  42. data/mustache/resources.mustache +65 -0
  43. data/mustache/root.mustache +244 -0
  44. data/mustache/tag.mustache +27 -0
  45. data/pics/test-suites.jpg +0 -0
  46. metadata +146 -0
@@ -0,0 +1,292 @@
1
+ # -*- mode: ruby -*-
2
+
3
+ # ------------------------------------------------------------------
4
+ # requires
5
+
6
+ require 'yaml'
7
+ require 'json'
8
+ require 'rake'
9
+ require 'rspec/core/rake_task'
10
+
11
+ # ------------------------------------------------------------------
12
+ # test-suites.yaml
13
+
14
+ require_relative "../test-suites/test_suites.rb"
15
+ test_suites = AwsMustTemplates::TestSuites::TestSuites.new
16
+
17
+ # ------------------------------------------------------------------
18
+ # configs
19
+
20
+ aws_must = "aws-must.rb" # command to conver yaml-configs to cf-templates
21
+
22
+ # read json using aws cli
23
+ describe_stacks_command = "aws cloudformation describe-stacks"
24
+
25
+ # stack states
26
+ SUCESS_STATES = ["CREATE_COMPLETE", "UPDATE_COMPLETE"]
27
+ FAILURE_STATES = ["CREATE_FAILED", "DELETE_FAILED", "UPDATE_ROLLBACK_FAILED", "ROLLBACK_FAILED", "ROLLBACK_COMPLETE","ROLLBACK_FAILED","UPDATE_ROLLBACK_COMPLETE","UPDATE_ROLLBACK_FAILED"]
28
+ END_STATES = SUCESS_STATES + FAILURE_STATES
29
+
30
+
31
+ # ------------------------------------------------------------------
32
+ # namespace :suite
33
+
34
+ namespace :suite do
35
+
36
+ # suite_properties.each{ |a| a.keys.first }
37
+
38
+ # **********
39
+ desc "Run all suites"
40
+ task :all, :gen_opts do |t,args|
41
+ Rake::Task['suite:clean'].invoke()
42
+ Rake::Task['suite:suites'].invoke(args.gen_opts)
43
+ end
44
+
45
+ task :clean do
46
+
47
+ files = FileList[ "#{suite_test_report_dirpath()}/**/*"]
48
+ files.exclude { |f| File.directory?(f) }
49
+
50
+ rm_rf files unless files.empty?
51
+
52
+ end
53
+
54
+ # **********
55
+ all_suites = test_suites.suite_ids.map{ |id| "suite:" + id }
56
+ task :suites, :gen_opts do |t,args|
57
+
58
+ failed_suites = []
59
+
60
+ all_suites.each do |t|
61
+ begin
62
+ Rake::Task[t].invoke( args.gen_opts )
63
+ failed_suites << t unless $?.success?
64
+ # # Run in isolation && continue no matter what
65
+ # sh "rake #{t}; true"
66
+ rescue => e
67
+ puts "#{e.class}: #{e.message}"
68
+ failed_suites << t
69
+ # puts e.backtrace
70
+ puts "continue with next suite"
71
+ end
72
+
73
+ end # all_suites.each
74
+
75
+ if failed_suites.any? then
76
+ puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
77
+ puts "Failed suites"
78
+ puts failed_suites
79
+ puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
80
+ raise "failed_suites=#{failed_suites}"
81
+ end
82
+
83
+ end # task :all
84
+
85
+ # **********
86
+ test_suites.suite_ids.each do |suite_id|
87
+
88
+
89
+ # suite = test_suites.get_suite( suite_id )
90
+
91
+ # find the stack name for suite
92
+ stack = test_suites.get_suite_stack_id( suite_id )
93
+
94
+ # **********
95
+ # Create stack for a suite
96
+ desc "Create stack #{stack} for suite #{suite_id}"
97
+ task "#{suite_id}-stack-create", :gen_opts do |t,args|
98
+ args.with_defaults( :gen_opts => "-m aws-must-templates" )
99
+ json_template="#{aws_must} gen #{stack}.yaml #{args.gen_opts}"
100
+ sh "aws cloudformation create-stack --stack-name #{stack} --capabilities CAPABILITY_IAM --template-body \"$(#{json_template})\" --disable-rollback"
101
+ end
102
+
103
+ desc "Create stack #{stack} for suite #{suite_id}"
104
+ task "#{suite_id}-stack-wait" do
105
+
106
+ while true
107
+
108
+ stack_json = JSON.parse( %x{ #{describe_stacks_command} } )
109
+ stack_json = stack_json["Stacks"].select{ |a| a["StackName"] == stack }.first
110
+ raise "Could not find stack '#{stack}'" unless stack_json
111
+
112
+ break if END_STATES.include?( stack_json["StackStatus"] )
113
+
114
+ print "."
115
+ $stdout.flush
116
+
117
+ sleep 10
118
+
119
+ end
120
+
121
+ end
122
+
123
+
124
+ # **********
125
+ # delete stack for a suite
126
+ desc "Delete stack #{stack} for suite #{suite_id}"
127
+ task "#{suite_id}-stack-delete" do
128
+ sh "aws cloudformation delete-stack --stack-name #{stack}"
129
+ end
130
+
131
+ task :report_dir do
132
+ t = suite_test_report_dirpath()
133
+ sh "mkdir -p #{t}" unless File.exist?(t)
134
+ end
135
+
136
+ # **********
137
+ desc "Show status for stack #{stack}"
138
+ task "#{suite_id}-stack-status" do
139
+ sh "aws cloudformation describe-stacks --stack-name #{stack}"
140
+ end
141
+
142
+ # **********
143
+ # Test common roles for suite
144
+ desc "Suite #{suite_id} - common roles"
145
+ RSpec::Core::RakeTask.new( "#{suite_id}-common" ) do |t|
146
+ puts "------------------------------------------------------------------"
147
+ puts "suite=#{suite_id }"
148
+
149
+ # see spec/spec_helper.rb
150
+ ENV['TARGET_SUITE_ID'] = suite_id
151
+
152
+ # test all roles for the instance
153
+ t.rspec_opts = rspec_opts( suite_id )
154
+ t.fail_on_error = false
155
+ t.ruby_opts= rspec_ruby_opts
156
+ # t.pattern = suite["roles"].map { |r| spec_pattern( r ) }.join(",")
157
+ t.pattern = test_suites.suite_role_ids( suite_id ).map{ |r| spec_pattern( r ) }.join(",")
158
+
159
+
160
+ end if test_suites.suite_roles( suite_id )
161
+
162
+
163
+ # **********
164
+ # Run tasks for suite suite_id
165
+
166
+ desc "Run all takss for suite '#{suite_id}' - {suite['desc']"
167
+ suite_tasks =
168
+ [
169
+ "suite:report_dir",
170
+ [ "suite:#{suite_id}-stack-create", "gen_opts" ],
171
+ "suite:#{suite_id}-stack-wait",
172
+ ] +
173
+ ( Rake::Task.task_defined?( "suite:#{suite_id}-common" ) ? [ "suite:#{suite_id}-common" ] : [] ) +
174
+ # ( suite["instances"] ? suite["instances"].each.map{ |a| "suite:#{suite_id}:" + a.keys.first } : [] ) +
175
+ ( test_suites.suite_instance_ids( suite_id ).each.map{ |instance_id| "suite:#{suite_id}:" + instance_id } ) +
176
+ [ "suite:#{suite_id}-stack-delete" ]
177
+
178
+ task suite_id, :gen_opts do |ta,args|
179
+
180
+ failed_tasks = []
181
+
182
+ suite_tasks.each do |task|
183
+ begin
184
+ if task.kind_of?( Array )
185
+ taskname = task.shift
186
+ Rake::Task[taskname].invoke( *(task.select{ |arg_name| args[arg_name]}.map{ |arg_name| args[arg_name] }) )
187
+ else
188
+ Rake::Task[task].invoke( args )
189
+ end
190
+ failed_tasks << task unless $?.success?
191
+ # # Run in isolation && continue no matter what
192
+ # sh "rake #{t}; true"
193
+ rescue => e
194
+ puts "#{e.class}: #{e.message}"
195
+ failed_tasks << task
196
+ # puts e.backtrace
197
+ puts "continue with next task"
198
+ end
199
+ end
200
+
201
+ if ! failed_tasks.empty? then
202
+ puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
203
+ puts "Failed tasks"
204
+ puts failed_tasks
205
+ puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
206
+ raise "failed_tasks = #{failed_tasks}"
207
+ end
208
+
209
+ end
210
+
211
+
212
+ # instance tasks (within suite)
213
+ namespace suite_id do
214
+
215
+ # suite["instances"].each do |instance_map|
216
+ test_suites.suite_instance_ids( suite_id ).each do |instance_id|
217
+
218
+ # instance_id = instance_map.keys.first
219
+ # instance = instance_map[instance_id]
220
+
221
+ # **********
222
+ desc "Test roles for instance '#{instance_id}' in suite '#{suite_id}'"
223
+ RSpec::Core::RakeTask.new( instance_id ) do |t|
224
+
225
+ puts "------------------------------------------------------------------"
226
+ puts "suite=#{suite_id }, instance=#{instance_id}"
227
+
228
+ # see spec/spec_helper.rb
229
+ ENV['TARGET_SUITE_ID'] = suite_id
230
+ ENV['TARGET_INSTANCE_ID'] = instance_id
231
+
232
+ t.rspec_opts = rspec_opts( suite_id, instance_id )
233
+ t.fail_on_error = false
234
+ t.ruby_opts= rspec_ruby_opts
235
+
236
+ # test all roles for the instance
237
+ t.pattern = test_suites.suite_instance_role_ids( suite_id, instance_id ).map{ |r| spec_pattern( r ) }.join(",")
238
+
239
+ end
240
+ end # instance_ids
241
+ end # ns suite_id
242
+
243
+ end # suite_properties.each
244
+
245
+ # ------------------------------------------------------------------
246
+ # DRY methods
247
+
248
+ # spec found in 'user_test' or 'gem_test' directory
249
+ def spec_pattern( role )
250
+ spec_root="spec/aws-must-templates"
251
+ user_test = File.expand_path( "#{spec_root}/#{role}" )
252
+ gem_test = File.expand_path( File.join( File.dirname( __FILE__), "../..", "#{spec_root}/#{role}" ))
253
+
254
+ return "#{user_test}/*_spec.rb" if File.exist?( user_test )
255
+ return "#{gem_test}/*_spec.rb" if File.exist?( gem_test )
256
+
257
+ message = <<-EOS
258
+
259
+ Could not locate test spec
260
+ in test direcotory '#{user_test}'
261
+ EOS
262
+ message += <<-EOS if user_test != gem_test
263
+ nor in gem test directory '#{gem_test}'
264
+ EOS
265
+ raise message
266
+
267
+ end
268
+
269
+ # use -I option to allow Gem and client specs to include spec_helper
270
+ def rspec_ruby_opts
271
+ "-I #{File.join( File.dirname(__FILE__), '../../spec/support' )}"
272
+ end
273
+
274
+ # to pass to rpsec
275
+ def rspec_opts( suite_id, instance_id=nil )
276
+ # "--format documentation"
277
+ # "--format progress --format documentation --out generated-docs/suites/#{suite_id}#{ instance_id ? '-'+instance_id : ""}.txt"
278
+ "--format progress --format documentation --out #{suite_test_report_filepath( suite_id, instance_id )}"
279
+ end
280
+
281
+ def suite_test_report_filepath( suite_id, instance_id=nil )
282
+ "#{suite_test_report_dirpath()}/#{suite_id}#{ instance_id ? '-' + instance_id : ""}.txt"
283
+ end
284
+
285
+ def suite_test_report_dirpath
286
+ "generated-docs/suites"
287
+ end
288
+
289
+
290
+
291
+ end # ns suite
292
+
@@ -0,0 +1,115 @@
1
+ require 'yaml'
2
+
3
+ module AwsMustTemplates
4
+
5
+ module TestSuites
6
+
7
+ # ------------------------------------------------------------------
8
+ # Constants
9
+ SUITE_CONFIGS = 'test-suites.yaml' # YAML configuration file for suites/instances
10
+
11
+ # ------------------------------------------------------------------
12
+ # class
13
+
14
+ class TestSuites
15
+
16
+ # ------------------------------------------------------------------
17
+ # constructor loads YAML configuration, raise expcetion if not found
18
+ def initialize( )
19
+ yaml_file = SUITE_CONFIGS
20
+
21
+ raise <<-EOS unless File.exist?( yaml_file )
22
+
23
+ No such file '#{yaml_file}'
24
+
25
+ Could not load test-suites configuration file.
26
+
27
+ EOS
28
+
29
+ @suites = YAML.load_file( yaml_file ) || []
30
+ end
31
+
32
+ # ------------------------------------------------------------------
33
+ # return list of suite-ids
34
+ def suite_ids
35
+ return @suites.map{ |suite| suite.keys.first }
36
+ end
37
+
38
+ # ------------------------------------------------------------------
39
+ # return list of suite-roles (i.e. roles not in instances)
40
+ def suite_roles( suite_id )
41
+ suite = get_suite( suite_id )
42
+ return (suite ? suite["roles"] : nil)
43
+ end
44
+
45
+ # ------------------------------------------------------------------
46
+ # return list of suite-roles-ids (i.e. roles not in instances)
47
+ def suite_role_ids( suite_id )
48
+ roles = suite_roles( suite_id )
49
+ return nil unless roles
50
+ return roles.map{ |r| r.is_a?( Hash ) ? r.keys.first : r }
51
+ end
52
+
53
+
54
+ # ------------------------------------------------------------------
55
+ # return list of instanceid for a suite
56
+ def suite_instance_ids( suite_id )
57
+ suite = get_suite( suite_id )
58
+ return nil unless suite
59
+ return suite["instances"] ? suite["instances"].map{ |instance_hash| instance_hash.keys.first } : []
60
+ end
61
+
62
+ # ------------------------------------------------------------------
63
+ # currenty one suite means one to one stack
64
+ alias_method :stack_ids, :suite_ids
65
+
66
+ # return suite configuration for the suite id
67
+ def get_suite( suite_id )
68
+ suite = @suites.select { |suite| suite.keys.first == suite_id }.first
69
+ return suite[suite_id] if suite
70
+ return nil
71
+ end
72
+
73
+ # return suite configuration for the suite id
74
+ def get_suite_stack_id( suite_id )
75
+ return suite_id
76
+ end
77
+
78
+ # return array of role_ids for 'instance_id' in 'suite_id'
79
+ def suite_instance_role_ids( suite_id, instance_id )
80
+ roles = suite_instance_roles( suite_id, instance_id )
81
+ return roles unless roles
82
+ return roles.map{ |r| r.is_a?( Hash ) ? r.keys.first : r }
83
+ end
84
+
85
+ # return roles for 'instance_id' in 'suite_id'
86
+ def suite_instance_roles( suite_id, instance_id )
87
+ instance = suite_instance( suite_id, instance_id )
88
+ return nil unless instance
89
+ return [] unless instance[instance_id]["roles"]
90
+ # roles may be a hash or a string
91
+ return instance[instance_id]["roles"]
92
+ end
93
+
94
+
95
+ # ------------------------------------------------------------------
96
+ # return suite instance
97
+
98
+ private
99
+
100
+ # instance sub document for `instance_id` in `suite_id`
101
+ def suite_instance( suite_id, instance_id )
102
+ suite = get_suite( suite_id )
103
+ return nil unless suite && suite["instances"]
104
+ return suite["instances"].select { |i| i.keys.first == instance_id }.first
105
+ end
106
+
107
+
108
+
109
+ end # class TestSuites
110
+
111
+ end # module TestSuites
112
+
113
+
114
+ end # module AwsMustTemplates
115
+
@@ -0,0 +1,34 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+ ## <a id="commonCfnSignal.mustache"></a>commonCfnSignal.mustache<a class='navigator' href='#top'>[top]</a>
7
+
8
+ **NOT USED**
9
+
10
+ <strike>
11
+ Common template to send a signlan
12
+
13
+ **Attributes**:
14
+
15
+ * `WaitHandle` : to signal
16
+ * `Message` : text message for the signal
17
+
18
+ </strike>
19
+
20
+ +++close+++
21
+
22
+ }}
23
+
24
+
25
+ {{! +++fold-on+++ }}
26
+
27
+ {{# WaitHandle}}
28
+ , "HANDLE='", { "Ref" : "{{WaitHandle}}" }, "'\n"
29
+ , "echo \"Signal success '{{WaitHandle}}' -handle with message '{{Message}}'\" \n"
30
+ , "type cfn-signal && sudo cfn-signal --success true --reason \"{{Message}}\" $HANDLE \n"
31
+ {{/ WaitHandle}}
32
+
33
+
34
+ {{! +++fold-off+++ }}
@@ -0,0 +1,33 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+ ## <a id="commonCreationPolicy.mustache"></a>commonCreationPolicy.mustache<a class='navigator' href='#top'>[top]</a>
7
+
8
+ You associate the CreationPolicy attribute with a resource to prevent its status from reaching create complete until AWS CloudFormation receives a specified number of success signals or the timeout period is exceeded.
9
+
10
+
11
+ **Attributes**:
12
+
13
+ * `CreationPolicy` : sub document defining creation policy
14
+ * `Timeout`: The value must be in ISO8601 duration format, in the
15
+ form: "PT#H#M#S", where each # is the number of hours, minutes,
16
+ and seconds, respectively.
17
+
18
+ +++close+++
19
+
20
+ }}
21
+
22
+ {{! +++fold-on+++ }}
23
+
24
+ {{# CreationPolicy }}
25
+ , "CreationPolicy" : {
26
+ "ResourceSignal": {
27
+ "Timeout": "{{Timeout}}"
28
+ }
29
+ }
30
+ {{/ CreationPolicy }}
31
+
32
+
33
+ {{! +++fold-off+++ }}
@@ -0,0 +1,25 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+ ## <a id="commonDependsOn.mustache"></a>commonDependsOn.mustache<a class='navigator' href='#top'>[top]</a>
7
+
8
+
9
+ Common template to output key and value for `DependsOn`
10
+
11
+ **Attributes**:
12
+
13
+ * `DependsOn` : resource name on which dependency defined
14
+
15
+ +++close+++
16
+
17
+ }}
18
+
19
+ {{! +++fold-on+++ }}
20
+
21
+
22
+ {{# DependsOn }}, "DependsOn" : "{{DependsOn}}" {{/ DependsOn }}
23
+
24
+
25
+ {{! +++fold-off+++ }}
@@ -0,0 +1,27 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+ ## <a id="commonInstanceType.mustache"></a>commonInstanceType.mustache <a class='navigator' href='#top'>[top]</a>
7
+
8
+ Output value for `InstanceType` -attribute
9
+
10
+ **Attributes**:
11
+
12
+ * `InstanceType`: value of instance type
13
+ * `InstanceTypeRef`: reference to instance type
14
+
15
+
16
+
17
+ +++close+++
18
+
19
+ }}
20
+
21
+ {{! +++fold-on+++ }}
22
+
23
+
24
+ {{# InstanceType }}"{{ InstanceType }}"{{/ InstanceType }}
25
+ {{# InstanceTypeRef }}{ "Ref": "{{ InstanceTypeRef }}" }{{/ InstanceTypeRef }}
26
+
27
+ {{! +++fold-off+++ }}
@@ -0,0 +1,28 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+ ## <a id="commonKeyValue.mustache"></a>commonKeyValue.mustache<a class='navigator' href='#top'>[top]</a>
7
+
8
+ Common template to output key-value pair
9
+
10
+ **Attributes**:
11
+
12
+ * `Key`:
13
+ * value given as as commonValue, [commonValue.mustache](#commonValue.mustache)
14
+
15
+ +++close+++
16
+
17
+ }}
18
+
19
+
20
+ {{! +++fold-on+++ }}
21
+
22
+ {
23
+ "Key" : "{{Key}}"
24
+ , "Value" : {{> commonValue }}
25
+ }
26
+
27
+
28
+ {{! +++fold-off+++ }}
@@ -0,0 +1,23 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+ ## <a id="commonStackRef.mustache"></a>commonStackRef.mustache<a class='navigator' href='#top'>[top]</a>
7
+
8
+ Common template to output nested stack reference
9
+
10
+ **Attributes**:
11
+
12
+ * `Stack` : name of the nested stack resource
13
+ * `Output`: name of output variable in nested stack
14
+
15
+ +++close+++
16
+
17
+ }}
18
+
19
+ {{! +++fold-on+++ }}
20
+
21
+ { "Fn::GetAtt": [ "{{Stack}}", "Outputs.{{Output}}"] }
22
+
23
+ {{! +++fold-off+++ }}
@@ -0,0 +1,34 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+ ## <a id="commonValue.mustache"></a>commonValue.mustache<a class='navigator' href='#top'>[top]</a>
7
+
8
+ Common template to output value (Value/Ref/Attr/StackRef)
9
+
10
+ **Attributes**:
11
+
12
+ * `Value` : output value
13
+ * `Ref`: output Ref
14
+ * `StackRef`:
15
+ * `Stack`
16
+ * `Output`
17
+ * `Attr`:
18
+ * `Ref`
19
+ * `Name`
20
+
21
+ +++close+++
22
+
23
+ }}
24
+
25
+ {{! +++fold-on+++ }}
26
+
27
+
28
+ {{#Value}}"{{Value}}"{{/Value}}
29
+ {{#Ref}}{ "Ref": "{{Ref}}" }{{/Ref}}
30
+ {{#Attr}}{ "Fn::GetAtt" : [ "{{Ref}}", "{{Name}}" ] }{{/Attr}}
31
+ {{#StackRef}}{ "Fn::GetAtt": [ "{{Stack}}", "Outputs.{{Output}}"] }{{/StackRef}}
32
+
33
+
34
+ {{! +++fold-off+++ }}
@@ -0,0 +1,27 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+
7
+ ## <a id="initializeCFinit.mustache"></a>initializeCFinit.mustache<a class='navigator' href='#top'> [top]</a>
8
+
9
+ Launch cfn-init to install the files and packages from the metadata
10
+
11
+ **Attributes**:
12
+
13
+ * `Resource`: The logical resource ID of the resource that contains the metadata.
14
+
15
+ +++close+++
16
+
17
+ }}
18
+
19
+ {{! +++fold-on+++ }}
20
+
21
+ , "# Install the files and packages from the metadata\n"
22
+ , "STACK='", { "Ref": "AWS::StackName" }, "'\n"
23
+ , "REGION='", { "Ref": "AWS::Region" }, "'\n"
24
+ , "cfn-init -v --stack $STACK --region $REGION --resource {{Resource}} \n "
25
+
26
+
27
+ {{! +++fold-off+++ }}
@@ -0,0 +1,27 @@
1
+ {{!
2
+
3
+
4
+ +++start+++
5
+
6
+
7
+ ## <a id="initializeCFtools.mustache"></a>initializeCFtools.mustache<a class='navigator' href='#top'> [top]</a>
8
+
9
+ An [adapted](https://gist.github.com/kixorz/10194688) Ubuntu
10
+ CloudFormation Tools installation snippet.
11
+
12
+ **Attributes**:
13
+
14
+ * none
15
+
16
+ +++close+++
17
+
18
+ }}
19
+
20
+
21
+ {{! +++fold-on+++ }}
22
+ , "sudo apt-get -y install python-setuptools \n"
23
+ , "[ -d aws-cfn-bootstrap-latest ] || mkdir aws-cfn-bootstrap-latest \n"
24
+ , "curl https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz | tar xz -C aws-cfn-bootstrap-latest --strip-components 1 \n"
25
+ , "sudo easy_install aws-cfn-bootstrap-latest \n"
26
+
27
+ {{! +++fold-off+++ }}