automan 2.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/.gitignore +17 -0
- data/.rvmrc +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +29 -0
- data/Rakefile +6 -0
- data/automan.gemspec +30 -0
- data/bin/baker +4 -0
- data/bin/mover +4 -0
- data/bin/scanner +4 -0
- data/bin/snapper +4 -0
- data/bin/stacker +4 -0
- data/bin/stalker +4 -0
- data/lib/automan.rb +27 -0
- data/lib/automan/base.rb +64 -0
- data/lib/automan/beanstalk/application.rb +74 -0
- data/lib/automan/beanstalk/configuration.rb +137 -0
- data/lib/automan/beanstalk/deployer.rb +193 -0
- data/lib/automan/beanstalk/errors.rb +22 -0
- data/lib/automan/beanstalk/package.rb +39 -0
- data/lib/automan/beanstalk/router.rb +102 -0
- data/lib/automan/beanstalk/terminator.rb +60 -0
- data/lib/automan/beanstalk/uploader.rb +58 -0
- data/lib/automan/beanstalk/version.rb +100 -0
- data/lib/automan/chef/uploader.rb +30 -0
- data/lib/automan/cli/baker.rb +63 -0
- data/lib/automan/cli/base.rb +14 -0
- data/lib/automan/cli/mover.rb +47 -0
- data/lib/automan/cli/scanner.rb +24 -0
- data/lib/automan/cli/snapper.rb +78 -0
- data/lib/automan/cli/stacker.rb +106 -0
- data/lib/automan/cli/stalker.rb +279 -0
- data/lib/automan/cloudformation/errors.rb +40 -0
- data/lib/automan/cloudformation/launcher.rb +196 -0
- data/lib/automan/cloudformation/replacer.rb +102 -0
- data/lib/automan/cloudformation/terminator.rb +61 -0
- data/lib/automan/cloudformation/uploader.rb +57 -0
- data/lib/automan/ec2/errors.rb +4 -0
- data/lib/automan/ec2/image.rb +137 -0
- data/lib/automan/ec2/instance.rb +83 -0
- data/lib/automan/mixins/aws_caller.rb +115 -0
- data/lib/automan/mixins/utils.rb +18 -0
- data/lib/automan/rds/errors.rb +7 -0
- data/lib/automan/rds/snapshot.rb +244 -0
- data/lib/automan/s3/downloader.rb +25 -0
- data/lib/automan/s3/uploader.rb +20 -0
- data/lib/automan/version.rb +3 -0
- data/lib/automan/wait_rescuer.rb +17 -0
- data/spec/beanstalk/application_spec.rb +49 -0
- data/spec/beanstalk/configuration_spec.rb +98 -0
- data/spec/beanstalk/deployer_spec.rb +162 -0
- data/spec/beanstalk/package_spec.rb +9 -0
- data/spec/beanstalk/router_spec.rb +65 -0
- data/spec/beanstalk/terminator_spec.rb +67 -0
- data/spec/beanstalk/uploader_spec.rb +53 -0
- data/spec/beanstalk/version_spec.rb +60 -0
- data/spec/chef/uploader_spec.rb +9 -0
- data/spec/cloudformation/launcher_spec.rb +240 -0
- data/spec/cloudformation/replacer_spec.rb +58 -0
- data/spec/cloudformation/templates/worker_role.json +337 -0
- data/spec/cloudformation/terminator_spec.rb +63 -0
- data/spec/cloudformation/uploader_spec.rb +50 -0
- data/spec/ec2/image_spec.rb +158 -0
- data/spec/ec2/instance_spec.rb +57 -0
- data/spec/mixins/aws_caller_spec.rb +39 -0
- data/spec/mixins/utils_spec.rb +44 -0
- data/spec/rds/snapshot_spec.rb +152 -0
- metadata +278 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
require 'automan'
|
|
2
|
+
|
|
3
|
+
module Automan::Cli
|
|
4
|
+
class Stalker < Base
|
|
5
|
+
|
|
6
|
+
desc "alias", "point dns to elb"
|
|
7
|
+
|
|
8
|
+
option :environment_name,
|
|
9
|
+
required: true,
|
|
10
|
+
aliases: "-e",
|
|
11
|
+
desc: "Beanstalk environment containing target ELB"
|
|
12
|
+
|
|
13
|
+
option :hosted_zone_name,
|
|
14
|
+
required: true,
|
|
15
|
+
aliases: "-z",
|
|
16
|
+
desc: "Hosted zone for which apex will be routed to ELB"
|
|
17
|
+
|
|
18
|
+
option :hostname,
|
|
19
|
+
required: true,
|
|
20
|
+
aliases: "-h",
|
|
21
|
+
desc: "Alias to create (must be fqdn, e.g. 'dev1.dydev.me')"
|
|
22
|
+
|
|
23
|
+
def alias
|
|
24
|
+
Automan::Beanstalk::Router.new(options).run
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc "deploy", "deploy a beanstalk service"
|
|
28
|
+
|
|
29
|
+
option :name,
|
|
30
|
+
required: true,
|
|
31
|
+
aliases: "-n",
|
|
32
|
+
desc: "name of the service"
|
|
33
|
+
|
|
34
|
+
option :environment,
|
|
35
|
+
required: true,
|
|
36
|
+
aliases: "-e",
|
|
37
|
+
desc: "environment tag (e.g. dev, stage, prd)"
|
|
38
|
+
|
|
39
|
+
option :version_label,
|
|
40
|
+
aliases: "-l",
|
|
41
|
+
desc: "beanstalk application version label"
|
|
42
|
+
|
|
43
|
+
option :package,
|
|
44
|
+
aliases: "-p",
|
|
45
|
+
desc: "s3 path to version package (s3://bucket/package.zip)"
|
|
46
|
+
|
|
47
|
+
option :manifest,
|
|
48
|
+
aliases: "-m",
|
|
49
|
+
desc: "s3 path to manifest file containing version label and package location"
|
|
50
|
+
|
|
51
|
+
option :configuration_template,
|
|
52
|
+
required: true,
|
|
53
|
+
aliases: "-t",
|
|
54
|
+
desc: "beanstalk configuration template name"
|
|
55
|
+
|
|
56
|
+
option :beanstalk_name,
|
|
57
|
+
aliases: "-b",
|
|
58
|
+
desc: "alternate beanstalk environment name"
|
|
59
|
+
|
|
60
|
+
option :number_to_keep,
|
|
61
|
+
aliases: "-n",
|
|
62
|
+
type: :numeric,
|
|
63
|
+
desc: "cull old versions and keep newest NUMBER_TO_KEEP"
|
|
64
|
+
|
|
65
|
+
def deploy
|
|
66
|
+
# you must specify either a manifest file or both package and version label
|
|
67
|
+
if options[:manifest].nil? &&
|
|
68
|
+
(options[:version_label].nil? || options[:package].nil?)
|
|
69
|
+
puts "Must specify either manifest or both version_label and package"
|
|
70
|
+
help "deploy"
|
|
71
|
+
exit 1
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
Automan::Beanstalk::Deployer.new(options).deploy
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
desc "terminate", "terminate a beanstalk environment"
|
|
78
|
+
|
|
79
|
+
option :name,
|
|
80
|
+
required: true,
|
|
81
|
+
aliases: "-n",
|
|
82
|
+
desc: "name of the beanstalk environment"
|
|
83
|
+
|
|
84
|
+
def terminate
|
|
85
|
+
Automan::Beanstalk::Terminator.new(options).terminate
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
desc "create-app", "create beanstalk application"
|
|
89
|
+
|
|
90
|
+
option :name,
|
|
91
|
+
required: true,
|
|
92
|
+
aliases: "-n",
|
|
93
|
+
desc: "name of the application"
|
|
94
|
+
|
|
95
|
+
def create_app
|
|
96
|
+
Automan::Beanstalk::Application.new(options).create
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
desc "delete-app", "delete beanstalk application"
|
|
100
|
+
|
|
101
|
+
option :name,
|
|
102
|
+
required: true,
|
|
103
|
+
aliases: "-n",
|
|
104
|
+
desc: "name of the application"
|
|
105
|
+
|
|
106
|
+
def delete_app
|
|
107
|
+
Automan::Beanstalk::Application.new(options).delete
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
desc "create-config", "create beanstalk configuration template"
|
|
111
|
+
|
|
112
|
+
option :name,
|
|
113
|
+
required: true,
|
|
114
|
+
aliases: "-n",
|
|
115
|
+
desc: "name of the configuration template"
|
|
116
|
+
|
|
117
|
+
option :application,
|
|
118
|
+
required: true,
|
|
119
|
+
aliases: "-a",
|
|
120
|
+
desc: "name of the application"
|
|
121
|
+
|
|
122
|
+
option :template,
|
|
123
|
+
required: true,
|
|
124
|
+
aliases: "-t",
|
|
125
|
+
desc: "file containing configuration options"
|
|
126
|
+
|
|
127
|
+
option :platform,
|
|
128
|
+
required: "true",
|
|
129
|
+
aliases: "-p",
|
|
130
|
+
default: "64bit Windows Server 2012 running IIS 8",
|
|
131
|
+
desc: "beanstalk solution stack name"
|
|
132
|
+
|
|
133
|
+
def create_config
|
|
134
|
+
Automan::Beanstalk::Configuration.new(options).create
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
desc "update-config", "update beanstalk configuration template"
|
|
138
|
+
|
|
139
|
+
option :name,
|
|
140
|
+
required: true,
|
|
141
|
+
aliases: "-n",
|
|
142
|
+
desc: "name of the configuration template"
|
|
143
|
+
|
|
144
|
+
option :application,
|
|
145
|
+
required: true,
|
|
146
|
+
aliases: "-a",
|
|
147
|
+
desc: "name of the application"
|
|
148
|
+
|
|
149
|
+
option :template,
|
|
150
|
+
required: true,
|
|
151
|
+
aliases: "-t",
|
|
152
|
+
desc: "file containing configuration options"
|
|
153
|
+
|
|
154
|
+
option :platform,
|
|
155
|
+
required: "true",
|
|
156
|
+
aliases: "-p",
|
|
157
|
+
default: "64bit Windows Server 2012 running IIS 8",
|
|
158
|
+
desc: "beanstalk solution stack name"
|
|
159
|
+
|
|
160
|
+
def update_config
|
|
161
|
+
Automan::Beanstalk::Configuration.new(options).update
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
desc "delete-config", "delete beanstalk configuration template"
|
|
165
|
+
|
|
166
|
+
option :name,
|
|
167
|
+
required: true,
|
|
168
|
+
aliases: "-n",
|
|
169
|
+
desc: "name of the configuration template"
|
|
170
|
+
|
|
171
|
+
option :application,
|
|
172
|
+
required: true,
|
|
173
|
+
aliases: "-a",
|
|
174
|
+
desc: "name of the application"
|
|
175
|
+
|
|
176
|
+
def delete_config
|
|
177
|
+
Automan::Beanstalk::Configuration.new(options).delete
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
desc "upload-config", "validate and upload beanstalk configuration template files to s3"
|
|
181
|
+
|
|
182
|
+
option :template_files,
|
|
183
|
+
required: true,
|
|
184
|
+
aliases: "-t",
|
|
185
|
+
desc: "File system glob of configuration templates to upload"
|
|
186
|
+
|
|
187
|
+
option :s3_path,
|
|
188
|
+
required: true,
|
|
189
|
+
aliases: "-p",
|
|
190
|
+
desc: "S3 path to destination"
|
|
191
|
+
|
|
192
|
+
def upload_config
|
|
193
|
+
Automan::Beanstalk::Uploader.new(options).upload_config_templates
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
desc "delete-version", "delete an application version"
|
|
197
|
+
|
|
198
|
+
option :application,
|
|
199
|
+
required: true,
|
|
200
|
+
aliases: "-a",
|
|
201
|
+
desc: "name of the application"
|
|
202
|
+
|
|
203
|
+
option :label,
|
|
204
|
+
required: true,
|
|
205
|
+
aliases: "-l",
|
|
206
|
+
desc: "version label to be deleted"
|
|
207
|
+
|
|
208
|
+
def delete_version
|
|
209
|
+
Automan::Beanstalk::Version.new(options).delete
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
desc "cull-versions", "delete oldest versions, keeping N newest"
|
|
213
|
+
|
|
214
|
+
option :application,
|
|
215
|
+
required: true,
|
|
216
|
+
aliases: "-a",
|
|
217
|
+
desc: "name of the application"
|
|
218
|
+
|
|
219
|
+
option :number_to_keep,
|
|
220
|
+
required: true,
|
|
221
|
+
aliases: "-n",
|
|
222
|
+
type: :numeric,
|
|
223
|
+
desc: "keep newest NUMBER_TO_KEEP versions"
|
|
224
|
+
|
|
225
|
+
def cull_versions
|
|
226
|
+
Automan::Beanstalk::Version.new(options).cull_versions(options[:number_to_keep])
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
desc "show-versions", "show all versions for an application"
|
|
230
|
+
|
|
231
|
+
option :application,
|
|
232
|
+
required: true,
|
|
233
|
+
aliases: "-a",
|
|
234
|
+
desc: "name of the application"
|
|
235
|
+
|
|
236
|
+
def show_versions
|
|
237
|
+
versions = Automan::Beanstalk::Version.new(options).versions
|
|
238
|
+
versions.each do |v|
|
|
239
|
+
tokens = [
|
|
240
|
+
v[:application_name],
|
|
241
|
+
v[:version_label],
|
|
242
|
+
v[:date_created].iso8601
|
|
243
|
+
]
|
|
244
|
+
say tokens.join("\t")
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
desc "package", "upload a zip file to s3 to be deployed to beanstalk"
|
|
249
|
+
|
|
250
|
+
option :destination,
|
|
251
|
+
required: true,
|
|
252
|
+
aliases: "-d",
|
|
253
|
+
desc: "full s3 path of uploaded package"
|
|
254
|
+
|
|
255
|
+
option :source,
|
|
256
|
+
required: true,
|
|
257
|
+
aliases: "-s",
|
|
258
|
+
desc: "path to local zip file to be uploaded"
|
|
259
|
+
|
|
260
|
+
option :manifest,
|
|
261
|
+
aliases: "-m",
|
|
262
|
+
desc: "if set, also upload a manifest file with full s3 path MANIFEST"
|
|
263
|
+
|
|
264
|
+
option :version_label,
|
|
265
|
+
aliases: "-l",
|
|
266
|
+
desc: "version_label for manifest, required if -m"
|
|
267
|
+
|
|
268
|
+
def package
|
|
269
|
+
|
|
270
|
+
if !options[:manifest].nil? && options[:version_label].nil?
|
|
271
|
+
puts "Must specify version_label when uploading manifest file"
|
|
272
|
+
help "package"
|
|
273
|
+
exit 1
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
Automan::Beanstalk::Package.new(options).upload_package
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Automan::Cloudformation
|
|
2
|
+
class MissingParametersError < StandardError
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
class BadTemplateError < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class StackExistsError < StandardError
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class StackDoesNotExistError < StandardError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class StackBrokenError < StandardError
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class StackDeletionError < StandardError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class StackCreationError < StandardError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class StackUpdateError < StandardError
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class WaitTimedOutError < StandardError
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class MissingAutoScalingGroupError < StandardError
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class MissingManifestError < StandardError
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class NoTemplatesError < StandardError
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class InvalidTemplateError < StandardError
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
require 'automan'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
# TODO: add timeout
|
|
5
|
+
|
|
6
|
+
module Automan::Cloudformation
|
|
7
|
+
class Launcher < Automan::Base
|
|
8
|
+
add_option :name,
|
|
9
|
+
:template,
|
|
10
|
+
:disable_rollback,
|
|
11
|
+
:enable_iam,
|
|
12
|
+
:enable_update,
|
|
13
|
+
:parameters,
|
|
14
|
+
:manifest,
|
|
15
|
+
:wait_for_completion
|
|
16
|
+
|
|
17
|
+
include Automan::Mixins::Utils
|
|
18
|
+
|
|
19
|
+
def initialize(options=nil)
|
|
20
|
+
@wait_for_completion = false
|
|
21
|
+
super
|
|
22
|
+
@wait = Wait.new({
|
|
23
|
+
delay: 120,
|
|
24
|
+
attempts: 15, # 15 x 2m == 30m
|
|
25
|
+
debug: true,
|
|
26
|
+
rescuer: WaitRescuer.new(),
|
|
27
|
+
logger: @logger
|
|
28
|
+
})
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def manifest_exists?
|
|
32
|
+
s3_object_exists? manifest
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def read_manifest
|
|
36
|
+
if !manifest_exists?
|
|
37
|
+
raise MissingManifestError, "Manifest #{manifest} does not exist"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# read manifest from s3 location
|
|
41
|
+
json = s3_read(manifest)
|
|
42
|
+
|
|
43
|
+
# parse it from json
|
|
44
|
+
data = JSON.parse json
|
|
45
|
+
|
|
46
|
+
# merge manifest parameters into cli parameters
|
|
47
|
+
parameters.merge!(data)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def template_handle(template_path)
|
|
51
|
+
if looks_like_s3_path? template_path
|
|
52
|
+
bucket, key = parse_s3_path template_path
|
|
53
|
+
return s3.buckets[bucket].objects[key]
|
|
54
|
+
else
|
|
55
|
+
return File.read(template_path)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def parse_template_parameters
|
|
60
|
+
cfn.validate_template( template_handle(template) )
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def validate_parameters
|
|
64
|
+
if parameters.nil?
|
|
65
|
+
raise MissingParametersError, "there are no parameters!"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
template_params_hash = parse_template_parameters
|
|
69
|
+
|
|
70
|
+
if template_params_hash.has_key? :code
|
|
71
|
+
mesg = template_params_hash[:message]
|
|
72
|
+
raise BadTemplateError, "template did not validate: #{mesg}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# make sure any template parameters w/o a default are specified
|
|
76
|
+
template_params = template_params_hash[:parameters]
|
|
77
|
+
required_params = template_params.select { |x| !x.has_key? :default_value}
|
|
78
|
+
required_params.each do |rp|
|
|
79
|
+
unless parameters.has_key? rp[:parameter_key]
|
|
80
|
+
raise MissingParametersError, "required parameter #{rp[:parameter_key]} was not specified"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# add iam capabilities if needed
|
|
85
|
+
if template_params_hash.has_key?(:capabilities) &&
|
|
86
|
+
template_params_hash[:capabilities].include?('CAPABILITY_IAM')
|
|
87
|
+
self.enable_iam = true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def stack_exists?
|
|
93
|
+
cfn.stacks[name].exists?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def stack_status
|
|
97
|
+
cfn.stacks[name].status
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def stack_launch_complete?
|
|
101
|
+
case stack_status
|
|
102
|
+
when 'CREATE_COMPLETE'
|
|
103
|
+
true
|
|
104
|
+
when 'CREATE_FAILED', /^ROLLBACK_/
|
|
105
|
+
raise StackCreationError, "Stack #{name} failed to launch"
|
|
106
|
+
else
|
|
107
|
+
false
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def stack_update_complete?
|
|
112
|
+
case stack_status
|
|
113
|
+
when 'UPDATE_COMPLETE'
|
|
114
|
+
true
|
|
115
|
+
when 'UPDATE_FAILED', /^UPDATE_ROLLBACK_/
|
|
116
|
+
raise StackUpdateError, "Stack #{name} failed to update"
|
|
117
|
+
else
|
|
118
|
+
false
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def launch
|
|
123
|
+
opts = {
|
|
124
|
+
parameters: parameters
|
|
125
|
+
}
|
|
126
|
+
opts[:capabilities] = ['CAPABILITY_IAM'] if enable_iam
|
|
127
|
+
opts[:disable_rollback] = disable_rollback
|
|
128
|
+
|
|
129
|
+
logger.info "launching stack #{name}"
|
|
130
|
+
cfn.stacks.create name, template_handle(template), opts
|
|
131
|
+
|
|
132
|
+
if wait_for_completion
|
|
133
|
+
logger.info "waiting for stack #{name} to launch"
|
|
134
|
+
wait_until { stack_launch_complete? }
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def update_stack(name, opts)
|
|
139
|
+
cfn.stacks[name].update( opts )
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def update
|
|
143
|
+
opts = {
|
|
144
|
+
template: template_handle(template),
|
|
145
|
+
parameters: parameters
|
|
146
|
+
}
|
|
147
|
+
opts[:capabilities] = ['CAPABILITY_IAM'] if enable_iam
|
|
148
|
+
|
|
149
|
+
logger.info "updating stack #{name}"
|
|
150
|
+
|
|
151
|
+
# if cfn determines that no updates are to be performed,
|
|
152
|
+
# it raises a ValidationError
|
|
153
|
+
begin
|
|
154
|
+
update_stack(name, opts)
|
|
155
|
+
rescue AWS::CloudFormation::Errors::ValidationError => e
|
|
156
|
+
if e.message != "No updates are to be performed."
|
|
157
|
+
raise e
|
|
158
|
+
else
|
|
159
|
+
logger.info e.message
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if wait_for_completion
|
|
164
|
+
logger.info "waiting for stack #{name} to update"
|
|
165
|
+
wait_until { stack_update_complete? }
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def launch_or_update
|
|
171
|
+
|
|
172
|
+
if !manifest.nil?
|
|
173
|
+
read_manifest
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
log_options
|
|
177
|
+
|
|
178
|
+
validate_parameters
|
|
179
|
+
|
|
180
|
+
if stack_exists?
|
|
181
|
+
|
|
182
|
+
logger.info "stack #{name} exists"
|
|
183
|
+
if enable_update == true
|
|
184
|
+
update
|
|
185
|
+
else
|
|
186
|
+
raise StackExistsError, "stack #{name} already exists"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
else
|
|
190
|
+
launch
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
end
|