aws-must-templates 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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+++ }}