sfn 0.0.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +107 -0
- data/LICENSE +13 -0
- data/README.md +142 -61
- data/bin/sfn +43 -0
- data/lib/chef/knife/knife_plugin_seed.rb +117 -0
- data/lib/sfn.rb +17 -0
- data/lib/sfn/cache.rb +385 -0
- data/lib/sfn/command.rb +45 -0
- data/lib/sfn/command/create.rb +87 -0
- data/lib/sfn/command/describe.rb +87 -0
- data/lib/sfn/command/destroy.rb +74 -0
- data/lib/sfn/command/events.rb +98 -0
- data/lib/sfn/command/export.rb +103 -0
- data/lib/sfn/command/import.rb +117 -0
- data/lib/sfn/command/inspect.rb +160 -0
- data/lib/sfn/command/list.rb +59 -0
- data/lib/sfn/command/promote.rb +17 -0
- data/lib/sfn/command/update.rb +95 -0
- data/lib/sfn/command/validate.rb +34 -0
- data/lib/sfn/command_module.rb +9 -0
- data/lib/sfn/command_module/base.rb +150 -0
- data/lib/sfn/command_module/stack.rb +166 -0
- data/lib/sfn/command_module/template.rb +147 -0
- data/lib/sfn/config.rb +106 -0
- data/lib/sfn/config/create.rb +35 -0
- data/lib/sfn/config/describe.rb +19 -0
- data/lib/sfn/config/destroy.rb +9 -0
- data/lib/sfn/config/events.rb +25 -0
- data/lib/sfn/config/export.rb +29 -0
- data/lib/sfn/config/import.rb +24 -0
- data/lib/sfn/config/inspect.rb +37 -0
- data/lib/sfn/config/list.rb +25 -0
- data/lib/sfn/config/promote.rb +23 -0
- data/lib/sfn/config/update.rb +20 -0
- data/lib/sfn/config/validate.rb +49 -0
- data/lib/sfn/monkey_patch.rb +8 -0
- data/lib/sfn/monkey_patch/stack.rb +200 -0
- data/lib/sfn/provider.rb +224 -0
- data/lib/sfn/utils.rb +23 -0
- data/lib/sfn/utils/debug.rb +31 -0
- data/lib/sfn/utils/json.rb +37 -0
- data/lib/sfn/utils/object_storage.rb +28 -0
- data/lib/sfn/utils/output.rb +79 -0
- data/lib/sfn/utils/path_selector.rb +99 -0
- data/lib/sfn/utils/ssher.rb +29 -0
- data/lib/sfn/utils/stack_exporter.rb +275 -0
- data/lib/sfn/utils/stack_parameter_scrubber.rb +37 -0
- data/lib/sfn/utils/stack_parameter_validator.rb +124 -0
- data/lib/sfn/version.rb +4 -0
- data/sfn.gemspec +19 -0
- metadata +110 -4
data/lib/sfn/config.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
require 'bogo-config'
|
3
|
+
|
4
|
+
module Sfn
|
5
|
+
|
6
|
+
# Top level configuration
|
7
|
+
class Config < Bogo::Config
|
8
|
+
|
9
|
+
# Only values allowed designating bool type
|
10
|
+
BOOLEAN_VALUES = [TrueClass, FalseClass]
|
11
|
+
|
12
|
+
autoload :Create, 'sfn/config/create'
|
13
|
+
autoload :Describe, 'sfn/config/describe'
|
14
|
+
autoload :Destroy, 'sfn/config/destroy'
|
15
|
+
autoload :Describe, 'sfn/config/describe'
|
16
|
+
autoload :Events, 'sfn/config/events'
|
17
|
+
autoload :Export, 'sfn/config/export'
|
18
|
+
autoload :Import, 'sfn/config/import'
|
19
|
+
autoload :Inspect, 'sfn/config/inspect'
|
20
|
+
autoload :List, 'sfn/config/list'
|
21
|
+
autoload :Promote, 'sfn/config/promote'
|
22
|
+
autoload :Update, 'sfn/config/update'
|
23
|
+
autoload :Validate, 'sfn/config/validate'
|
24
|
+
|
25
|
+
attribute(
|
26
|
+
:credentials, Smash,
|
27
|
+
:coerce => proc{|v|
|
28
|
+
v = Smash[v.split(',').map{|x| v.split('=')}] if v.is_a?(String)
|
29
|
+
v.to_smash
|
30
|
+
},
|
31
|
+
:description => 'Provider credentials'
|
32
|
+
)
|
33
|
+
attribute(
|
34
|
+
:ignore_parameters, String,
|
35
|
+
:multiple => true,
|
36
|
+
:description => 'Parameters to ignore during modifications'
|
37
|
+
)
|
38
|
+
attribute(
|
39
|
+
:interactive_parameters, [TrueClass, FalseClass],
|
40
|
+
:default => true,
|
41
|
+
:description => 'Prompt for template parameters'
|
42
|
+
)
|
43
|
+
attribute(
|
44
|
+
:poll, [TrueClass, FalseClass],
|
45
|
+
:default => true,
|
46
|
+
:description => 'Poll stack events on modification actions'
|
47
|
+
)
|
48
|
+
attribute(
|
49
|
+
:defaults, [TrueClass, FalseClass],
|
50
|
+
:description => 'Automatically accept default values'
|
51
|
+
)
|
52
|
+
attribute(
|
53
|
+
:yes, [TrueClass, FalseClass],
|
54
|
+
:description => 'Automatically accept any requests for confirmation'
|
55
|
+
)
|
56
|
+
attribute(
|
57
|
+
:config, String,
|
58
|
+
:description => 'Configuration file path'
|
59
|
+
)
|
60
|
+
|
61
|
+
attribute :create, Create, :coerce => proc{|v| Create.new(v)}
|
62
|
+
attribute :update, Update, :coerce => proc{|v| Update.new(v)}
|
63
|
+
attribute :destroy, Destroy, :coerce => proc{|v| Destroy.new(v)}
|
64
|
+
attribute :events, Events, :coerce => proc{|v| Events.new(v)}
|
65
|
+
attribute :export, Export, :coerce => proc{|v| Export.new(v)}
|
66
|
+
attribute :import, Import, :coerce => proc{|v| Import.new(v)}
|
67
|
+
attribute :inspect, Inspect, :coerce => proc{|v| Inpsect.new(v)}
|
68
|
+
attribute :describe, Describe, :coerce => proc{|v| Describe.new(v)}
|
69
|
+
attribute :list, List, :coerce => proc{|v| List.new(v)}
|
70
|
+
attribute :promote, Promote, :coerce => proc{|v| Promote.new(v)}
|
71
|
+
attribute :validate, Validate, :coerce => proc{|v| Validate.new(v)}
|
72
|
+
|
73
|
+
# Provide all options for config class (includes global configs)
|
74
|
+
#
|
75
|
+
# @param klass [Class]
|
76
|
+
# @return [Smash]
|
77
|
+
def self.options_for(klass)
|
78
|
+
shorts = ['h'] # always reserve `-h` for help
|
79
|
+
_options_for(self, shorts).merge(
|
80
|
+
_options_for(klass, shorts)
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Provide options for config class
|
85
|
+
#
|
86
|
+
# @param klass [Class]
|
87
|
+
# @param shorts [Array<String>]
|
88
|
+
# @return [Smash]
|
89
|
+
def self._options_for(klass, shorts)
|
90
|
+
Smash[
|
91
|
+
klass.attributes.sort_by(&:first).map do |name, info|
|
92
|
+
next unless info[:description]
|
93
|
+
short = name.chars.zip(name.chars.map(&:upcase)).flatten.detect do |c|
|
94
|
+
!shorts.include?(c)
|
95
|
+
end
|
96
|
+
shorts << short
|
97
|
+
info[:short] = short
|
98
|
+
info[:long] = name.tr('_', '-')
|
99
|
+
info[:boolean] = [info[:type]].compact.flatten.all?{|t| BOOLEAN_VALUES.include?(t)}
|
100
|
+
[name, info]
|
101
|
+
end.compact
|
102
|
+
]
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
# Create command configuration
|
6
|
+
class Create < Update
|
7
|
+
|
8
|
+
attribute(
|
9
|
+
:timeout, Integer,
|
10
|
+
:coerce => proc{|v| v.to_i},
|
11
|
+
:description => 'Seconds to wait for stack to complete'
|
12
|
+
)
|
13
|
+
attribute(
|
14
|
+
:rollback, [TrueClass, FalseClass],
|
15
|
+
:description => 'Rollback stack on failure'
|
16
|
+
)
|
17
|
+
attribute(
|
18
|
+
:capabilities, String,
|
19
|
+
:multiple => true,
|
20
|
+
:description => 'Capabilities to allow the stack'
|
21
|
+
)
|
22
|
+
attribute(
|
23
|
+
:options, String,
|
24
|
+
:multiple => true,
|
25
|
+
:description => 'Extra options to apply to the API call'
|
26
|
+
)
|
27
|
+
attribute(
|
28
|
+
:notifications, String,
|
29
|
+
:multiple => true,
|
30
|
+
:description => 'Notification endpoints for stack events'
|
31
|
+
)
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
class Describe < Bogo::Config
|
6
|
+
|
7
|
+
attribute(
|
8
|
+
:resources, [TrueClass, FalseClass],
|
9
|
+
:description => 'Display stack resource list'
|
10
|
+
)
|
11
|
+
|
12
|
+
attribute(
|
13
|
+
:outputs, [TrueClass, FalseClass],
|
14
|
+
:description => 'Display stack outputs'
|
15
|
+
)
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
# Events command configuration
|
6
|
+
class Events < Bogo::Config
|
7
|
+
|
8
|
+
attribute(
|
9
|
+
:attribute, String,
|
10
|
+
:multiple => true,
|
11
|
+
:description => 'Event attribute to display'
|
12
|
+
)
|
13
|
+
attribute(
|
14
|
+
:poll_delay, Integer,
|
15
|
+
:default => 20,
|
16
|
+
:description => 'Seconds to pause between each event poll'
|
17
|
+
)
|
18
|
+
attribute(
|
19
|
+
:all_attributes, [TrueClass, FalseClass],
|
20
|
+
:description => 'Display all event attributes'
|
21
|
+
)
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
|
6
|
+
# Export command configuration
|
7
|
+
class Export < Bogo::Config
|
8
|
+
|
9
|
+
attribute(
|
10
|
+
:name, String,
|
11
|
+
:description => 'Export file base name'
|
12
|
+
)
|
13
|
+
attribute(
|
14
|
+
:path, String,
|
15
|
+
:description => 'Local path prefix for dump file'
|
16
|
+
)
|
17
|
+
attribute(
|
18
|
+
:bucket, String,
|
19
|
+
:description => 'Remote storage bucket'
|
20
|
+
)
|
21
|
+
attribute(
|
22
|
+
:bucket_prefix, String,
|
23
|
+
:description => 'Remote key prefix within bucket for dump file'
|
24
|
+
)
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
|
6
|
+
# Import command configuration
|
7
|
+
class Import < Bogo::Config
|
8
|
+
|
9
|
+
attribute(
|
10
|
+
:path, String,
|
11
|
+
:description => 'Directory path JSON export files are located'
|
12
|
+
)
|
13
|
+
attribute(
|
14
|
+
:bucket, String,
|
15
|
+
:description => 'Remote storage bucket JSON export files are located'
|
16
|
+
)
|
17
|
+
attribute(
|
18
|
+
:bucket_prefix, String,
|
19
|
+
:description => 'Remote key prefix within bucket for dump file'
|
20
|
+
)
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
# Inspect command configuration
|
6
|
+
class Inspect < Bogo::Config
|
7
|
+
|
8
|
+
attribute(
|
9
|
+
:attribute, String,
|
10
|
+
:multiple => true,
|
11
|
+
:description => 'Dot delimited attribute to view'
|
12
|
+
)
|
13
|
+
attribute(
|
14
|
+
:nodes, [TrueClass, FalseClass],
|
15
|
+
:description => 'Locate all instances and display addresses'
|
16
|
+
)
|
17
|
+
attribute(
|
18
|
+
:instance_failure, String,
|
19
|
+
:description => 'Display log file error from failed not if possible',
|
20
|
+
)
|
21
|
+
attribute(
|
22
|
+
:failure_log_path, String,
|
23
|
+
:description => 'Path to remote log file for display on failure',
|
24
|
+
:default => '/var/log/chef/client.log'
|
25
|
+
)
|
26
|
+
attribute(
|
27
|
+
:identity_file, String,
|
28
|
+
:description => 'SSH identity file for authentication'
|
29
|
+
)
|
30
|
+
attribute(
|
31
|
+
:ssh_user, String,
|
32
|
+
:description => 'SSH username for inspection connect'
|
33
|
+
)
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
# List command configuration
|
6
|
+
class List < Bogo::Config
|
7
|
+
|
8
|
+
attribute(
|
9
|
+
:attribute, String,
|
10
|
+
:multiple => true,
|
11
|
+
:description => 'Attribute of stack to print'
|
12
|
+
)
|
13
|
+
attribute(
|
14
|
+
:all_attributes, [TrueClass, FalseClass],
|
15
|
+
:description => 'Print all available attributes'
|
16
|
+
)
|
17
|
+
attribute(
|
18
|
+
:status, String,
|
19
|
+
:multiple => true,
|
20
|
+
:description => 'Match stacks with given status. Use "none" to disable.'
|
21
|
+
)
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
# Promote command configuration
|
6
|
+
class Promote < Bogo::Config
|
7
|
+
|
8
|
+
attribute(
|
9
|
+
:accounts, String,
|
10
|
+
:description => 'JSON accounts file path'
|
11
|
+
)
|
12
|
+
attribute(
|
13
|
+
:bucket, String,
|
14
|
+
:description => 'Bucket name containing the exports'
|
15
|
+
)
|
16
|
+
attribute(
|
17
|
+
:bucket_prefix, String,
|
18
|
+
:description => 'Key prefix within remote bucket'
|
19
|
+
)
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
# Update command configuration
|
6
|
+
class Update < Validate
|
7
|
+
|
8
|
+
attribute(
|
9
|
+
:print_only, [TrueClass, FalseClass],
|
10
|
+
:description => 'Print the resulting stack template'
|
11
|
+
)
|
12
|
+
attribute(
|
13
|
+
:apply_stack, String,
|
14
|
+
:multiple => true,
|
15
|
+
:description => 'Apply outputs from stack to input parameters'
|
16
|
+
)
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
class Config
|
5
|
+
# Validate command configuration
|
6
|
+
class Validate < Bogo::Config
|
7
|
+
|
8
|
+
attribute(
|
9
|
+
:processing, [TrueClass, FalseClass],
|
10
|
+
:description => 'Call the unicorns and explode the glitter bombs'
|
11
|
+
)
|
12
|
+
attribute(
|
13
|
+
:file, String,
|
14
|
+
:description => 'Path to template file'
|
15
|
+
)
|
16
|
+
attribute(
|
17
|
+
:file_path_prompt, [TrueClass, FalseClass],
|
18
|
+
:default => true,
|
19
|
+
:description => 'Enable interactive prompt for template path discovery'
|
20
|
+
)
|
21
|
+
attribute(
|
22
|
+
:base_directory, String,
|
23
|
+
:description => 'Path to root of of templates directory'
|
24
|
+
)
|
25
|
+
attribute(
|
26
|
+
:no_base_directory, [TrueClass, FalseClass],
|
27
|
+
:description => 'Unset any value used for the template root directory path'
|
28
|
+
)
|
29
|
+
attribute(
|
30
|
+
:translate, String,
|
31
|
+
:description => 'Translate generated template to given prodiver'
|
32
|
+
)
|
33
|
+
attribute(
|
34
|
+
:translate_chunk, Integer,
|
35
|
+
:description => 'Chunk length for serialization'
|
36
|
+
)
|
37
|
+
attribute(
|
38
|
+
:apply_nesting, [TrueClass, FalseClass],
|
39
|
+
:default => true,
|
40
|
+
:description => 'Apply stack nesting'
|
41
|
+
)
|
42
|
+
attribute(
|
43
|
+
:nesting_bucket, String,
|
44
|
+
:description => 'Bucket to use for storing nested stack templates'
|
45
|
+
)
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'sfn'
|
3
|
+
|
4
|
+
module Sfn
|
5
|
+
module MonkeyPatch
|
6
|
+
|
7
|
+
# Expand stack model functionality
|
8
|
+
module Stack
|
9
|
+
|
10
|
+
include Bogo::AnimalStrings
|
11
|
+
|
12
|
+
## Status helpers
|
13
|
+
|
14
|
+
# Check for state suffix
|
15
|
+
#
|
16
|
+
# @param args [String, Symbol] state suffix to check for (multiple allowed)
|
17
|
+
# @return [TrueClass, FalseClass] true if any matches found in argument list
|
18
|
+
def status_ends_with?(*args)
|
19
|
+
stat = status.to_s.downcase
|
20
|
+
!!args.map(&:to_s).map(&:downcase).detect do |suffix|
|
21
|
+
stat.end_with?(suffix)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Check for state prefix
|
26
|
+
#
|
27
|
+
# @param args [String, Symbol] state prefix to check for (multiple allowed)
|
28
|
+
# @return [TrueClass, FalseClass] true if any matches found in argument list
|
29
|
+
def status_starts_with?(*args)
|
30
|
+
stat = status.to_s.downcase
|
31
|
+
!!args.map(&:to_s).map(&:downcase).detect do |prefix|
|
32
|
+
stat.start_with?(prefix)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Check for state inclusion
|
37
|
+
#
|
38
|
+
# @param args [String, Symbol] state string to check for (multiple allowed)
|
39
|
+
# @return [TrueClass, FalseClass] true if any matches found in argument list
|
40
|
+
def status_includes?(*args)
|
41
|
+
stat = status.to_s.downcase
|
42
|
+
!!args.map(&:to_s).map(&:downcase).detect do |string|
|
43
|
+
stat.include?(string)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [TrueClass, FalseClass] stack is in progress
|
48
|
+
def in_progress?
|
49
|
+
status_ends_with?(:in_progress)
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [TrueClass, FalseClass] stack is in complete state
|
53
|
+
def complete?
|
54
|
+
status_ends_with?(:complete, :failed)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [TrueClass, FalseClass] stack is failed state
|
58
|
+
def failed?
|
59
|
+
status_ends_with?(:failed) ||
|
60
|
+
(status_includes?(:rollback) && status_ends_with?(:complete))
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [TrueClass, FalseClass] stack is in success state
|
64
|
+
def success?
|
65
|
+
!failed? && complete?
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [TrueClass, FalseClass] stack is creating
|
69
|
+
def creating?
|
70
|
+
in_progress? && status_starts_with?(:create)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [TrueClass, FalseClass] stack is deleting
|
74
|
+
def deleting?
|
75
|
+
in_progress? && status_starts_with?(:delete)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [TrueClass, FalseClass] stack is updating
|
79
|
+
def updating?
|
80
|
+
in_progress? && status_starts_with?(:update)
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [TrueClass, FalseClass] stack is rolling back
|
84
|
+
def rollbacking?
|
85
|
+
in_progress? && status_starts_with?(:rollback)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [String] action currently being performed
|
89
|
+
def performing
|
90
|
+
if(in_progress?)
|
91
|
+
status.to_s.downcase.split('_').first.to_sym
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
### Color coders
|
96
|
+
|
97
|
+
# @return [TrueClass, FalseClass] stack is in red state
|
98
|
+
def red?
|
99
|
+
failed? || deleting?
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [TrueClass, FalseClass] stack is in green state
|
103
|
+
def green?
|
104
|
+
success?
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [TrueClass, FalseClass] stack is in yellow state
|
108
|
+
def yellow?
|
109
|
+
!red? && !green?
|
110
|
+
end
|
111
|
+
|
112
|
+
# Provides color of stack state. Red is an error state, yellow
|
113
|
+
# is a warning state and green is a success state
|
114
|
+
#
|
115
|
+
# @return [Symbol] color of state (:red, :yellow, :green)
|
116
|
+
def color_state
|
117
|
+
red? ? :red : green? ? :green : :yellow
|
118
|
+
end
|
119
|
+
|
120
|
+
# Provides text of stack state. Danger is an error state, warning
|
121
|
+
# is a warning state and success is a success state
|
122
|
+
#
|
123
|
+
# @return [Symbol] color of state (:danger, :warning, :success)
|
124
|
+
def text_state
|
125
|
+
red? ? :danger : green? ? :success : :warning
|
126
|
+
end
|
127
|
+
|
128
|
+
# @return [String] URL safe encoded stack id
|
129
|
+
def encoded_id
|
130
|
+
Base64.urlsafe_encode64(id)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Whole number representation of current completion
|
134
|
+
#
|
135
|
+
# @param min [Integer] lowest allowed return value (defaults 5)
|
136
|
+
# @return [Integer] percent complete (0..100)
|
137
|
+
def percent_complete(min = 5)
|
138
|
+
if(in_progress?)
|
139
|
+
total_resources = load_template.fetch('Resources', []).size
|
140
|
+
total_complete = resources.all.find_all do |resource|
|
141
|
+
resource.resource_status.downcase.end_with?('complete')
|
142
|
+
end.size
|
143
|
+
result = ((total_complete.to_f / total_resources) * 100).to_i
|
144
|
+
result > min.to_i ? result : min
|
145
|
+
else
|
146
|
+
100
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Apply stack outputs to current stack parameters
|
151
|
+
#
|
152
|
+
# @param remote_stack [Miasma::Orchestration::Stack]
|
153
|
+
# @return [self]
|
154
|
+
# @note setting `DisableApply` within parameter hash will
|
155
|
+
# prevent parameters being overridden
|
156
|
+
def apply_stack(remote_stack, ignore_params=nil)
|
157
|
+
default_key = 'Default'
|
158
|
+
stack_parameters = template['Parameters']
|
159
|
+
valid_parameters = Smash[
|
160
|
+
stack_parameters.map do |key, val|
|
161
|
+
unless(val['DisableApply'])
|
162
|
+
[snake(key), key]
|
163
|
+
end
|
164
|
+
end.compact
|
165
|
+
]
|
166
|
+
unless(ignore_params)
|
167
|
+
if(defined?(Chef::Config))
|
168
|
+
ignore_params = Chef::Config[:knife].to_smash.get(:cloudformation, :ignore_parameters)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
if(ignore_params)
|
172
|
+
valid_parameters = Hash[
|
173
|
+
valid_parameters.map do |snake_param, camel_param|
|
174
|
+
unless(ignore_params.include?(camel_param))
|
175
|
+
[snake_param, camel_param]
|
176
|
+
end
|
177
|
+
end.compact
|
178
|
+
]
|
179
|
+
end
|
180
|
+
if(persisted?)
|
181
|
+
remote_stack.outputs.each do |output|
|
182
|
+
if(param_key = valid_parameters[snake(output.key)])
|
183
|
+
parameters.merge!(param_key => output.value)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
else
|
187
|
+
remote_stack.outputs.each do |output|
|
188
|
+
if(param_key = valid_parameters[snake(output.key)])
|
189
|
+
stack_parameters[param_key][default_key] = output.value
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Infect miasma
|
200
|
+
Miasma::Models::Orchestration::Stack.send(:include, Sfn::MonkeyPatch::Stack)
|