bora 1.3.0 → 1.4.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: 1cd2cfc5042845d206c5fdd8916b6a0212fc943c
4
- data.tar.gz: 3a0f73e893cb10e2d871bfe2e8e364fa9500aaf3
3
+ metadata.gz: bda479f0f99b528601bf7581eb924ea786ccdcb7
4
+ data.tar.gz: 1318e90d4665d1185c07385d684d36d2b1d0fd44
5
5
  SHA512:
6
- metadata.gz: 90dd31bc2e7058cf9e65d9c17d30936c5891943c8d390528e721012b64aef849aa9917192589a316915026af429df1e9ecdec107cfbffdb45f7b364eee0cf4c2
7
- data.tar.gz: 5669c210393f07cf5c337c911f6a885e29d8dd1d3bd139162e5d02d87eeeff40a6d7bf271cbcd9018ce056e020635fd70ec8625c5a9a80d2f714729bf4efb11c
6
+ metadata.gz: c28c0dae89eacea8416d327764a9c1eae4a45cf8a32c230a31c3f7727363ac7a7c4063c66d94fd5d80e26e770205a31c81fd5ffce9e4bedf4e88410d0382146d
7
+ data.tar.gz: 8d2017b83d7b70aa761c5ec03ec3306de17673bc8f6a268a3c0d8c7733102eebfc4698cdfeda62b6dfd39d4e5120dcf0a4c6318b0e6695e394dc7283352a6f8f
data/README.md CHANGED
@@ -230,6 +230,16 @@ params:
230
230
  url: http://${domain}/foo
231
231
  ```
232
232
 
233
+ This even works within array or hash parameters,
234
+ although you can only look up values from the top level params.
235
+
236
+ ```yaml
237
+ params:
238
+ domain: example.com
239
+ site_config:
240
+ url: http://${domain}/foo
241
+ ```
242
+
233
243
 
234
244
  ### Stack Output Lookup
235
245
 
@@ -274,7 +284,14 @@ ${hostedzone://example.com}
274
284
  ${hostedzone://example.com/public}
275
285
  ${hostedzone://example.com/private}
276
286
  ```
287
+ ### AMI Lookup
288
+
289
+ Looks up an AMI given a name prefix which may contain wildcards. If query returns multiple images the latest is used.
277
290
 
291
+ ```bash
292
+ ${ami://amzn-ami-hv*x86_64-gp2?owner=amazon}
293
+ ${ami://my-windows-soe}
294
+ ```
278
295
 
279
296
  ## Overriding Stack Parameters from the Command Line
280
297
 
@@ -35,10 +35,17 @@ class Bora
35
35
  private
36
36
 
37
37
  def process_param_substitutions(val, params)
38
- return val unless val.is_a? String
39
- val.gsub(PLACEHOLDER_REGEX) do |placeholder|
40
- process_placeholder(placeholder, params)
38
+ result = val
39
+ if val.is_a? String
40
+ result = val.gsub(PLACEHOLDER_REGEX) do |placeholder|
41
+ process_placeholder(placeholder, params)
42
+ end
43
+ elsif val.is_a? Array
44
+ result = val.map { |i| process_param_substitutions(i, params) }
45
+ elsif val.is_a? Hash
46
+ result = val.map { |k, v| [k, process_param_substitutions(v, params)] }.to_h
41
47
  end
48
+ result
42
49
  end
43
50
 
44
51
  def process_placeholder(placeholder, params)
@@ -46,17 +53,25 @@ class Bora
46
53
  if !uri.scheme
47
54
  # This token refers to another parameter, rather than a resolver
48
55
  value_to_substitute = params[uri.path]
49
- !value_to_substitute || has_unresolved_placeholder?(value_to_substitute) ? placeholder : value_to_substitute
56
+ return !value_to_substitute || has_unresolved_placeholder?(value_to_substitute) ? placeholder : value_to_substitute
50
57
  else
51
58
  # This token needs to be resolved by a resolver
52
59
  resolver_name = uri.scheme
53
60
  resolver = @resolver_cache[resolver_name] || @loader.load_resolver(resolver_name).new(@stack)
54
- resolver.resolve(uri)
61
+ return resolver.resolve(uri)
55
62
  end
56
63
  end
57
64
 
58
65
  def has_unresolved_placeholder?(val)
59
- val =~ PLACEHOLDER_REGEX
66
+ result = false
67
+ if val.is_a? String
68
+ result = val =~ PLACEHOLDER_REGEX
69
+ elsif val.is_a? Array
70
+ result = val.find { |i| has_unresolved_placeholder?(i) }
71
+ elsif val.is_a? Hash
72
+ result = val.find { |_, v| has_unresolved_placeholder?(v) }
73
+ end
74
+ result
60
75
  end
61
76
 
62
77
  def parse_uri(s)
@@ -0,0 +1,42 @@
1
+ require 'bora/cfn/stack'
2
+
3
+ class Bora
4
+ module Resolver
5
+ class Ami
6
+ NoAMI = Class.new(StandardError)
7
+ InvalidParameter = Class.new(StandardError)
8
+
9
+ def initialize(stack)
10
+ @stack = stack
11
+ end
12
+
13
+ def resolve(uri)
14
+ owner = 'self' # Default to account owner
15
+ ami_prefix = uri.host
16
+ raise InvalidParameter, "Invalid ami parameter #{uri}" unless ami_prefix
17
+ if !uri.query.nil? && uri.query.include?('owner')
18
+ query = URI.decode_www_form(uri.query).to_h
19
+ owner = query['owner']
20
+ end
21
+
22
+ ec2 = Aws::EC2::Client.new(region: @stack.region)
23
+ images = ec2.describe_images(
24
+ owners: [owner],
25
+ filters: [
26
+ {
27
+ name: 'name',
28
+ values: [ami_prefix]
29
+ },
30
+ {
31
+ name: 'state',
32
+ values: ['available']
33
+ }
34
+ ]
35
+ ).images
36
+
37
+ raise NoAMI, "No Matching AMI's for prefix #{ami_prefix}" if images.empty?
38
+ images.sort! { |a, b| DateTime.parse(a.creation_date) <=> DateTime.parse(b.creation_date) }.last.image_id
39
+ end
40
+ end
41
+ end
42
+ end
@@ -26,7 +26,7 @@ class Bora
26
26
  private
27
27
 
28
28
  def resolve_region(uri, stack)
29
- region = uri.host || stack.region || Aws::CloudFormation::Client.new.config[:region]
29
+ region = uri.host || stack.region
30
30
  end
31
31
 
32
32
  def parse_key_context(uri)
@@ -17,6 +17,8 @@ class Bora
17
17
  STACK_OUTPUTS_DO_NOT_EXIST_MESSAGE = "Stack '%s' has no outputs"
18
18
  STACK_PARAMETERS_DO_NOT_EXIST_MESSAGE = "Stack '%s' has no parameters"
19
19
  STACK_VALIDATE_SUCCESS_MESSAGE = "Template for stack '%s' is valid"
20
+ STACK_DIFF_TEMPLATE_UNCHANGED_MESSAGE = "Template has not changed"
21
+ STACK_DIFF_PARAMETERS_UNCHANGED_MESSAGE = "Parameters have not changed"
20
22
 
21
23
  def initialize(stack_name, template_file, stack_config)
22
24
  @stack_name = stack_name
@@ -26,7 +28,7 @@ class Bora
26
28
  end
27
29
  @template_file = template_file
28
30
  @stack_config = stack_config
29
- @region = @stack_config['default_region']
31
+ @region = @stack_config['default_region'] || Aws::CloudFormation::Client.new.config[:region]
30
32
  @cfn_options = extract_cfn_options(stack_config)
31
33
  @cfn_stack = Cfn::Stack.new(@cfn_stack_name, @region)
32
34
  @resolver = ParameterResolver.new(self)
@@ -57,23 +59,8 @@ class Bora
57
59
 
58
60
  def diff(override_params = {}, context_lines = 3)
59
61
  generate(override_params)
60
- diff = Diffy::Diff.new(@cfn_stack.template, @cfn_stack.new_template(@cfn_options),
61
- context: context_lines,
62
- include_diff_info: true)
63
- diff = diff.reject { |line| line =~ /^(---|\+\+\+|\\\\)/ }
64
- diff = diff.map do |line|
65
- case line
66
- when /^\+/
67
- line.chomp.colorize(:green)
68
- when /^-/
69
- line.chomp.colorize(:red)
70
- when /^@@/
71
- line.chomp.colorize(:cyan)
72
- else
73
- line.chomp
74
- end
75
- end
76
- puts diff.join("\n")
62
+ diff_parameters
63
+ diff_template(override_params, context_lines)
77
64
  end
78
65
 
79
66
  def events
@@ -156,6 +143,52 @@ class Bora
156
143
 
157
144
  protected
158
145
 
146
+ def diff_parameters
147
+ if @cfn_stack.parameters && !@cfn_stack.parameters.empty?
148
+ current_params = @cfn_stack.parameters.sort { |a, b| a.key <=> b.key }.map(&:to_s).join("\n") + "\n"
149
+ end
150
+ if @cfn_options[:parameters] && !@cfn_options[:parameters].empty?
151
+ new_params = @cfn_options[:parameters].sort { |a, b|
152
+ a[:parameter_key] <=> b[:parameter_key]
153
+ }.map { |p|
154
+ "#{p[:parameter_key] } - #{p[:parameter_value]}"
155
+ }.join("\n") + "\n"
156
+ end
157
+
158
+ if current_params || new_params
159
+ puts "Parameters".colorize(mode: :bold)
160
+ puts "----------"
161
+ diff = Diffy::Diff.new(current_params, new_params).to_s(String.disable_colorization ? :text : :color).chomp
162
+ puts diff && !diff.empty? ? diff : STACK_DIFF_PARAMETERS_UNCHANGED_MESSAGE
163
+ puts
164
+ end
165
+ end
166
+
167
+ def diff_template(override_params, context_lines)
168
+ diff = Diffy::Diff.new(@cfn_stack.template, @cfn_stack.new_template(@cfn_options),
169
+ context: context_lines,
170
+ include_diff_info: true)
171
+ diff = diff.reject { |line| line =~ /^(---|\+\+\+|\\\\)/ }
172
+ diff = diff.map do |line|
173
+ case line
174
+ when /^\+/
175
+ line.chomp.colorize(:green)
176
+ when /^-/
177
+ line.chomp.colorize(:red)
178
+ when /^@@/
179
+ line.chomp.colorize(:cyan)
180
+ else
181
+ line.chomp
182
+ end
183
+ end
184
+ diff = diff.join("\n")
185
+
186
+ puts "Template".colorize(mode: :bold)
187
+ puts "--------"
188
+ puts diff && !diff.empty? ? diff : STACK_DIFF_TEMPLATE_UNCHANGED_MESSAGE
189
+ puts
190
+ end
191
+
159
192
  def generate(override_params = {}, pretty_json = false)
160
193
  params = resolved_params(override_params)
161
194
  if File.extname(@template_file) == ".rb"
@@ -180,8 +213,7 @@ class Bora
180
213
  end
181
214
 
182
215
  def invoke_action(action, *args)
183
- region_text = @region ? "in region #{@region}" : "in default region"
184
- puts "#{action.capitalize} stack '#{@cfn_stack_name}' #{region_text}"
216
+ puts "#{action.capitalize} stack '#{@cfn_stack_name}' in region #{@region}"
185
217
  success = @cfn_stack.send(action, *args) { |event| puts event }
186
218
  if success
187
219
  puts STACK_ACTION_SUCCESS_MESSAGE % [action.capitalize, @cfn_stack_name]
@@ -205,12 +237,6 @@ class Bora
205
237
  template_body
206
238
  end
207
239
 
208
- def process_params(override_params)
209
- params = @stack_config['params'] || {}
210
- params.merge!(override_params) if override_params
211
- @resolver.resolve(params)
212
- end
213
-
214
240
  def extract_cfn_options(config)
215
241
  valid_options = ["capabilities"]
216
242
  config.select { |k| valid_options.include?(k) }
@@ -1,3 +1,3 @@
1
1
  class Bora
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bora
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Blaxland
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-17 00:00:00.000000000 Z
11
+ date: 2016-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -165,6 +165,7 @@ files:
165
165
  - lib/bora/cli.rb
166
166
  - lib/bora/parameter_resolver.rb
167
167
  - lib/bora/parameter_resolver_loader.rb
168
+ - lib/bora/resolver/ami.rb
168
169
  - lib/bora/resolver/cfn.rb
169
170
  - lib/bora/resolver/credstash.rb
170
171
  - lib/bora/resolver/hostedzone.rb