sfn 3.0.32 → 3.1.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/CHANGELOG.md +5 -0
- data/bin/command-config-generator +34 -14
- data/docs/command-config.md +338 -1
- data/docs/commands.md +56 -10
- data/docs/usage.md +1 -0
- data/lib/sfn.rb +1 -0
- data/lib/sfn/command.rb +1 -0
- data/lib/sfn/command/import.rb +8 -1
- data/lib/sfn/command/plan.rb +8 -51
- data/lib/sfn/command/realize.rb +82 -0
- data/lib/sfn/command/update.rb +1 -1
- data/lib/sfn/command_module/planning.rb +6 -2
- data/lib/sfn/command_module/stack.rb +11 -3
- data/lib/sfn/command_module/template.rb +5 -1
- data/lib/sfn/config.rb +9 -1
- data/lib/sfn/config/plan.rb +18 -0
- data/lib/sfn/config/realize.rb +13 -0
- data/lib/sfn/config/validate.rb +8 -1
- data/lib/sfn/error.rb +61 -0
- data/lib/sfn/version.rb +1 -1
- metadata +5 -3
- data/lib/chef/knife/knife_plugin_seed.rb +0 -117
data/docs/commands.md
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
title: "CLI Commands"
|
3
3
|
weight: 4
|
4
4
|
anchors:
|
5
|
-
- title: "Lifecycle
|
6
|
-
url: "#lifecycle
|
7
|
-
- title: "
|
8
|
-
url: "#
|
9
|
-
- title: "Configuration
|
10
|
-
url: "#configuration
|
5
|
+
- title: "Lifecycle"
|
6
|
+
url: "#lifecycle"
|
7
|
+
- title: "Informational"
|
8
|
+
url: "#informational"
|
9
|
+
- title: "Configuration"
|
10
|
+
url: "#configuration"
|
11
11
|
---
|
12
12
|
|
13
13
|
## SparkleFormation CLI commands
|
@@ -16,7 +16,7 @@ The `sfn` command provides a collection of subcommands to handle stack
|
|
16
16
|
lifecycles as well as subcommands to aid in inspection of existing
|
17
17
|
stacks.
|
18
18
|
|
19
|
-
### Lifecycle
|
19
|
+
### Lifecycle
|
20
20
|
|
21
21
|
#### Stack create
|
22
22
|
|
@@ -172,6 +172,52 @@ Example of stack update:
|
|
172
172
|
|
173
173
|

|
174
174
|
|
175
|
+
#### Stack plan
|
176
|
+
|
177
|
+
The `plan` command allows for a stack to be created or updated via `sfn`. It uses the
|
178
|
+
planning functionality of the provider to include planning information prior to
|
179
|
+
application of the creation/modifications. The `plan` command is currently only
|
180
|
+
supported with the AWS provider. When using the `update` command, the plan generation
|
181
|
+
uses the internal planner with `sfn` and supports showing resource for nested stacks.
|
182
|
+
This is currently not supported with the remote planning API.
|
183
|
+
|
184
|
+
Available options for the `plan` command are similar to the `create` and `update`
|
185
|
+
commands. Additionally, available plans can be listed for a given stack:
|
186
|
+
|
187
|
+
~~~
|
188
|
+
$ sfn plan my-stack --list
|
189
|
+
~~~
|
190
|
+
|
191
|
+
By default the plan will be created with a default name (`miasma-changeset-STACKNAME`). A
|
192
|
+
custom name can be used for the plan:
|
193
|
+
|
194
|
+
~~~
|
195
|
+
$ sfn plan my-stack --file my_template --plan-name custom-plan-name
|
196
|
+
~~~
|
197
|
+
|
198
|
+
It is also possible to apply an existing plan for a stack by providing the plan name:
|
199
|
+
|
200
|
+
~~~
|
201
|
+
$ sfn plan my-stack --plan-name existing-plan-name
|
202
|
+
~~~
|
203
|
+
|
204
|
+
#### Stack realize
|
205
|
+
|
206
|
+
The `realize` command loads an existing plan for a given stack and executes the plan. This
|
207
|
+
is useful to allow generating plans and then executing a plan at a later time. For example
|
208
|
+
a stack plan can be first generated and not applied:
|
209
|
+
|
210
|
+
~~~
|
211
|
+
$ sfn plan my-stack --file my_template --plan-only
|
212
|
+
~~~
|
213
|
+
|
214
|
+
This generates the plan and displays the result but does not apply the changes. The plan
|
215
|
+
can then be loaded and applied using the `realize` command:
|
216
|
+
|
217
|
+
~~~
|
218
|
+
$ sfn realize my-stack
|
219
|
+
~~~
|
220
|
+
|
175
221
|
#### Stack destroy
|
176
222
|
|
177
223
|
Existing stacks can be destroyed via `sfn`:
|
@@ -209,7 +255,7 @@ Example of stack destroy:
|
|
209
255
|
|
210
256
|

|
211
257
|
|
212
|
-
###
|
258
|
+
### Informational
|
213
259
|
|
214
260
|
#### Stack list
|
215
261
|
|
@@ -386,7 +432,7 @@ is installed on the local system, an image can be generated directly:
|
|
386
432
|
$ sfn graph --file my_template --graph-type png
|
387
433
|
~~~
|
388
434
|
|
389
|
-
### Configuration
|
435
|
+
### Configuration
|
390
436
|
|
391
437
|
To aid setup and configuration, `sfn` provides a configuration helper:
|
392
438
|
|
@@ -399,4 +445,4 @@ one automatically generated for them:
|
|
399
445
|
|
400
446
|
~~~
|
401
447
|
$ sfn conf --generate
|
402
|
-
~~~
|
448
|
+
~~~
|
data/docs/usage.md
CHANGED
data/lib/sfn.rb
CHANGED
data/lib/sfn/command.rb
CHANGED
@@ -21,6 +21,7 @@ module Sfn
|
|
21
21
|
autoload :Plan, "sfn/command/plan"
|
22
22
|
autoload :Print, "sfn/command/print"
|
23
23
|
autoload :Promote, "sfn/command/promote"
|
24
|
+
autoload :Realize, "sfn/command/realize"
|
24
25
|
autoload :Update, "sfn/command/update"
|
25
26
|
autoload :Validate, "sfn/command/validate"
|
26
27
|
|
data/lib/sfn/command/import.rb
CHANGED
@@ -23,7 +23,14 @@ module Sfn
|
|
23
23
|
if entries.size > 1
|
24
24
|
valid = false
|
25
25
|
until valid
|
26
|
-
|
26
|
+
if config[:interactive_parameters]
|
27
|
+
answer = ui.ask_question(
|
28
|
+
"Import via file system (fs) or remote bucket (remote)?",
|
29
|
+
:default => "remote",
|
30
|
+
)
|
31
|
+
else
|
32
|
+
answer = "remote"
|
33
|
+
end
|
27
34
|
valid = true if %w(remote fs).include?(answer)
|
28
35
|
entries = [answer]
|
29
36
|
end
|
data/lib/sfn/command/plan.rb
CHANGED
@@ -36,7 +36,12 @@ module Sfn
|
|
36
36
|
if stack && stack.plan
|
37
37
|
ui.warn "Found existing plan for this stack"
|
38
38
|
begin
|
39
|
-
|
39
|
+
if config[:load_existing]
|
40
|
+
raise Bogo::Ui::ConfirmationDeclined
|
41
|
+
end
|
42
|
+
if config[:load_existing].nil?
|
43
|
+
ui.confirm "Destroy existing plan"
|
44
|
+
end
|
40
45
|
ui.info "Destroying existing plan to generate new plan"
|
41
46
|
stack.plan.destroy
|
42
47
|
rescue Bogo::Ui::ConfirmationDeclined
|
@@ -127,56 +132,8 @@ module Sfn
|
|
127
132
|
end
|
128
133
|
|
129
134
|
plan = stack.plan || stack.plan_generate
|
130
|
-
|
131
|
-
|
132
|
-
display_plan_information(plan)
|
133
|
-
rescue Bogo::Ui::ConfirmationDeclined
|
134
|
-
stack.reload
|
135
|
-
if (stack.template.nil? || stack.template.empty?) && stack.state == :unknown
|
136
|
-
ui.auto_confirm = false
|
137
|
-
ui.warn "Stack appears to be empty and should be destroyed"
|
138
|
-
ui.confirm "Destroy stack?"
|
139
|
-
stack.destroy
|
140
|
-
poll_stack(stack.name)
|
141
|
-
else
|
142
|
-
ui.confirm "Destroy generated plan?"
|
143
|
-
plan.destroy
|
144
|
-
end
|
145
|
-
raise
|
146
|
-
end
|
147
|
-
|
148
|
-
if config[:merge_api_options]
|
149
|
-
config.fetch(:options, Smash.new).each_pair do |key, value|
|
150
|
-
if stack.respond_to?("#{key}=")
|
151
|
-
stack.send("#{key}=", value)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
begin
|
157
|
-
api_action!(:api_stack => stack) do
|
158
|
-
stack.plan_execute
|
159
|
-
if config[:poll]
|
160
|
-
poll_stack(stack.name)
|
161
|
-
if stack.reload.state == :update_complete || stack.reload.state == :create_complete
|
162
|
-
ui.info "Stack plan apply complete: #{ui.color("SUCCESS", :green)}"
|
163
|
-
namespace.const_get(:Describe).new({:outputs => true}, [name]).execute!
|
164
|
-
else
|
165
|
-
ui.fatal "Update of stack #{ui.color(name, :bold)}: #{ui.color("FAILED", :red, :bold)}"
|
166
|
-
raise "Stack did not reach a successful completion state."
|
167
|
-
end
|
168
|
-
else
|
169
|
-
ui.warn "Stack state polling has been disabled."
|
170
|
-
ui.info "Stack plan apply initialized for #{ui.color(name, :green)}"
|
171
|
-
end
|
172
|
-
end
|
173
|
-
rescue Miasma::Error::ApiError::RequestError => e
|
174
|
-
if e.message.downcase.include?("no updates")
|
175
|
-
ui.warn "No changes detected for stack (#{stack.name})"
|
176
|
-
else
|
177
|
-
raise
|
178
|
-
end
|
179
|
-
end
|
135
|
+
namespace.const_get(:Realize).
|
136
|
+
new(config, [name]).execute!
|
180
137
|
end
|
181
138
|
|
182
139
|
# Display plan list in table form
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "sfn"
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Command
|
5
|
+
# Realize command
|
6
|
+
class Realize < Command
|
7
|
+
include Sfn::CommandModule::Base
|
8
|
+
include Sfn::CommandModule::Planning
|
9
|
+
|
10
|
+
# Run the stack realize command
|
11
|
+
def execute!
|
12
|
+
name_required!
|
13
|
+
name = name_args.first
|
14
|
+
|
15
|
+
stack_info = "#{ui.color("Name:", :bold)} #{name}"
|
16
|
+
begin
|
17
|
+
stack = provider.stacks.get(name)
|
18
|
+
rescue Miasma::Error::ApiError::RequestError
|
19
|
+
raise Error::StackNotFound,
|
20
|
+
"Failed to locate stack: #{name}"
|
21
|
+
end
|
22
|
+
|
23
|
+
if config[:plan_name]
|
24
|
+
ui.debug "Setting custom plan name - #{config[:plan_name]}"
|
25
|
+
# ensure custom attribute is dirty so we can modify
|
26
|
+
stack.custom = stack.custom.dup
|
27
|
+
stack.custom[:plan_name] = config[:plan_name]
|
28
|
+
end
|
29
|
+
|
30
|
+
ui.info " -> Loading plan information..."
|
31
|
+
|
32
|
+
plan = stack.plan
|
33
|
+
if plan.nil?
|
34
|
+
raise Error::StackPlanNotFound,
|
35
|
+
"Failed to locate plan for stack `#{name}`"
|
36
|
+
end
|
37
|
+
|
38
|
+
display_plan_information(plan)
|
39
|
+
|
40
|
+
return if config[:plan_only]
|
41
|
+
|
42
|
+
if config[:merge_api_options]
|
43
|
+
config.fetch(:options, Smash.new).each_pair do |key, value|
|
44
|
+
if stack.respond_to?("#{key}=")
|
45
|
+
stack.send("#{key}=", value)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
api_action!(:api_stack => stack) do
|
52
|
+
stack.plan_execute
|
53
|
+
if config[:poll]
|
54
|
+
poll_stack(stack.name)
|
55
|
+
if [:update_complete, :create_complete].
|
56
|
+
include?(stack.reload.state)
|
57
|
+
ui.info "Stack plan apply complete: " \
|
58
|
+
"#{ui.color("SUCCESS", :green)}"
|
59
|
+
namespace.const_get(:Describe).
|
60
|
+
new({:outputs => true}, [name]).execute!
|
61
|
+
else
|
62
|
+
ui.fatal "Update of stack #{ui.color(name, :bold)}: " \
|
63
|
+
"#{ui.color("FAILED", :red, :bold)}"
|
64
|
+
raise Error::StackStateIncomplete
|
65
|
+
end
|
66
|
+
else
|
67
|
+
ui.warn "Stack state polling has been disabled."
|
68
|
+
ui.info "Stack plan apply initialized for " \
|
69
|
+
"#{ui.color(name, :green)}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
rescue Miasma::Error::ApiError::RequestError => e
|
73
|
+
if e.message.downcase.include?("no updates")
|
74
|
+
ui.warn "No changes detected for stack (#{stack.name})"
|
75
|
+
else
|
76
|
+
raise
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/sfn/command/update.rb
CHANGED
@@ -27,8 +27,12 @@ module Sfn
|
|
27
27
|
unless print_plan_result(result, [result.name])
|
28
28
|
ui.info "No resources life cycle changes detected in this update!"
|
29
29
|
end
|
30
|
-
|
31
|
-
|
30
|
+
if config[:plan_apply]
|
31
|
+
return ui.info "Realizing this stack plan..."
|
32
|
+
elsif config[:plan_only]
|
33
|
+
return
|
34
|
+
end
|
35
|
+
ui.confirm "Realize this stack plan?"
|
32
36
|
end
|
33
37
|
|
34
38
|
# Print plan information to the UI
|
@@ -340,9 +340,17 @@ module Sfn
|
|
340
340
|
end
|
341
341
|
if current_value && current_value.to_s != stack_value.to_s
|
342
342
|
if config[:parameter_validation] == "default"
|
343
|
-
ui.warn "Nested stack has been altered directly!
|
344
|
-
|
345
|
-
|
343
|
+
ui.warn "Nested stack has been altered directly! " \
|
344
|
+
"This update may cause unexpected modifications!"
|
345
|
+
ui.warn "Stack name: #{c_stack.name}. Parameter: #{p_key}. " \
|
346
|
+
"Current value: #{stack_value}. Expected value: #{current_value} " \
|
347
|
+
"(via: #{c_value.inspect})"
|
348
|
+
if config[:interactive_parameters]
|
349
|
+
answer = ui.ask_question("Use current value or expected value for #{p_key} " \
|
350
|
+
"[current/expected]?", :valid => ["current", "expected"])
|
351
|
+
else
|
352
|
+
raise Error::InteractionDisabled
|
353
|
+
end
|
346
354
|
else
|
347
355
|
answer = config[:parameter_validation]
|
348
356
|
end
|
@@ -588,7 +588,11 @@ module Sfn
|
|
588
588
|
ui.puts "#{output.join("\n")}\n"
|
589
589
|
response = nil
|
590
590
|
until valid[response]
|
591
|
-
|
591
|
+
if config[:interactive_parameters]
|
592
|
+
response = ui.ask_question("Enter selection").to_i
|
593
|
+
else
|
594
|
+
raise Error::InteractionDisabled
|
595
|
+
end
|
592
596
|
end
|
593
597
|
entry = valid[response]
|
594
598
|
if entry[:type] == :collection
|
data/lib/sfn/config.rb
CHANGED
@@ -38,7 +38,9 @@ module Sfn
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# Only values allowed designating bool type
|
41
|
-
BOOLEAN = BOOLEAN_VALUES = [TrueClass, FalseClass]
|
41
|
+
BOOLEAN = BOOLEAN_VALUES = [TrueClass, FalseClass].freeze
|
42
|
+
# Boolean type with nil included
|
43
|
+
TRISTATE_BOOLEAN = (BOOLEAN + [NilClass]).freeze
|
42
44
|
|
43
45
|
autoload :Conf, "sfn/config/conf"
|
44
46
|
autoload :Create, "sfn/config/create"
|
@@ -57,6 +59,7 @@ module Sfn
|
|
57
59
|
autoload :Plan, "sfn/config/plan"
|
58
60
|
autoload :Print, "sfn/config/print"
|
59
61
|
autoload :Promote, "sfn/config/promote"
|
62
|
+
autoload :Realize, "sfn/config/realize"
|
60
63
|
autoload :Update, "sfn/config/update"
|
61
64
|
autoload :Validate, "sfn/config/validate"
|
62
65
|
|
@@ -104,6 +107,11 @@ module Sfn
|
|
104
107
|
:description => "Enable debug output",
|
105
108
|
:short_flag => "u",
|
106
109
|
)
|
110
|
+
attribute(
|
111
|
+
:log, String,
|
112
|
+
:description => "Enable logging with given level",
|
113
|
+
:short_flag => "G",
|
114
|
+
)
|
107
115
|
attribute(
|
108
116
|
:colors, [TrueClass, FalseClass],
|
109
117
|
:description => "Enable colorized output",
|
data/lib/sfn/config/plan.rb
CHANGED
@@ -17,6 +17,24 @@ module Sfn
|
|
17
17
|
:description => "Custom plan name or ID (not applicable to all providers)",
|
18
18
|
)
|
19
19
|
|
20
|
+
attribute(
|
21
|
+
:load_existing, TRISTATE_BOOLEAN,
|
22
|
+
:description => "Load existing plan if exists",
|
23
|
+
:default => nil,
|
24
|
+
)
|
25
|
+
|
26
|
+
attribute(
|
27
|
+
:auto_destroy_stack, TRISTATE_BOOLEAN,
|
28
|
+
:description => "Automatically destroy empty stack",
|
29
|
+
:default => nil,
|
30
|
+
)
|
31
|
+
|
32
|
+
attribute(
|
33
|
+
:auto_destroy_plan, TRISTATE_BOOLEAN,
|
34
|
+
:description => "Automatically destroy generated plan",
|
35
|
+
:default => nil,
|
36
|
+
)
|
37
|
+
|
20
38
|
attribute(
|
21
39
|
:list, BOOLEAN,
|
22
40
|
:description => "List all available plans for stack",
|
data/lib/sfn/config/validate.rb
CHANGED
@@ -81,7 +81,14 @@ module Sfn
|
|
81
81
|
result = Smash.new
|
82
82
|
v.split(",").each do |item_pair|
|
83
83
|
key, value = item_pair.split(/[=:]/, 2)
|
84
|
-
result[key]
|
84
|
+
if !result[key]
|
85
|
+
result[key] = value
|
86
|
+
next
|
87
|
+
end
|
88
|
+
if !result.is_a?(Array)
|
89
|
+
result[key] = [result[key]]
|
90
|
+
end
|
91
|
+
result[key] << value
|
85
92
|
end
|
86
93
|
result
|
87
94
|
when Hash
|