sfn 2.1.0 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/docs/callbacks.md +188 -1
- data/lib/sfn/callback.rb +2 -0
- data/lib/sfn/callback/aws_assume_role.rb +93 -0
- data/lib/sfn/callback/aws_mfa.rb +102 -0
- data/lib/sfn/callback/stack_policy.rb +12 -10
- data/lib/sfn/command/inspect.rb +25 -1
- data/lib/sfn/command/list.rb +1 -1
- data/lib/sfn/command/update.rb +12 -6
- data/lib/sfn/command_module/callbacks.rb +4 -4
- data/lib/sfn/command_module/stack.rb +1 -1
- data/lib/sfn/command_module/template.rb +1 -1
- data/lib/sfn/config/inspect.rb +5 -0
- data/lib/sfn/planner/aws.rb +1 -1
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +4 -2
- metadata +48 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef688f38c0f0be5810c525cd37e77d5a4216756a
|
4
|
+
data.tar.gz: 1f3e4f9a893e376b9c7e77fda5f1e495e27df905
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be3015b69f844371bff9588753a0cec1b9ca1dfb05cb957106583e62ed8a5a9b4284b052938ddb53ace50c8f85f0a73a4884b0131c2948a5d49693f41d3a88d7
|
7
|
+
data.tar.gz: ae268210135a9b5bbc406a1c7684a5e560f16548b21f2b29bd3c8164c66ffe0668c189f995a4c27f86797047f997c3ef3be12d809135b229f86cf3ac049b9225
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# v2.1.2
|
2
|
+
* [enhancement] Include parameter name on error output when failed to receive (#116)
|
3
|
+
* [enhancement] Rescue planner errors and notify user. Allow update to proceed (#124)
|
4
|
+
* [feature] Add built-in callback for AWS MFA support (#123)
|
5
|
+
* [fix] Compare parameters values on updates as String type (#126)
|
6
|
+
* [fix] Remove policy modification on stack delete within AWS (#127)
|
7
|
+
* [feature] Support optional stack policy removal prior to update (#127)
|
8
|
+
* [feature] Add built-in callback for AWS Assume Role credential caching (#128)
|
9
|
+
|
1
10
|
# v2.1.0
|
2
11
|
* [fix] Use SparkleFormation::Collection helper to ensure proper pack ordering (#115)
|
3
12
|
* [fix] Set minimum constraint on sparkle_formation library to 2.1.2
|
data/docs/callbacks.md
CHANGED
@@ -6,6 +6,10 @@ anchors:
|
|
6
6
|
url: "#enabling-callbacks"
|
7
7
|
- title: "Builtin Callbacks"
|
8
8
|
url: "#builtin-callbacks"
|
9
|
+
- title: "Custom Callbacks"
|
10
|
+
url: "#custom-callbacks"
|
11
|
+
- title: "Addon Callbacks"
|
12
|
+
url: "#addon-callbacks"
|
9
13
|
---
|
10
14
|
|
11
15
|
## Callbacks
|
@@ -20,7 +24,7 @@ are generally invoked in two places:
|
|
20
24
|
There are also callbacks available prior to the execution
|
21
25
|
of a command. These can also be isolated to specific commands:
|
22
26
|
|
23
|
-
* `
|
27
|
+
* `after_config` - Prior to the execution of the command.
|
24
28
|
|
25
29
|
### Enabling Callbacks
|
26
30
|
|
@@ -76,8 +80,127 @@ end
|
|
76
80
|
|
77
81
|
Builtin callbacks distributed with `sfn`:
|
78
82
|
|
83
|
+
* AWS Assume Role
|
84
|
+
* AWS MFA
|
79
85
|
* Stack Policy
|
80
86
|
|
87
|
+
#### AWS Assume Role
|
88
|
+
|
89
|
+
When assuming a role via STS on AWS a temporary set of credentials and token
|
90
|
+
are generated for use. This callback will cache these credentials for re-use
|
91
|
+
to prevent re-generation of temporary credentials on every command request.
|
92
|
+
|
93
|
+
To enable the callback:
|
94
|
+
|
95
|
+
~~~ruby
|
96
|
+
Configuration.new do
|
97
|
+
callbacks do
|
98
|
+
default ['aws_assume_role']
|
99
|
+
end
|
100
|
+
end
|
101
|
+
~~~
|
102
|
+
|
103
|
+
Once temporary credentials have been generated, the callback will store the credentials
|
104
|
+
within a file in the working directory named `.sfn-aws`. This path can be modified via
|
105
|
+
configuration:
|
106
|
+
|
107
|
+
~~~ruby
|
108
|
+
Configuration.new do
|
109
|
+
aws_assume_role do
|
110
|
+
cache_file '/custom/path/to/file'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
~~~
|
114
|
+
|
115
|
+
Loading and storage of credentials will only occur if a role is provided to assume. Given
|
116
|
+
a configuration of:
|
117
|
+
|
118
|
+
~~~ruby
|
119
|
+
Configuration.new do
|
120
|
+
callbacks.default 'aws_assume_role'
|
121
|
+
credentials do
|
122
|
+
aws_sts_role_arn ENV['AWS_STS_ROLE']
|
123
|
+
end
|
124
|
+
end
|
125
|
+
~~~
|
126
|
+
|
127
|
+
The callback will be enabled when the environment variable is provided:
|
128
|
+
|
129
|
+
~~~
|
130
|
+
$ AWS_STS_ROLE="arn:...MY_ROLE" sfn list
|
131
|
+
~~~
|
132
|
+
|
133
|
+
and will not be enabled when the environment variable is not provided:
|
134
|
+
|
135
|
+
~~~
|
136
|
+
$ sfn list
|
137
|
+
~~~
|
138
|
+
|
139
|
+
It can also be disabled/enabled via configuration setting:
|
140
|
+
|
141
|
+
~~~ruby
|
142
|
+
Configuration.new do
|
143
|
+
aws_assume_role.status 'enabled'
|
144
|
+
end
|
145
|
+
~~~
|
146
|
+
|
147
|
+
#### AWS Multifactor Authentication
|
148
|
+
|
149
|
+
Support for MFA within AWS can be provided using the AWS MFA callback. It will
|
150
|
+
prompt for an MFA token code which is then used to generate the new session.
|
151
|
+
|
152
|
+
To enable the callback:
|
153
|
+
|
154
|
+
~~~ruby
|
155
|
+
Configuration.new do
|
156
|
+
callbacks do
|
157
|
+
default ['aws_mfa']
|
158
|
+
end
|
159
|
+
end
|
160
|
+
~~~
|
161
|
+
|
162
|
+
The default virtual MFA device ARN will be used when creating the new session. If a
|
163
|
+
non-default virutal MFA device or a hardware device is being used, set the device
|
164
|
+
serial number with the configuration:
|
165
|
+
|
166
|
+
~~~ruby
|
167
|
+
Configuration.new do
|
168
|
+
credentials do
|
169
|
+
provider :aws
|
170
|
+
aws_sts_mfa_serial_number 'DEVICE_IDENTIFIER'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
~~~
|
174
|
+
|
175
|
+
After a session has been successfully created, the callback will store the session
|
176
|
+
token and credentials within a file in the working directory named `.sfn-aws`. This
|
177
|
+
path can be configured via configuration:
|
178
|
+
|
179
|
+
~~~ruby
|
180
|
+
Configuration.new do
|
181
|
+
aws_mfa do
|
182
|
+
cache_file '/custom/path/to/file'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
~~~
|
186
|
+
|
187
|
+
Use of MFA may be conditional based on actions performed. For easier toggling of
|
188
|
+
MFA usage, a configuration value can be used to enable or disable MFA:
|
189
|
+
|
190
|
+
~~~ruby
|
191
|
+
Configuration.new do
|
192
|
+
aws_mfa do
|
193
|
+
cache_file ENV.fetch('SFN_MFA', 'enabled')
|
194
|
+
end
|
195
|
+
end
|
196
|
+
~~~
|
197
|
+
|
198
|
+
With this configuration, MFA usage can be easily disabled:
|
199
|
+
|
200
|
+
~~~
|
201
|
+
$ SFN_MFA=disabled sfn list
|
202
|
+
~~~
|
203
|
+
|
81
204
|
#### Stack Policy Callback
|
82
205
|
|
83
206
|
The Stack Policy Callback utilizes the [policy feature](http://www.sparkleformation.io/docs/sparkle_formation/stack-policies.html)
|
@@ -94,6 +217,18 @@ Configuration.new do
|
|
94
217
|
end
|
95
218
|
~~~
|
96
219
|
|
220
|
+
By default a stack policy is not disabled when an update command is run. This may
|
221
|
+
require multiple update commands to be run first disabling the existing policy, then
|
222
|
+
running the actual update. Stack policies can be automatically removed prior to update
|
223
|
+
allowing the stack to be properly updated with the newly generated policy applied on
|
224
|
+
completion. To disable the stack policy on update, add this to your configuration:
|
225
|
+
|
226
|
+
~~~ruby
|
227
|
+
Configuration.new do
|
228
|
+
stack_policy.update 'defenseless'
|
229
|
+
end
|
230
|
+
~~~
|
231
|
+
|
97
232
|
### Custom Callbacks
|
98
233
|
|
99
234
|
To create a custom callback define a new class within the callback namespace
|
@@ -156,3 +291,55 @@ Configuration.new do
|
|
156
291
|
callbacks.after ['custom_callback']
|
157
292
|
end
|
158
293
|
~~~
|
294
|
+
|
295
|
+
The sfn command will output a notification to the user before a callback is
|
296
|
+
run, and after it has completed. This may be too verbose for some callbacks.
|
297
|
+
A callback may disable this output using the `quiet` method:
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
module Sfn
|
301
|
+
class Callback
|
302
|
+
class MyCallback < Callback
|
303
|
+
|
304
|
+
def quiet
|
305
|
+
true
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
```
|
312
|
+
|
313
|
+
### Addon Callbacks
|
314
|
+
|
315
|
+
#### Usage
|
316
|
+
|
317
|
+
Addon callbacks must be installed to the local bundle, or the system depending
|
318
|
+
on usage type.
|
319
|
+
|
320
|
+
For bundle usage, add the callback to the Gemfile:
|
321
|
+
|
322
|
+
~~~ruby
|
323
|
+
gem 'sfn-callback-name'
|
324
|
+
~~~
|
325
|
+
|
326
|
+
For system usage, install the gem:
|
327
|
+
|
328
|
+
~~~
|
329
|
+
$ gem install sfn-callback-name
|
330
|
+
~~~
|
331
|
+
|
332
|
+
#### Callbacks
|
333
|
+
|
334
|
+
##### sfn-parameters
|
335
|
+
|
336
|
+
Manage stack parameters via files within the project repository.
|
337
|
+
|
338
|
+
* https://github.com/sparkleformation/sfn-parameters
|
339
|
+
|
340
|
+
##### sfn-serverspec
|
341
|
+
|
342
|
+
Define Serverspec rules directly on resources within templates
|
343
|
+
and automatically run after success stack creation or update.
|
344
|
+
|
345
|
+
* https://github.com/sparkleformation/sfn-serverspec
|
data/lib/sfn/callback.rb
CHANGED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Callback
|
5
|
+
# Support for AWS STS role credential caching
|
6
|
+
class AwsAssumeRole < Callback
|
7
|
+
|
8
|
+
# Items to cache in local file
|
9
|
+
STS_STORE_ITEMS = [
|
10
|
+
:aws_sts_token,
|
11
|
+
:aws_sts_access_key_id,
|
12
|
+
:aws_sts_secret_access_key,
|
13
|
+
:aws_sts_token_expires
|
14
|
+
]
|
15
|
+
|
16
|
+
# Prevent callback output to user
|
17
|
+
def quiet
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Inject STS related configuration into
|
22
|
+
# API provider credentials
|
23
|
+
def after_config(*_)
|
24
|
+
if(enabled? && config.fetch(:credentials, :aws_sts_role_arn))
|
25
|
+
load_stored_session
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Store session token if available for
|
30
|
+
# later use
|
31
|
+
def after(*_)
|
32
|
+
if(enabled?)
|
33
|
+
if(api.connection.aws_sts_role_arn && api.connection.aws_sts_token)
|
34
|
+
path = config.fetch(:aws_assume_role, :cache_file, '.sfn-aws')
|
35
|
+
FileUtils.touch(path)
|
36
|
+
File.chmod(0600, path)
|
37
|
+
values = load_stored_values(path)
|
38
|
+
STS_STORE_ITEMS.map do |key|
|
39
|
+
values[key] = api.connection.data[key]
|
40
|
+
end
|
41
|
+
File.open(path, 'w') do |file|
|
42
|
+
file.puts MultiJson.dump(values)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [TrueClass, FalseClass]
|
49
|
+
def enabled?
|
50
|
+
config.fetch(:aws_assume_role, :status, 'enabled').to_s == 'enabled'
|
51
|
+
end
|
52
|
+
|
53
|
+
# Load stored configuration data into the api connection
|
54
|
+
#
|
55
|
+
# @return [TrueClass, FalseClass]
|
56
|
+
def load_stored_session
|
57
|
+
path = config.fetch(:aws_assume_role, :cache_file, '.sfn-aws')
|
58
|
+
if(File.exists?(path))
|
59
|
+
values = load_stored_values(path)
|
60
|
+
STS_STORE_ITEMS.each do |key|
|
61
|
+
api.connection.data[key] = values[key]
|
62
|
+
end
|
63
|
+
if(values[:aws_sts_token_expires])
|
64
|
+
begin
|
65
|
+
api.connection.data[:aws_sts_token_expires] = Time.parse(values[:aws_sts_token_expires])
|
66
|
+
rescue
|
67
|
+
end
|
68
|
+
end
|
69
|
+
true
|
70
|
+
else
|
71
|
+
false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Load stored values
|
76
|
+
#
|
77
|
+
# @param path [String]
|
78
|
+
# @return [Hash]
|
79
|
+
def load_stored_values(path)
|
80
|
+
begin
|
81
|
+
if(File.exists?(path))
|
82
|
+
MultiJson.load(File.read(path)).to_smash
|
83
|
+
else
|
84
|
+
Smash.new
|
85
|
+
end
|
86
|
+
rescue MultiJson::ParseError
|
87
|
+
Smash.new
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Callback
|
5
|
+
# Support for AWS MFA
|
6
|
+
class AwsMfa < Callback
|
7
|
+
|
8
|
+
# Items to cache in local file
|
9
|
+
SESSION_STORE_ITEMS = [
|
10
|
+
:aws_sts_session_token,
|
11
|
+
:aws_sts_session_access_key_id,
|
12
|
+
:aws_sts_session_secret_access_key,
|
13
|
+
:aws_sts_session_token_expires
|
14
|
+
]
|
15
|
+
|
16
|
+
# Prevent callback output to user
|
17
|
+
def quiet
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Inject MFA related configuration into
|
22
|
+
# API provider credentials
|
23
|
+
def after_config(*_)
|
24
|
+
if(enabled?)
|
25
|
+
load_stored_session
|
26
|
+
api.connection.aws_sts_session_token_code = method(:prompt_for_code)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Store session token if available for
|
31
|
+
# later use
|
32
|
+
def after(*_)
|
33
|
+
if(enabled?)
|
34
|
+
if(api.connection.aws_sts_session_token)
|
35
|
+
path = config.fetch(:aws_mfa, :cache_file, '.sfn-aws')
|
36
|
+
FileUtils.touch(path)
|
37
|
+
File.chmod(0600, path)
|
38
|
+
values = load_stored_values(path)
|
39
|
+
SESSION_STORE_ITEMS.map do |key|
|
40
|
+
values[key] = api.connection.data[key]
|
41
|
+
end
|
42
|
+
File.open(path, 'w') do |file|
|
43
|
+
file.puts MultiJson.dump(values)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [TrueClass, FalseClass]
|
50
|
+
def enabled?
|
51
|
+
config.fetch(:aws_mfa, :status, 'enabled').to_s == 'enabled'
|
52
|
+
end
|
53
|
+
|
54
|
+
# Load stored configuration data into the api connection
|
55
|
+
#
|
56
|
+
# @return [TrueClass, FalseClass]
|
57
|
+
def load_stored_session
|
58
|
+
path = config.fetch(:aws_mfa, :cache_file, '.sfn-aws')
|
59
|
+
if(File.exists?(path))
|
60
|
+
values = load_stored_values(path)
|
61
|
+
SESSION_STORE_ITEMS.each do |key|
|
62
|
+
api.connection.data[key] = values[key]
|
63
|
+
end
|
64
|
+
if(values[:aws_sts_session_token_expires])
|
65
|
+
begin
|
66
|
+
api.connection.data[:aws_sts_session_token_expires] = Time.parse(values[:aws_sts_session_token_expires])
|
67
|
+
rescue
|
68
|
+
end
|
69
|
+
end
|
70
|
+
true
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Load stored values
|
77
|
+
#
|
78
|
+
# @param path [String]
|
79
|
+
# @return [Hash]
|
80
|
+
def load_stored_values(path)
|
81
|
+
begin
|
82
|
+
if(File.exists?(path))
|
83
|
+
MultiJson.load(File.read(path)).to_smash
|
84
|
+
else
|
85
|
+
Smash.new
|
86
|
+
end
|
87
|
+
rescue MultiJson::ParseError
|
88
|
+
Smash.new
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Request MFA code from user
|
93
|
+
#
|
94
|
+
# @return [String]
|
95
|
+
def prompt_for_code
|
96
|
+
result = ui.ask 'AWS MFA code', :valid => /^\d{6}$/
|
97
|
+
result.strip
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -41,18 +41,20 @@ module Sfn
|
|
41
41
|
alias_method :after_create, :submit_policy
|
42
42
|
alias_method :after_update, :submit_policy
|
43
43
|
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
# Disable all existing policies prior to update
|
45
|
+
#
|
46
|
+
# @param args [Hash]
|
47
|
+
def before_update(args)
|
48
|
+
if(config.get(:stack_policy, :update).to_s == 'defenseless')
|
49
|
+
ui.warn 'Disabling all stack policies for update.'
|
50
|
+
stack = args[:api_stack]
|
51
|
+
([stack] + stack.nested_stacks).compact.each do |p_stack|
|
52
|
+
@policies[p_stack.name] = DEFENSELESS_POLICY
|
53
|
+
run_action "Disabling stack policy for #{ui.color(p_stack.name, :yellow)}" do
|
54
|
+
save_stack_policy(p_stack)
|
55
|
+
end
|
53
56
|
end
|
54
57
|
end
|
55
|
-
ui.warn "Policy modification for deletion not currently enabled!"
|
56
58
|
end
|
57
59
|
|
58
60
|
# Generate stack policy for stack and cache for the after hook
|
data/lib/sfn/command/inspect.rb
CHANGED
@@ -15,7 +15,7 @@ module Sfn
|
|
15
15
|
stack = provider.connection.stacks.get(stack_name)
|
16
16
|
ui.info "Stack inspection #{ui.color(stack_name, :bold)}:"
|
17
17
|
outputs = api_action!(:api_stack => stack) do
|
18
|
-
[:attribute, :nodes, :instance_failure].map do |key|
|
18
|
+
[:attribute, :nodes, :load_balancers, :instance_failure].map do |key|
|
19
19
|
if(config.has_key?(key))
|
20
20
|
send("display_#{key}", stack)
|
21
21
|
key
|
@@ -160,6 +160,30 @@ module Sfn
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
+
def display_load_balancers(stack)
|
164
|
+
load_balancers = Smash[
|
165
|
+
stack.resources.all.find_all do |resource|
|
166
|
+
resource.within?(:load_balancer, :balancers)
|
167
|
+
end.map do |lb|
|
168
|
+
exp_lb = lb.expand
|
169
|
+
lb_pub_addrs = exp_lb.public_addresses.nil? ? nil : exp_lb.public_addresses.map(&:address)
|
170
|
+
lb_priv_addrs = exp_lb.private_addresses.nil? ? nil : exp_lb.private_addresses.map(&:address)
|
171
|
+
[lb.id, Smash.new(
|
172
|
+
:name => exp_lb.name,
|
173
|
+
:state => exp_lb.state,
|
174
|
+
:public_addresses => lb_pub_addrs,
|
175
|
+
:private_addresses => lb_priv_addrs,
|
176
|
+
:server_states => exp_lb.server_states
|
177
|
+
).delete_if {|k,v| v.nil?}
|
178
|
+
]
|
179
|
+
end
|
180
|
+
]
|
181
|
+
unless load_balancers.empty?
|
182
|
+
ui.info ' Load Balancer Instances:'
|
183
|
+
ui.puts MultiJson.dump(load_balancers, :pretty => true)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
163
187
|
end
|
164
188
|
end
|
165
189
|
end
|
data/lib/sfn/command/list.rb
CHANGED
data/lib/sfn/command/update.rb
CHANGED
@@ -87,12 +87,18 @@ module Sfn
|
|
87
87
|
update_template = stack.template
|
88
88
|
|
89
89
|
if(config[:plan])
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
begin
|
91
|
+
stack.template = original_template
|
92
|
+
stack.parameters = original_parameters
|
93
|
+
plan = build_planner(stack)
|
94
|
+
if(plan)
|
95
|
+
result = plan.generate_plan(file, config_root_parameters)
|
96
|
+
display_plan_information(result)
|
97
|
+
end
|
98
|
+
rescue => e
|
99
|
+
ui.error "Unexpected error when generating plan information: #{e.class} - #{e}"
|
100
|
+
ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
101
|
+
ui.confirm 'Continue with stack update?'
|
96
102
|
end
|
97
103
|
end
|
98
104
|
|
@@ -31,14 +31,14 @@ module Sfn
|
|
31
31
|
clbks = types.map do |c_type|
|
32
32
|
callbacks_for(c_type)
|
33
33
|
end.flatten(1).compact.uniq.each do |item|
|
34
|
-
callback_name, callback = item
|
35
|
-
ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color('starting', :yellow)}"
|
34
|
+
callback_name, callback, quiet = item
|
35
|
+
ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color('starting', :yellow)}" unless quiet
|
36
36
|
if(args.empty?)
|
37
37
|
callback.call
|
38
38
|
else
|
39
39
|
callback.call(*args)
|
40
40
|
end
|
41
|
-
ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color('complete', :green)}"
|
41
|
+
ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color('complete', :green)}" unless quiet
|
42
42
|
end
|
43
43
|
nil
|
44
44
|
end
|
@@ -59,7 +59,7 @@ module Sfn
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
if(instance.respond_to?(type))
|
62
|
-
[c_name, instance.method(type)]
|
62
|
+
[c_name, instance.method(type), instance.respond_to?(:quiet) ? instance.quiet : false]
|
63
63
|
end
|
64
64
|
end.compact
|
65
65
|
end
|
@@ -257,7 +257,7 @@ module Sfn
|
|
257
257
|
else
|
258
258
|
current_value = c_value
|
259
259
|
end
|
260
|
-
if(current_value && current_value != stack_value)
|
260
|
+
if(current_value && current_value.to_s != stack_value.to_s)
|
261
261
|
ui.warn 'Nested stack has been altered directly! This update may cause unexpected modifications!'
|
262
262
|
ui.warn "Stack name: #{c_stack.name}. Parameter: #{p_key}. Current value: #{stack_value}. Expected value: #{current_value} (via: #{c_value.inspect})"
|
263
263
|
answer = ui.ask_question("Use current value or expected value for #{p_key} [current/expected]?", :valid => ['current', 'expected'])
|
@@ -67,7 +67,7 @@ module Sfn
|
|
67
67
|
end
|
68
68
|
if(result.nil? || (result.respond_to?(:empty?) && result.empty?))
|
69
69
|
if(attempts > MAX_PARAMETER_ATTEMPTS)
|
70
|
-
ui.fatal
|
70
|
+
ui.fatal "Failed to receive allowed parameter! (Parameter: #{p_name})"
|
71
71
|
exit 1
|
72
72
|
else
|
73
73
|
ui.error "Invalid value provided for parameter. Must be type: `#{p_config[:type].to_s.capitalize}`"
|
data/lib/sfn/config/inspect.rb
CHANGED
@@ -16,6 +16,11 @@ module Sfn
|
|
16
16
|
:description => 'Locate all instances and display addresses',
|
17
17
|
:short_flag => 'n'
|
18
18
|
)
|
19
|
+
attribute(
|
20
|
+
:load_balancers, [TrueClass, FalseClass],
|
21
|
+
:description => 'Locate all load balancers, display addresses and server states',
|
22
|
+
:short_flag => 'l'
|
23
|
+
)
|
19
24
|
attribute(
|
20
25
|
:instance_failure, [TrueClass, FalseClass],
|
21
26
|
:description => 'Display log file error from failed not if possible',
|
data/lib/sfn/planner/aws.rb
CHANGED
@@ -335,7 +335,7 @@ module Sfn
|
|
335
335
|
resource_name = p_path[1]
|
336
336
|
property_name = p_path[3].sub(/\[\d+\]$/, '')
|
337
337
|
type = templates[:origin]['Resources'][resource_name]['Type']
|
338
|
-
info = SfnAws.registry
|
338
|
+
info = SfnAws.registry.fetch(type, {})
|
339
339
|
effect = info[:full_properties].fetch(property_name, {}).fetch(:update_causes, :unknown).to_sym
|
340
340
|
resource = Smash.new(
|
341
341
|
:name => resource_name,
|
data/lib/sfn/version.rb
CHANGED
data/sfn.gemspec
CHANGED
@@ -11,9 +11,11 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.license = 'Apache-2.0'
|
12
12
|
s.require_path = 'lib'
|
13
13
|
s.add_runtime_dependency 'bogo-cli', '>= 0.2.0', '< 0.4'
|
14
|
-
s.add_runtime_dependency 'miasma', '>= 0.
|
15
|
-
s.add_runtime_dependency 'miasma-aws', '>= 0.
|
14
|
+
s.add_runtime_dependency 'miasma', '>= 0.3.0', '< 0.4'
|
15
|
+
s.add_runtime_dependency 'miasma-aws', '>= 0.3.0', '< 0.4'
|
16
16
|
s.add_runtime_dependency 'miasma-azure', '>= 0.1.0', '< 0.3'
|
17
|
+
s.add_runtime_dependency 'miasma-open-stack', '>= 0.1.0', '< 0.3'
|
18
|
+
s.add_runtime_dependency 'miasma-rackspace', '>= 0.1.0', '< 0.3'
|
17
19
|
s.add_runtime_dependency 'net-ssh'
|
18
20
|
s.add_runtime_dependency 'sparkle_formation', '>= 2.1.2', '< 3'
|
19
21
|
s.add_runtime_dependency 'hashdiff', '~> 0.2.2'
|
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: 2.1.
|
4
|
+
version: 2.1.2
|
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-02-
|
11
|
+
date: 2016-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bogo-cli
|
@@ -36,7 +36,7 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.
|
39
|
+
version: 0.3.0
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '0.4'
|
@@ -46,7 +46,7 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 0.
|
49
|
+
version: 0.3.0
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '0.4'
|
@@ -56,7 +56,7 @@ dependencies:
|
|
56
56
|
requirements:
|
57
57
|
- - ">="
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: 0.
|
59
|
+
version: 0.3.0
|
60
60
|
- - "<"
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '0.4'
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.
|
69
|
+
version: 0.3.0
|
70
70
|
- - "<"
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: '0.4'
|
@@ -90,6 +90,46 @@ dependencies:
|
|
90
90
|
- - "<"
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '0.3'
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: miasma-open-stack
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 0.1.0
|
100
|
+
- - "<"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.3'
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.1.0
|
110
|
+
- - "<"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0.3'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: miasma-rackspace
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 0.1.0
|
120
|
+
- - "<"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0.3'
|
123
|
+
type: :runtime
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 0.1.0
|
130
|
+
- - "<"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.3'
|
93
133
|
- !ruby/object:Gem::Dependency
|
94
134
|
name: net-ssh
|
95
135
|
requirement: !ruby/object:Gem::Requirement
|
@@ -220,6 +260,8 @@ files:
|
|
220
260
|
- lib/sfn.rb
|
221
261
|
- lib/sfn/cache.rb
|
222
262
|
- lib/sfn/callback.rb
|
263
|
+
- lib/sfn/callback/aws_assume_role.rb
|
264
|
+
- lib/sfn/callback/aws_mfa.rb
|
223
265
|
- lib/sfn/callback/stack_policy.rb
|
224
266
|
- lib/sfn/command.rb
|
225
267
|
- lib/sfn/command/conf.rb
|