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 +4 -4
- data/README.md +17 -0
- data/lib/bora/parameter_resolver.rb +21 -6
- data/lib/bora/resolver/ami.rb +42 -0
- data/lib/bora/resolver/credstash.rb +1 -1
- data/lib/bora/stack.rb +52 -26
- data/lib/bora/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bda479f0f99b528601bf7581eb924ea786ccdcb7
|
4
|
+
data.tar.gz: 1318e90d4665d1185c07385d684d36d2b1d0fd44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
39
|
-
val.
|
40
|
-
|
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
|
-
|
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
|
data/lib/bora/stack.rb
CHANGED
@@ -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
|
-
|
61
|
-
|
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
|
-
|
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) }
|
data/lib/bora/version.rb
CHANGED
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.
|
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-
|
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
|