cloudformation-ruby-dsl 1.4.6 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa81a5113abb0ee72e9abaac42fc8128012449ce
4
- data.tar.gz: 9a8d10f20443f9ada8534a7dd485bbe40e742883
3
+ metadata.gz: 922a754ed43415e7919a4e4b6793c14ed596ec62
4
+ data.tar.gz: cdbdcedd3c9a48a194c0ba38cc2ddb7462cd5fbf
5
5
  SHA512:
6
- metadata.gz: 0c83e68921de83c6b2cab289b5c3de09a3cde4d306021a4ee262e8f5084319c392951dfa566d8b9528a6a0bbb2bc729ccf73cf974960725a37617efecd8f93bc
7
- data.tar.gz: cead01a51502610a2ad58948f366d827eb4d8f7e52d73d0579e605f79e17d2d200d570b5c71090b78aca35c5f22d4065ac5f9d3784d2807fec78e1dffc88ae5d
6
+ metadata.gz: 63e08da62b61214f641fb651457c1cfb4114ae3eea242a49a6b0939f913184bd5f658471e98176e173c5820ed5fc289e41bf071e99cbd1e0b712be760590295a
7
+ data.tar.gz: ae973485d3a5cfde77175006ee831467ba9ebc4c23231d17b81818741df20f59ff78d10462896af4866ef8d0d5d609b5dffe129f4267fab83ee8257f2defb088
data/OWNERS CHANGED
@@ -1,4 +1,6 @@
1
1
  # Owners.
2
2
 
3
3
  jonaf
4
- temujin9
4
+ temujin9
5
+ mike-unitskyi
6
+ shawnsmith
data/README.md CHANGED
@@ -45,8 +45,8 @@ Make the resulting file executable (`chmod +x [NEW_NAME.rb]`). It can respond to
45
45
  2 - there are differences between an existing stack and your template
46
46
  ```
47
47
  - `validate`: run validation against the stack definition
48
- - `create`: create a new stack from the output
49
- - `update`: update an existing stack from the output. Produces following exit codes:
48
+ - `create`: create a new stack from the output (takes optional `--s3-bucket` to upload the template to the specified S3 bucket prior to creating the stack)
49
+ - `update`: update an existing stack from the output (takes optional `--s3-bucket` to upload the template to the specified S3 bucket prior to creating the stack). Produces following exit codes:
50
50
  ```
51
51
  0 - update finished successfully
52
52
  1 - no updates to perform, stack doesn't exist, unable to update immutable parameter or tag, AWS ServiceError exception
@@ -62,7 +62,7 @@ Command line options similar to cloudformation commands, but parsed by the dsl.
62
62
  - `--stack-name`
63
63
  - `--region`
64
64
  - `--parameters`
65
- - `--tag `
65
+ - `--tag`
66
66
 
67
67
  Any other parameters are passed directly onto cloudformation. (--disable-rollback for instance)
68
68
 
@@ -31,7 +31,7 @@ require 'highline/import'
31
31
 
32
32
  ############################# AWS SDK Support
33
33
 
34
- class AwsCfn
34
+ class AwsClients
35
35
  attr_accessor :cfn_client_instance
36
36
 
37
37
  def initialize(args)
@@ -58,6 +58,13 @@ class AwsCfn
58
58
  end
59
59
  @cfn_client_instance
60
60
  end
61
+
62
+ def s3_client
63
+ if @s3_client_instance == nil
64
+ @s3_client_instance = Aws::S3::Client.new()
65
+ end
66
+ @s3_client_instance
67
+ end
61
68
  end
62
69
 
63
70
  # utility class to deserialize Structs as JSON
@@ -85,13 +92,14 @@ def parse_args
85
92
  :region => default_region,
86
93
  :profile => nil,
87
94
  :nopretty => false,
95
+ :s3_bucket => nil,
88
96
  }
89
97
  ARGV.slice_before(/^--/).each do |name, value|
90
98
  case name
91
99
  when '--stack-name'
92
100
  args[:stack_name] = value
93
101
  when '--parameters'
94
- args[:parameters] = Hash[value.split(/;/).map { |pair| parts = pair.split(/=/, 2); [ parts[0], Parameter.new(parts[1]) ] }] #/# fix for syntax highlighting
102
+ args[:parameters] = Hash[value.split(/;/).map { |pair| parts = pair.split(/=/, 2); [ parts[0], Parameter.new(parts[1]) ] }]
95
103
  when '--interactive'
96
104
  args[:interactive] = true
97
105
  when '--region'
@@ -100,6 +108,8 @@ def parse_args
100
108
  args[:profile] = value
101
109
  when '--nopretty'
102
110
  args[:nopretty] = true
111
+ when '--s3-bucket'
112
+ args[:s3_bucket] = value
103
113
  end
104
114
  end
105
115
 
@@ -151,8 +161,9 @@ def validate_action(action)
151
161
  end
152
162
 
153
163
  def cfn(template)
154
- aws_cfn = AwsCfn.new({:region => template.aws_region, :aws_profile => template.aws_profile})
155
- cfn_client = aws_cfn.cfn_client
164
+ aws_clients = AwsClients.new({:region => template.aws_region, :aws_profile => template.aws_profile})
165
+ cfn_client = aws_clients.cfn_client
166
+ s3_client = aws_clients.s3_client
156
167
 
157
168
  action = validate_action( ARGV[0] )
158
169
 
@@ -170,14 +181,10 @@ def cfn(template)
170
181
 
171
182
  cfn_tags.each {|k, v| cfn_tags[k] = v[:Value].to_s}
172
183
 
173
- if action == 'diff' or (action == 'expand' and not template.nopretty)
174
- template_string = JSON.pretty_generate(template)
175
- else
176
- template_string = JSON.generate(template)
177
- end
184
+ template_string = generate_template(template)
178
185
 
179
186
  # Derive stack name from ARGV
180
- _, options = extract_options(ARGV[1..-1], %w(--nopretty), %w(--profile --stack-name --region --parameters --tag))
187
+ _, options = extract_options(ARGV[1..-1], %w(--nopretty), %w(--profile --stack-name --region --parameters --tag --s3-bucket))
181
188
  # If the first argument is not an option and stack_name is undefined, assume it's the stack name
182
189
  # The second argument, if present, is the resource name used by the describe-resource command
183
190
  if template.stack_name.nil?
@@ -222,7 +229,7 @@ Make the resulting file executable (`chmod +x [NEW_NAME.rb]`). It can respond to
222
229
  - `get-template`: get entire template output of an existing stack
223
230
 
224
231
  Command line options similar to cloudformation commands, but parsed by the dsl.
225
- --profile --stack-name --region --parameters --tag
232
+ --profile --stack-name --region --parameters --tag --s3-bucket
226
233
 
227
234
  Any other parameters are passed directly onto cloudformation. (--disable-rollback for instance)
228
235
 
@@ -237,12 +244,7 @@ template.rb create --stack-name my_stack --parameters "BucketName=bucket-s3-stat
237
244
  when 'expand'
238
245
  # Write the pretty-printed JSON template to stdout and exit. [--nopretty] option writes output with minimal whitespace
239
246
  # example: <template.rb> expand --parameters "Env=prod" --region eu-west-1 --nopretty
240
- if template.nopretty
241
- puts template_string
242
- else
243
- puts template_string
244
- end
245
- exit(true)
247
+ template_string
246
248
 
247
249
  when 'diff'
248
250
  # example: <template.rb> diff my-stack-name --parameters "Env=prod" --region eu-west-1
@@ -332,7 +334,28 @@ template.rb create --stack-name my_stack --parameters "BucketName=bucket-s3-stat
332
334
 
333
335
  when 'validate'
334
336
  begin
335
- valid = cfn_client.validate_template({template_body: template_string})
337
+ validation_payload = {}
338
+ if template.s3_bucket.nil? then
339
+ validation_payload = {template_body: template_string}
340
+ else
341
+ template_path = "#{Time.now.strftime("%s")}/#{stack_name}.json"
342
+ # assumption: JSON is the only supported serialization format (YAML not allowed)
343
+ template_url = "https://s3.amazonaws.com/#{template.s3_bucket}/#{template_path}"
344
+ begin
345
+ s3_client.put_object({
346
+ bucket: template.s3_bucket,
347
+ key: template_path,
348
+ # canned ACL for authorized users to read the bucket (that should be *this* IAM role!)
349
+ acl: "private",
350
+ body: template_string,
351
+ })
352
+ rescue Aws::S3::Errors::ServiceError => e
353
+ $stderr.puts "Failed to upload stack template to S3: #{e}"
354
+ exit(false)
355
+ end
356
+ validation_payload = {template_url: template_url}
357
+ end
358
+ valid = cfn_client.validate_template(validation_payload)
336
359
  if valid.successful?
337
360
  puts "Validation successful"
338
361
  exit(true)
@@ -351,12 +374,34 @@ template.rb create --stack-name my_stack --parameters "BucketName=bucket-s3-stat
351
374
  # default options (not overridable)
352
375
  create_stack_opts = {
353
376
  stack_name: stack_name,
354
- template_body: template_string,
355
377
  parameters: template.parameters.map { |k,v| {parameter_key: k, parameter_value: v}}.to_a,
356
378
  tags: cfn_tags.map { |k,v| {"key" => k.to_s, "value" => v} }.to_a,
357
379
  capabilities: ["CAPABILITY_NAMED_IAM"],
358
380
  }
359
381
 
382
+ # If the user supplied the --s3-bucket option and
383
+ # access to the bucket, upload the template body to S3
384
+ if template.s3_bucket.nil? then
385
+ create_stack_opts["template_body"] = template_string
386
+ else
387
+ template_path = "#{Time.now.strftime("%s")}/#{stack_name}.json"
388
+ # assumption: JSON is the only supported serialization format (YAML not allowed)
389
+ template_url = "https://s3.amazonaws.com/#{template.s3_bucket}/#{template_path}"
390
+ begin
391
+ s3_client.put_object({
392
+ bucket: template.s3_bucket,
393
+ key: template_path,
394
+ # canned ACL for authorized users to read the bucket (that should be *this* IAM role!)
395
+ acl: "private",
396
+ body: template_string,
397
+ })
398
+ rescue Aws::S3::Errors::ServiceError => e
399
+ $stderr.puts "Failed to upload stack template to S3: #{e}"
400
+ exit(false)
401
+ end
402
+ create_stack_opts["template_url"] = template_url
403
+ end
404
+
360
405
  # fill in options from the command line
361
406
  extra_options = parse_arg_array_as_hash(options)
362
407
  create_stack_opts = extra_options.merge(create_stack_opts)
@@ -563,12 +608,29 @@ template.rb create --stack-name my_stack --parameters "BucketName=bucket-s3-stat
563
608
  # default options (not overridable)
564
609
  update_stack_opts = {
565
610
  stack_name: stack_name,
566
- template_body: template_string,
567
611
  parameters: template.parameters.map { |k,v| (v.use_previous_value && old_parameters.include?([k,v])) ? {parameter_key: k, use_previous_value: v.use_previous_value.to_s} : {parameter_key: k, parameter_value: v}}.to_a,
568
612
  tags: cfn_tags.map { |k,v| {"key" => k.to_s, "value" => v.to_s} }.to_a,
569
613
  capabilities: ["CAPABILITY_NAMED_IAM"],
570
614
  }
571
615
 
616
+ # if the the user supplies a bucket bucket and
617
+ # access to it, upload the template body
618
+ if template.s3_bucket.nil? then
619
+ update_stack_opts["template_body"] = template_string
620
+ else
621
+ template_path = "#{Time.now.strftime("%s")}/#{stack_name}.json"
622
+ # assumption: JSON is the only supported serialization format (YAML not allowed)
623
+ template_url = "https://s3.amazonaws.com/#{template.s3_bucket}/#{template_path}"
624
+ s3_client.put_object({
625
+ bucket: template.s3_bucket,
626
+ key: template_path,
627
+ # canned ACL for authorized users to read the bucket (that should be *this* IAM role!)
628
+ acl: "private",
629
+ body: template_string,
630
+ })
631
+ update_stack_opts["template_url"] = template_url
632
+ end
633
+
572
634
  # fill in options from the command line
573
635
  extra_options = parse_arg_array_as_hash(options)
574
636
  update_stack_opts = extra_options.merge(update_stack_opts)
@@ -654,7 +716,10 @@ end
654
716
  ##################################### Additional dsl logic
655
717
  # Core interpreter for the DSL
656
718
  class TemplateDSL < JsonObjectDSL
657
- def exec!()
719
+ def exec!
720
+ puts cfn(self)
721
+ end
722
+ def exec
658
723
  cfn(self)
659
724
  end
660
725
  end
@@ -4,7 +4,7 @@ require 'json'
4
4
 
5
5
  # Formats a template as JSON
6
6
  def generate_template(template)
7
- format_json template, !template.nopretty
7
+ generate_json template, !template.nopretty
8
8
  end
9
9
 
10
10
  def generate_json(data, pretty = true)
@@ -67,7 +67,8 @@ class TemplateDSL < JsonObjectDSL
67
67
  :aws_region,
68
68
  :nopretty,
69
69
  :stack_name,
70
- :aws_profile
70
+ :aws_profile,
71
+ :s3_bucket
71
72
 
72
73
  def initialize(options)
73
74
  @parameters = options.fetch(:parameters, {})
@@ -76,6 +77,7 @@ class TemplateDSL < JsonObjectDSL
76
77
  @aws_region = options.fetch(:region, default_region)
77
78
  @aws_profile = options[:profile]
78
79
  @nopretty = options.fetch(:nopretty, false)
80
+ @s3_bucket = options.fetch(:s3_bucket, nil)
79
81
  super()
80
82
  end
81
83
 
@@ -15,7 +15,7 @@
15
15
  module Cfn
16
16
  module Ruby
17
17
  module Dsl
18
- VERSION = "1.4.6"
18
+ VERSION = "1.5.0"
19
19
  end
20
20
  end
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudformation-ruby-dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.6
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shawn Smith
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2017-03-20 00:00:00.000000000 Z
18
+ date: 2018-03-27 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: detabulator
@@ -210,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
210
  version: '0'
211
211
  requirements: []
212
212
  rubyforge_project:
213
- rubygems_version: 2.5.1
213
+ rubygems_version: 2.4.6
214
214
  signing_key:
215
215
  specification_version: 4
216
216
  summary: Ruby DSL library that provides a wrapper around the CloudFormation. Written