aws-must-templates 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +390 -0
- data/lib/aws-must-templates.rb +2 -0
- data/lib/tasks/cross-ref.rb +78 -0
- data/lib/tasks/suite.rake +292 -0
- data/lib/test-suites/test_suites.rb +115 -0
- data/mustache/commonCfnSignal.mustache +34 -0
- data/mustache/commonCreationPolicy.mustache +33 -0
- data/mustache/commonDependsOn.mustache +25 -0
- data/mustache/commonInstanceType.mustache +27 -0
- data/mustache/commonKeyValue.mustache +28 -0
- data/mustache/commonStackRef.mustache +23 -0
- data/mustache/commonValue.mustache +34 -0
- data/mustache/initializeCFinit.mustache +27 -0
- data/mustache/initializeCFtools.mustache +27 -0
- data/mustache/initializeCfnInitHupFiles.mustache +85 -0
- data/mustache/initializeInstallAwsCli.mustache +32 -0
- data/mustache/initializeInstallChef.mustache +37 -0
- data/mustache/initializeProvisionChefZero.mustache +36 -0
- data/mustache/initializeStartCfnHup.mustache +25 -0
- data/mustache/mapping.mustache +27 -0
- data/mustache/mappingSubnetConfig.mustache +27 -0
- data/mustache/mappings.mustache +71 -0
- data/mustache/output.mustache +38 -0
- data/mustache/parameter.mustache +35 -0
- data/mustache/resource.mustache +51 -0
- data/mustache/resourceInstance.mustache +52 -0
- data/mustache/resourceInstanceInitialize.mustache +120 -0
- data/mustache/resourceInstanceMetadata.mustache +65 -0
- data/mustache/resourceInstanceProfile.mustache +34 -0
- data/mustache/resourceInternetGateway.mustache +87 -0
- data/mustache/resourcePolicy.mustache +50 -0
- data/mustache/resourceProvisionChef.mustache +38 -0
- data/mustache/resourceRole.mustache +40 -0
- data/mustache/resourceS3Bucket.mustache +39 -0
- data/mustache/resourceSecurityGroup.mustache +46 -0
- data/mustache/resourceStack.mustache +45 -0
- data/mustache/resourceSubnet.mustache +41 -0
- data/mustache/resourceUser.mustache +58 -0
- data/mustache/resourceVPC.mustache +44 -0
- data/mustache/resourceWait.mustache +39 -0
- data/mustache/resources.mustache +65 -0
- data/mustache/root.mustache +244 -0
- data/mustache/tag.mustache +27 -0
- data/pics/test-suites.jpg +0 -0
- 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+++ }}
|