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.
- 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+++ }}
|