sfn 3.0.4 → 3.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/docs/command-config.md +12 -0
- data/docs/commands.md +39 -1
- data/lib/sfn/command_module/base.rb +21 -5
- data/lib/sfn/command_module/stack.rb +46 -26
- data/lib/sfn/command_module/template.rb +8 -3
- data/lib/sfn/config/update.rb +6 -0
- data/lib/sfn/planner/aws.rb +5 -1
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3df819d62b28c079cec72e3d62adb265a83f854
|
4
|
+
data.tar.gz: 49e78edc88c14d463e4bd68e1cacb60acf50680d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33d2a858b98d1892197885c934830ef146f44e27a48303a3aa29b1b2ca5a6a46b1db3afcf2737d48d49ac5bc65f0a1bc0b96a62008c3382b48391ae2571db217
|
7
|
+
data.tar.gz: f4662e9cc07cbc33464455e57987903b0bfdf054021d705d0ae1b538b8d56ab4833af0155e67cd2a7ea9e7feafbe9f71fae34bb6dd1343e965f4b54d61d112da
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# v3.0.6
|
2
|
+
* [fix] Cast all value types to String within AWS planner (#194)
|
3
|
+
* [fix] Fix template names on create/update prompting (#197)
|
4
|
+
* [enhancement] Extend validation support for compile time parameters (#199)
|
5
|
+
* [enhancement] Add parameter validation control on stack updates (#198)
|
6
|
+
* [feature] Support remote locations when using apply stack (#196)
|
7
|
+
|
1
8
|
# v3.0.4
|
2
9
|
* [fix] Update parameter values extraction location in planner
|
3
10
|
* [fix] Merge compile time parameters when existing are available
|
data/docs/command-config.md
CHANGED
@@ -109,6 +109,9 @@ $ sfn conf
|
|
109
109
|
| `--parameter` | Description | [DEPRECATED - use `parameters`] Pass template parameters directly (ParamName:ParamValue) |
|
110
110
|
| | Valid | `Bogo::Smash` |
|
111
111
|
| | Default | |
|
112
|
+
| `--parameter-validation` | Description | Stack parameter validation behavior |
|
113
|
+
| | Valid | `String` |
|
114
|
+
| | Default | "default"|
|
112
115
|
| `--parameters` | Description | Pass template parameters directly (Key:Value[,Key:Value,...]) |
|
113
116
|
| | Valid | `Bogo::Smash` |
|
114
117
|
| | Default | |
|
@@ -220,6 +223,9 @@ $ sfn create
|
|
220
223
|
| `--parameter` | Description | [DEPRECATED - use `parameters`] Pass template parameters directly (ParamName:ParamValue) |
|
221
224
|
| | Valid | `Bogo::Smash` |
|
222
225
|
| | Default | |
|
226
|
+
| `--parameter-validation` | Description | Stack parameter validation behavior |
|
227
|
+
| | Valid | `String` |
|
228
|
+
| | Default | "default"|
|
223
229
|
| `--parameters` | Description | Pass template parameters directly (Key:Value[,Key:Value,...]) |
|
224
230
|
| | Valid | `Bogo::Smash` |
|
225
231
|
| | Default | |
|
@@ -433,6 +439,9 @@ $ sfn diff
|
|
433
439
|
| `--parameter` | Description | [DEPRECATED - use `parameters`] Pass template parameters directly (ParamName:ParamValue) |
|
434
440
|
| | Valid | `Bogo::Smash` |
|
435
441
|
| | Default | |
|
442
|
+
| `--parameter-validation` | Description | Stack parameter validation behavior |
|
443
|
+
| | Valid | `String` |
|
444
|
+
| | Default | "default"|
|
436
445
|
| `--parameters` | Description | Pass template parameters directly (Key:Value[,Key:Value,...]) |
|
437
446
|
| | Valid | `Bogo::Smash` |
|
438
447
|
| | Default | |
|
@@ -1165,6 +1174,9 @@ $ sfn update
|
|
1165
1174
|
| `--parameter` | Description | [DEPRECATED - use `parameters`] Pass template parameters directly (ParamName:ParamValue) |
|
1166
1175
|
| | Valid | `Bogo::Smash` |
|
1167
1176
|
| | Default | |
|
1177
|
+
| `--parameter-validation` | Description | Stack parameter validation behavior |
|
1178
|
+
| | Valid | `String` |
|
1179
|
+
| | Default | "default"|
|
1168
1180
|
| `--parameters` | Description | Pass template parameters directly (Key:Value[,Key:Value,...]) |
|
1169
1181
|
| | Valid | `Bogo::Smash` |
|
1170
1182
|
| | Default | |
|
data/docs/commands.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
---
|
2
|
-
title: "Commands"
|
2
|
+
title: "CLI Commands"
|
3
3
|
weight: 4
|
4
4
|
anchors:
|
5
5
|
- title: "Lifecycle commands"
|
@@ -53,6 +53,8 @@ status code. The automatic polling behavior can be disabled:
|
|
53
53
|
$ sfn create my-stack --file my_template --no-poll
|
54
54
|
~~~
|
55
55
|
|
56
|
+
##### Apply stack
|
57
|
+
|
56
58
|
The `--apply-stack` option allows providing the name of an existing
|
57
59
|
stack when creating or updating. Applying stacks is simply fetching
|
58
60
|
the outputs from the applied stacks and automatically defaulting the
|
@@ -103,6 +105,42 @@ when prompted for the stack parameters, we will find the parameter
|
|
103
105
|
value for `LoadBalancerAddress` to be filled in with the output
|
104
106
|
provided from StackA.
|
105
107
|
|
108
|
+
##### Remote location apply stack
|
109
|
+
|
110
|
+
Stacks that are defined in a different region, or within a
|
111
|
+
different provider, can be applied by prefixing stack names with
|
112
|
+
the configured location name. Using the defined `.sfn` configuration:
|
113
|
+
|
114
|
+
~~~ruby
|
115
|
+
Configuration.new do
|
116
|
+
...
|
117
|
+
credentials do
|
118
|
+
provider :aws
|
119
|
+
aws_access_key_id ENV['AWS_ACCESS_KEY_ID']
|
120
|
+
aws_secret_access_key ENV['AWS_SECRET_ACCESS_KEY']
|
121
|
+
aws_region 'us-west-2'
|
122
|
+
end
|
123
|
+
locations do
|
124
|
+
ca_west do
|
125
|
+
provider :aws
|
126
|
+
aws_access_key_id ENV['AWS_ACCESS_KEY_ID']
|
127
|
+
aws_secret_access_key ENV['AWS_SECRET_ACCESS_KEY']
|
128
|
+
aws_region 'us-west-1'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
~~~
|
133
|
+
|
134
|
+
Now, when creating a new stack (which uses the configured credentials
|
135
|
+
targeting `us-west-2`) a stack from the `us-west-1` region can be applied
|
136
|
+
by prefixing the location name to the stack name:
|
137
|
+
|
138
|
+
~~~
|
139
|
+
$ sfn create StackB --apply-stack ca_west__StackA
|
140
|
+
~~~
|
141
|
+
|
142
|
+
_NOTE: Location providers are not required to be common._
|
143
|
+
|
106
144
|
Example of stack creation:
|
107
145
|
|
108
146
|
![stack create](./images/d_create.png)
|
@@ -18,12 +18,24 @@ module Sfn
|
|
18
18
|
[config.fetch(:stack_types, [])].flatten.compact
|
19
19
|
end
|
20
20
|
|
21
|
-
#
|
22
|
-
|
21
|
+
# Build provider connection for given location
|
22
|
+
#
|
23
|
+
# @param location [Symbol, String] name of location
|
24
|
+
# @return [Sfn::Provider]
|
25
|
+
def provider_for(location=nil)
|
26
|
+
key = ['provider', location].compact.map(&:to_s).join('_')
|
27
|
+
if(location)
|
28
|
+
credentials = config.get(:locations, location)
|
29
|
+
unless(credentials)
|
30
|
+
raise ArgumentError.new "Failed to locate provider credentials for location `#{location}`!"
|
31
|
+
end
|
32
|
+
else
|
33
|
+
credentials = config[:credentials]
|
34
|
+
end
|
23
35
|
begin
|
24
|
-
memoize(
|
36
|
+
memoize(key) do
|
25
37
|
result = Sfn::Provider.new(
|
26
|
-
:miasma =>
|
38
|
+
:miasma => credentials,
|
27
39
|
:async => false,
|
28
40
|
:fetch => false
|
29
41
|
)
|
@@ -38,17 +50,21 @@ module Sfn
|
|
38
50
|
config.fetch(:retries, {})
|
39
51
|
)
|
40
52
|
result.connection.data[:retry_ui] = ui
|
53
|
+
result.connection.data[:location] = location.to_s
|
41
54
|
result.connection.data[:locations] = config.fetch(:locations, {})
|
42
55
|
result.connection.data[:retry_type] = retry_config.fetch(:type, :exponential)
|
43
56
|
result.connection.data[:retry_interval] = retry_config.fetch(:interval, 5)
|
44
57
|
result.connection.data[:retry_max] = retry_config.fetch(:max_attempts, 20)
|
45
58
|
result
|
46
59
|
end
|
47
|
-
rescue
|
60
|
+
rescue => e
|
48
61
|
ui.error 'Failed to create remote API connection. Please validate configuration!'
|
62
|
+
ui.error "Connection failure reason - #{e.class} - #{e}"
|
49
63
|
raise
|
50
64
|
end
|
51
65
|
end
|
66
|
+
alias_method :provider, :provider_for
|
67
|
+
|
52
68
|
|
53
69
|
# Write exception information if debug is enabled
|
54
70
|
#
|
@@ -22,7 +22,10 @@ module Sfn
|
|
22
22
|
def apply_stacks!(stack)
|
23
23
|
remote_stacks = [config[:apply_stack]].flatten.compact
|
24
24
|
remote_stacks.each do |stack_name|
|
25
|
-
|
25
|
+
stack_info = stack_name.split('__')
|
26
|
+
stack_info.shift(nil) if stack_info.size == 1
|
27
|
+
stack_location, stack_name = stack_info
|
28
|
+
remote_stack = provider_for(stack_location).stack(stack_name)
|
26
29
|
if(remote_stack)
|
27
30
|
apply_nested_stacks!(remote_stack, stack)
|
28
31
|
mappings = generate_custom_apply_mappings(remote_stack)
|
@@ -60,8 +63,18 @@ module Sfn
|
|
60
63
|
if(config[:apply_mapping])
|
61
64
|
valid_keys = config[:apply_mapping].keys.find_all do |a_key|
|
62
65
|
a_key = a_key.to_s
|
63
|
-
|
64
|
-
|
66
|
+
key_parts = a_key.split('__')
|
67
|
+
case key_parts.size
|
68
|
+
when 3
|
69
|
+
provider_stack.api.data[:location] == key_parts[0] &&
|
70
|
+
provider_stack.name == key_parts[1]
|
71
|
+
when 2
|
72
|
+
provider_stack.name == key_parts[1]
|
73
|
+
when 1
|
74
|
+
true
|
75
|
+
else
|
76
|
+
raise ArgumentError "Invalid name format for apply stack mapping (`#{a_key}`)"
|
77
|
+
end
|
65
78
|
end
|
66
79
|
to_remove = valid_keys.find_all do |key|
|
67
80
|
valid_keys.any?{|v_key| v_key.match(/__#{Regexp.escape(key)}$/)}
|
@@ -69,7 +82,7 @@ module Sfn
|
|
69
82
|
valid_keys -= to_remove
|
70
83
|
Hash[
|
71
84
|
valid_keys.map do |a_key|
|
72
|
-
cut_key = a_key.
|
85
|
+
cut_key = a_key.split('__').last
|
73
86
|
[cut_key, config[:apply_mapping][a_key]]
|
74
87
|
end
|
75
88
|
]
|
@@ -226,32 +239,39 @@ module Sfn
|
|
226
239
|
def validate_stack_parameter(c_stack, p_key, p_ns_key, c_value)
|
227
240
|
stack_value = c_stack.parameters[p_key]
|
228
241
|
p_stack = c_stack.data[:parent_stack]
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
+
unless(config[:parameter_validation] == 'none')
|
243
|
+
if(c_value.is_a?(Hash))
|
244
|
+
case c_value.keys.first
|
245
|
+
when 'Ref'
|
246
|
+
current_value = p_stack.parameters[c_value.values.first]
|
247
|
+
when 'Fn::Att'
|
248
|
+
resource_name, output_name = c_value.values.first.split('.', 2)
|
249
|
+
ref_stack = p_stack.nested_stacks.detect{|i| i.data[:logical_id] == resource_name}
|
250
|
+
if(ref_stack)
|
251
|
+
output = ref_stack.outputs.detect do |o|
|
252
|
+
o.key == output_name
|
253
|
+
end
|
254
|
+
if(output)
|
255
|
+
current_value = output.value
|
256
|
+
end
|
242
257
|
end
|
243
258
|
end
|
259
|
+
else
|
260
|
+
current_value = c_value
|
261
|
+
end
|
262
|
+
if(current_value && current_value.to_s != stack_value.to_s)
|
263
|
+
if(config[:parameter_validation] == 'default')
|
264
|
+
ui.warn 'Nested stack has been altered directly! This update may cause unexpected modifications!'
|
265
|
+
ui.warn "Stack name: #{c_stack.name}. Parameter: #{p_key}. Current value: #{stack_value}. Expected value: #{current_value} (via: #{c_value.inspect})"
|
266
|
+
answer = ui.ask_question("Use current value or expected value for #{p_key} [current/expected]?", :valid => ['current', 'expected'])
|
267
|
+
else
|
268
|
+
answer = config[:parameter_validation]
|
269
|
+
end
|
270
|
+
answer == 'expected'
|
271
|
+
else
|
272
|
+
true
|
244
273
|
end
|
245
274
|
else
|
246
|
-
current_value = c_value
|
247
|
-
end
|
248
|
-
if(current_value && current_value.to_s != stack_value.to_s)
|
249
|
-
ui.warn 'Nested stack has been altered directly! This update may cause unexpected modifications!'
|
250
|
-
ui.warn "Stack name: #{c_stack.name}. Parameter: #{p_key}. Current value: #{stack_value}. Expected value: #{current_value} (via: #{c_value.inspect})"
|
251
|
-
answer = ui.ask_question("Use current value or expected value for #{p_key} [current/expected]?", :valid => ['current', 'expected'])
|
252
|
-
answer == 'expected'
|
253
|
-
else
|
254
|
-
# ui.warn "Unable to check #{p_key} for direct value modification. (Cannot auto-check expected value #{c_value.inspect})"
|
255
275
|
true
|
256
276
|
end
|
257
277
|
end
|
@@ -82,12 +82,17 @@ module Sfn
|
|
82
82
|
else
|
83
83
|
raise ArgumentError.new "Unknown compile time parameter type provided: `#{p_config[:type].inspect}` (Parameter: #{p_name})"
|
84
84
|
end
|
85
|
+
valid = validate_parameter(result, p_config.to_smash)
|
86
|
+
unless(valid == true)
|
87
|
+
result = nil
|
88
|
+
valid.each do |invalid_msg|
|
89
|
+
ui.error invalid_msg.last
|
90
|
+
end
|
91
|
+
end
|
85
92
|
if(result.nil? || (result.respond_to?(:empty?) && result.empty?))
|
86
93
|
if(attempts > MAX_PARAMETER_ATTEMPTS)
|
87
94
|
ui.fatal "Failed to receive allowed parameter! (Parameter: #{p_name})"
|
88
95
|
exit 1
|
89
|
-
else
|
90
|
-
ui.error "Invalid value provided for parameter `#{p_name}`. Must be type: `#{p_config[:type].to_s.capitalize}`"
|
91
96
|
end
|
92
97
|
end
|
93
98
|
end
|
@@ -489,7 +494,7 @@ module Sfn
|
|
489
494
|
t_name.to_s.start_with?(prefix.to_s)
|
490
495
|
end
|
491
496
|
else
|
492
|
-
template_names = sparkle_collection.templates.keys
|
497
|
+
template_names = sparkle_collection.templates.fetch(provider.connection.provider, {}).keys
|
493
498
|
end
|
494
499
|
collections = template_names.map do |t_name|
|
495
500
|
t_name = t_name.to_s.sub(/^#{Regexp.escape(prefix.to_s)}/, '')
|
data/lib/sfn/config/update.rb
CHANGED
@@ -59,6 +59,12 @@ module Sfn
|
|
59
59
|
:description => 'Merge API options defined within configuration on update',
|
60
60
|
:default => false
|
61
61
|
)
|
62
|
+
attribute(
|
63
|
+
:parameter_validation, String,
|
64
|
+
:allowed => ['default', 'none', 'current', 'expected'],
|
65
|
+
:description => 'Stack parameter validation behavior',
|
66
|
+
:default => 'default'
|
67
|
+
)
|
62
68
|
|
63
69
|
end
|
64
70
|
end
|
data/lib/sfn/planner/aws.rb
CHANGED
data/lib/sfn/version.rb
CHANGED
data/sfn.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_runtime_dependency 'miasma-rackspace', '>= 0.1.0', '< 0.3'
|
20
20
|
s.add_runtime_dependency 'miasma-google', '>= 0.1.0', '< 0.3'
|
21
21
|
s.add_runtime_dependency 'net-ssh'
|
22
|
-
s.add_runtime_dependency 'sparkle_formation', '>= 3', '< 4'
|
22
|
+
s.add_runtime_dependency 'sparkle_formation', '>= 3.0.3', '< 4'
|
23
23
|
s.add_runtime_dependency 'hashdiff', '~> 0.2.2'
|
24
24
|
s.add_runtime_dependency 'graph', '~> 2.8.1'
|
25
25
|
s.add_development_dependency 'rake', '~> 10'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sfn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bogo-cli
|
@@ -190,7 +190,7 @@ dependencies:
|
|
190
190
|
requirements:
|
191
191
|
- - ">="
|
192
192
|
- !ruby/object:Gem::Version
|
193
|
-
version:
|
193
|
+
version: 3.0.3
|
194
194
|
- - "<"
|
195
195
|
- !ruby/object:Gem::Version
|
196
196
|
version: '4'
|
@@ -200,7 +200,7 @@ dependencies:
|
|
200
200
|
requirements:
|
201
201
|
- - ">="
|
202
202
|
- !ruby/object:Gem::Version
|
203
|
-
version:
|
203
|
+
version: 3.0.3
|
204
204
|
- - "<"
|
205
205
|
- !ruby/object:Gem::Version
|
206
206
|
version: '4'
|