bora 1.3.0 → 1.4.0

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 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