sfn 3.0.28 → 3.0.30
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 +5 -5
- data/CHANGELOG.md +5 -0
- data/docs/callbacks.md +1 -0
- data/lib/chef/knife/knife_plugin_seed.rb +11 -17
- data/lib/sfn.rb +0 -2
- data/lib/sfn/api_provider.rb +0 -2
- data/lib/sfn/api_provider/google.rb +6 -9
- data/lib/sfn/api_provider/terraform.rb +4 -6
- data/lib/sfn/cache.rb +36 -39
- data/lib/sfn/callback.rb +0 -2
- data/lib/sfn/callback/aws_assume_role.rb +7 -8
- data/lib/sfn/callback/aws_mfa.rb +7 -8
- data/lib/sfn/callback/stack_policy.rb +15 -17
- data/lib/sfn/command.rb +9 -11
- data/lib/sfn/command/conf.rb +7 -10
- data/lib/sfn/command/create.rb +8 -12
- data/lib/sfn/command/describe.rb +6 -8
- data/lib/sfn/command/destroy.rb +8 -10
- data/lib/sfn/command/diff.rb +18 -25
- data/lib/sfn/command/events.rb +15 -16
- data/lib/sfn/command/export.rb +13 -17
- data/lib/sfn/command/graph.rb +11 -13
- data/lib/sfn/command/graph/aws.rb +27 -29
- data/lib/sfn/command/graph/terraform.rb +22 -23
- data/lib/sfn/command/import.rb +13 -16
- data/lib/sfn/command/init.rb +5 -7
- data/lib/sfn/command/inspect.rb +26 -29
- data/lib/sfn/command/lint.rb +10 -12
- data/lib/sfn/command/list.rb +5 -8
- data/lib/sfn/command/print.rb +3 -5
- data/lib/sfn/command/promote.rb +0 -2
- data/lib/sfn/command/update.rb +42 -46
- data/lib/sfn/command/validate.rb +4 -6
- data/lib/sfn/command_module/base.rb +17 -25
- data/lib/sfn/command_module/callbacks.rb +12 -8
- data/lib/sfn/command_module/stack.rb +39 -43
- data/lib/sfn/command_module/template.rb +89 -90
- data/lib/sfn/config.rb +30 -31
- data/lib/sfn/config/conf.rb +1 -3
- data/lib/sfn/config/create.rb +5 -7
- data/lib/sfn/config/describe.rb +3 -5
- data/lib/sfn/config/diff.rb +1 -1
- data/lib/sfn/config/events.rb +6 -8
- data/lib/sfn/config/export.rb +4 -7
- data/lib/sfn/config/graph.rb +4 -6
- data/lib/sfn/config/import.rb +3 -5
- data/lib/sfn/config/init.rb +0 -1
- data/lib/sfn/config/inspect.rb +7 -9
- data/lib/sfn/config/lint.rb +4 -4
- data/lib/sfn/config/list.rb +3 -5
- data/lib/sfn/config/print.rb +3 -5
- data/lib/sfn/config/promote.rb +3 -5
- data/lib/sfn/config/update.rb +10 -12
- data/lib/sfn/config/validate.rb +18 -20
- data/lib/sfn/lint.rb +0 -2
- data/lib/sfn/lint/definition.rb +3 -5
- data/lib/sfn/lint/rule.rb +7 -8
- data/lib/sfn/lint/rule_set.rb +11 -20
- data/lib/sfn/monkey_patch/stack.rb +32 -34
- data/lib/sfn/monkey_patch/stack/azure.rb +0 -1
- data/lib/sfn/monkey_patch/stack/google.rb +15 -16
- data/lib/sfn/planner.rb +1 -3
- data/lib/sfn/planner/aws.rb +82 -89
- data/lib/sfn/provider.rb +21 -23
- data/lib/sfn/utils.rb +0 -2
- data/lib/sfn/utils/debug.rb +1 -2
- data/lib/sfn/utils/json.rb +3 -2
- data/lib/sfn/utils/object_storage.rb +1 -2
- data/lib/sfn/utils/output.rb +8 -9
- data/lib/sfn/utils/path_selector.rb +9 -10
- data/lib/sfn/utils/ssher.rb +2 -3
- data/lib/sfn/utils/stack_exporter.rb +20 -21
- data/lib/sfn/utils/stack_parameter_scrubber.rb +6 -7
- data/lib/sfn/utils/stack_parameter_validator.rb +14 -16
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +1 -1
- metadata +8 -8
data/lib/sfn/provider.rb
CHANGED
@@ -4,7 +4,6 @@ require 'sfn'
|
|
4
4
|
module Sfn
|
5
5
|
# Remote provider interface
|
6
6
|
class Provider
|
7
|
-
|
8
7
|
include Bogo::AnimalStrings
|
9
8
|
|
10
9
|
# Minimum number of seconds to wait before re-expanding in
|
@@ -38,15 +37,15 @@ module Sfn
|
|
38
37
|
# @option args [Logger] :logger use custom logger
|
39
38
|
# @option args [Numeric] :stack_expansion_interval interval to wait between stack data expands
|
40
39
|
# @option args [Numeric] :stack_list_interval interval to wait between stack list refresh
|
41
|
-
def initialize(args={})
|
40
|
+
def initialize(args = {})
|
42
41
|
args = args.to_smash
|
43
|
-
unless
|
42
|
+
unless args.get(:miasma, :provider)
|
44
43
|
best_guess = (args[:miasma] || {}).keys.group_by do |key|
|
45
44
|
key.to_s.split('_').first
|
46
45
|
end.sort do |x, y|
|
47
46
|
y.size <=> x.size
|
48
47
|
end.first
|
49
|
-
if
|
48
|
+
if best_guess
|
50
49
|
provider = best_guess.first.to_sym
|
51
50
|
else
|
52
51
|
raise ArgumentError.new 'Cannot auto determine :provider value for credentials'
|
@@ -54,15 +53,15 @@ module Sfn
|
|
54
53
|
else
|
55
54
|
provider = args[:miasma].delete(:provider).to_sym
|
56
55
|
end
|
57
|
-
if
|
58
|
-
if
|
56
|
+
if provider == :aws
|
57
|
+
if args[:miasma][:region]
|
59
58
|
args[:miasma][:aws_region] = args[:miasma].delete(:region)
|
60
59
|
end
|
61
60
|
end
|
62
|
-
if
|
61
|
+
if ENV['DEBUG'].to_s.downcase == 'true'
|
63
62
|
log_to = STDOUT
|
64
63
|
else
|
65
|
-
if
|
64
|
+
if Gem.win_platform?
|
66
65
|
log_to = 'NUL'
|
67
66
|
else
|
68
67
|
log_to = '/dev/null'
|
@@ -74,7 +73,7 @@ module Sfn
|
|
74
73
|
@connection = Miasma.api(
|
75
74
|
:provider => provider,
|
76
75
|
:type => :orchestration,
|
77
|
-
:credentials => args[:miasma]
|
76
|
+
:credentials => args[:miasma],
|
78
77
|
)
|
79
78
|
@cache = args.fetch(:cache, Cache.new(:local))
|
80
79
|
@async = args.fetch(:async, true)
|
@@ -82,21 +81,21 @@ module Sfn
|
|
82
81
|
cache.init(:stacks_lock, :lock, :timeout => 0.1)
|
83
82
|
cache.init(:stacks, :stamped)
|
84
83
|
cache.init(:stack_expansion_lock, :lock, :timeout => 0.1)
|
85
|
-
if
|
84
|
+
if args.fetch(:fetch, false)
|
86
85
|
async ? update_stack_list! : fetch_stacks
|
87
86
|
end
|
88
87
|
end
|
89
88
|
|
90
89
|
# @return [Miasma::Orchestration::Stacks]
|
91
|
-
def stacks(stack_id=nil)
|
90
|
+
def stacks(stack_id = nil)
|
92
91
|
connection.stacks.from_json(cached_stacks(stack_id))
|
93
92
|
end
|
94
93
|
|
95
94
|
# @return [String] json representation of cached stacks
|
96
|
-
def cached_stacks(stack_id=nil)
|
97
|
-
if
|
95
|
+
def cached_stacks(stack_id = nil)
|
96
|
+
if !@initial_fetch_complete || stack_id
|
98
97
|
recache = true
|
99
|
-
if
|
98
|
+
if stack_id && @initial_fetch_complete
|
100
99
|
recache = !!stacks.get(stack_id)
|
101
100
|
end
|
102
101
|
fetch_stacks(stack_id) if recache
|
@@ -145,7 +144,7 @@ module Sfn
|
|
145
144
|
# @param stack [Miasma::Models::Orchestration::Stack]
|
146
145
|
def expand_stack(stack)
|
147
146
|
logger.info "Stack expansion requested (#{stack.id})"
|
148
|
-
if((stack.in_progress? && Time.now.to_i - stack.attributes['Cached'].to_i > stack_expansion_interval) ||
|
147
|
+
if ((stack.in_progress? && Time.now.to_i - stack.attributes['Cached'].to_i > stack_expansion_interval) ||
|
149
148
|
!stack.attributes['Cached'])
|
150
149
|
begin
|
151
150
|
expanded = false
|
@@ -154,7 +153,7 @@ module Sfn
|
|
154
153
|
stack.reload
|
155
154
|
stack.data['Cached'] = Time.now.to_i
|
156
155
|
end
|
157
|
-
if
|
156
|
+
if expanded
|
158
157
|
save_expanded_stack(stack.id, stack.to_json)
|
159
158
|
end
|
160
159
|
rescue => e
|
@@ -168,10 +167,10 @@ module Sfn
|
|
168
167
|
# Request stack information and store in cache
|
169
168
|
#
|
170
169
|
# @return [TrueClass]
|
171
|
-
def fetch_stacks(stack_id=nil)
|
170
|
+
def fetch_stacks(stack_id = nil)
|
172
171
|
cache.locked_action(:stacks_lock) do
|
173
172
|
logger.info "Lock aquired for stack update. Requesting stacks from upstream. (#{Thread.current})"
|
174
|
-
if
|
173
|
+
if stack_id
|
175
174
|
single_stack = connection.stacks.get(stack_id)
|
176
175
|
stacks = single_stack ? {single_stack.id => single_stack} : {}
|
177
176
|
else
|
@@ -181,11 +180,11 @@ module Sfn
|
|
181
180
|
end
|
182
181
|
]
|
183
182
|
end
|
184
|
-
if
|
183
|
+
if cache[:stacks].value
|
185
184
|
existing_stacks = MultiJson.load(cache[:stacks].value)
|
186
185
|
# Force common types
|
187
186
|
stacks = MultiJson.load(MultiJson.dump(stacks))
|
188
|
-
if
|
187
|
+
if stack_id
|
189
188
|
stacks = existing_stacks.to_smash.deep_merge(stacks)
|
190
189
|
else
|
191
190
|
# Remove stacks that have been deleted
|
@@ -207,8 +206,8 @@ module Sfn
|
|
207
206
|
#
|
208
207
|
# @return [TrueClass, FalseClass]
|
209
208
|
def update_stack_list!
|
210
|
-
if
|
211
|
-
self.updater = Thread.new{
|
209
|
+
if updater.nil? || !updater.alive?
|
210
|
+
self.updater = Thread.new {
|
212
211
|
loop do
|
213
212
|
begin
|
214
213
|
fetch_stacks
|
@@ -231,7 +230,6 @@ module Sfn
|
|
231
230
|
def service_for(service)
|
232
231
|
connection.api_for(service)
|
233
232
|
end
|
234
|
-
|
235
233
|
end
|
236
234
|
end
|
237
235
|
|
data/lib/sfn/utils.rb
CHANGED
@@ -3,7 +3,6 @@ require 'sfn'
|
|
3
3
|
module Sfn
|
4
4
|
# Utility classes and modules
|
5
5
|
module Utils
|
6
|
-
|
7
6
|
autoload :Output, 'sfn/utils/output'
|
8
7
|
autoload :StackParameterValidator, 'sfn/utils/stack_parameter_validator'
|
9
8
|
autoload :StackParameterScrubber, 'sfn/utils/stack_parameter_scrubber'
|
@@ -18,6 +17,5 @@ module Sfn
|
|
18
17
|
extend JSON
|
19
18
|
extend ObjectStorage
|
20
19
|
extend Bogo::AnimalStrings
|
21
|
-
|
22
20
|
end
|
23
21
|
end
|
data/lib/sfn/utils/debug.rb
CHANGED
@@ -10,7 +10,7 @@ module Sfn
|
|
10
10
|
#
|
11
11
|
# @param msg [String]
|
12
12
|
def debug(msg)
|
13
|
-
if
|
13
|
+
if ENV['DEBUG'] || (respond_to?(:config) && config[:debug])
|
14
14
|
puts "<sfn - debug>: #{msg}"
|
15
15
|
end
|
16
16
|
end
|
@@ -28,6 +28,5 @@ module Sfn
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
32
31
|
end
|
33
32
|
end
|
data/lib/sfn/utils/json.rb
CHANGED
@@ -13,6 +13,7 @@ module Sfn
|
|
13
13
|
def _to_json(thing)
|
14
14
|
MultiJson.dump(thing)
|
15
15
|
end
|
16
|
+
|
16
17
|
alias_method :dump_json, :_to_json
|
17
18
|
|
18
19
|
# Load JSON data
|
@@ -22,6 +23,7 @@ module Sfn
|
|
22
23
|
def _from_json(thing)
|
23
24
|
MultiJson.load(thing)
|
24
25
|
end
|
26
|
+
|
25
27
|
alias_method :load_json, :_from_json
|
26
28
|
|
27
29
|
# Format object into pretty JSON
|
@@ -32,9 +34,8 @@ module Sfn
|
|
32
34
|
thing = _from_json(thing) if thing.is_a?(String)
|
33
35
|
MultiJson.dump(thing, :pretty => true)
|
34
36
|
end
|
35
|
-
alias_method :format_json, :_format_json
|
36
37
|
|
38
|
+
alias_method :format_json, :_format_json
|
37
39
|
end
|
38
|
-
|
39
40
|
end
|
40
41
|
end
|
@@ -17,12 +17,11 @@ module Sfn
|
|
17
17
|
content = object.is_a?(String) ? object : Utils._format_json(object)
|
18
18
|
directory.files.create(
|
19
19
|
:identity => path,
|
20
|
-
:body => content
|
20
|
+
:body => content,
|
21
21
|
)
|
22
22
|
loc = directory.service.service.name.split('::').last.downcase
|
23
23
|
"#{loc}://#{directory.identity}/#{path}"
|
24
24
|
end
|
25
|
-
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
data/lib/sfn/utils/output.rb
CHANGED
@@ -12,12 +12,12 @@ module Sfn
|
|
12
12
|
# @option args [TrueClass, FalseClass] :flat flatten result array
|
13
13
|
# @option args [Array] :attributes attributes to extract
|
14
14
|
# @todo this was extracted from events and needs to be cleaned up
|
15
|
-
def process(things, args={})
|
15
|
+
def process(things, args = {})
|
16
16
|
@event_ids ||= []
|
17
17
|
processed = things.reverse.map do |thing|
|
18
18
|
next if @event_ids.include?(thing['id'])
|
19
19
|
@event_ids.push(thing['id']).compact!
|
20
|
-
if
|
20
|
+
if args[:attributes]
|
21
21
|
args[:attributes].map do |key|
|
22
22
|
thing[key].to_s
|
23
23
|
end
|
@@ -34,9 +34,9 @@ module Sfn
|
|
34
34
|
# @param args [Hash]
|
35
35
|
# @option args [Array] :attributes
|
36
36
|
# @return [Array<String>] formatted titles
|
37
|
-
def get_titles(thing, args={})
|
37
|
+
def get_titles(thing, args = {})
|
38
38
|
attrs = args[:attributes] || []
|
39
|
-
if
|
39
|
+
if attrs.empty?
|
40
40
|
hash = thing.is_a?(Array) ? thing.first : thing
|
41
41
|
hash ||= {}
|
42
42
|
attrs = hash.keys
|
@@ -44,8 +44,8 @@ module Sfn
|
|
44
44
|
titles = attrs.map do |key|
|
45
45
|
camel(key).gsub(/([a-z])([A-Z])/, '\1 \2')
|
46
46
|
end.compact
|
47
|
-
if
|
48
|
-
titles.map{|s| @ui.color(s, :bold)}
|
47
|
+
if args[:format]
|
48
|
+
titles.map { |s| @ui.color(s, :bold) }
|
49
49
|
else
|
50
50
|
titles
|
51
51
|
end
|
@@ -58,7 +58,7 @@ module Sfn
|
|
58
58
|
# @param what [String] description of things for output
|
59
59
|
# @param args [Symbol] options (:ignore_empty_output)
|
60
60
|
def things_output(stack, things, what, *args)
|
61
|
-
unless
|
61
|
+
unless args.include?(:no_title)
|
62
62
|
output = get_titles(things, :format => true, :attributes => allowed_attributes)
|
63
63
|
else
|
64
64
|
output = []
|
@@ -66,14 +66,13 @@ module Sfn
|
|
66
66
|
columns = allowed_attributes.size
|
67
67
|
output += process(things, :flat => true, :attributes => allowed_attributes)
|
68
68
|
output.compact!
|
69
|
-
if
|
69
|
+
if output.empty?
|
70
70
|
ui.warn 'No information found' unless args.include?(:ignore_empty_output)
|
71
71
|
else
|
72
72
|
ui.info "#{what.to_s.capitalize} for stack: #{ui.color(stack, :bold)}" if stack
|
73
73
|
ui.info "#{ui.list(output, :uneven_columns_across, columns)}"
|
74
74
|
end
|
75
75
|
end
|
76
|
-
|
77
76
|
end
|
78
77
|
end
|
79
78
|
end
|
@@ -26,11 +26,11 @@ module Sfn
|
|
26
26
|
# @option opts [String] :files_name title for files
|
27
27
|
# @option opts [String] :filter_prefix only return results matching filter
|
28
28
|
# @return [String] file path
|
29
|
-
def prompt_for_file(directory, opts={})
|
29
|
+
def prompt_for_file(directory, opts = {})
|
30
30
|
file_list = Dir.glob(File.join(directory, '**', '**', '*')).find_all do |file|
|
31
31
|
File.file?(file)
|
32
32
|
end
|
33
|
-
if
|
33
|
+
if opts[:filter_prefix]
|
34
34
|
file_list = file_list.find_all do |file|
|
35
35
|
file.start_with?(options[:filter_prefix])
|
36
36
|
end
|
@@ -41,12 +41,12 @@ module Sfn
|
|
41
41
|
files = file_list.find_all do |path|
|
42
42
|
path.sub(directory, '').split('/').size == 2
|
43
43
|
end
|
44
|
-
if
|
44
|
+
if opts[:ignore_directories]
|
45
45
|
directories.delete_if do |dir|
|
46
46
|
opts[:ignore_directories].include?(File.basename(dir))
|
47
47
|
end
|
48
48
|
end
|
49
|
-
if
|
49
|
+
if directories.empty? && files.empty?
|
50
50
|
ui.fatal 'No formation paths discoverable!'
|
51
51
|
else
|
52
52
|
output = ['Please select an entry']
|
@@ -55,7 +55,7 @@ module Sfn
|
|
55
55
|
output.clear
|
56
56
|
idx = 1
|
57
57
|
valid = {}
|
58
|
-
unless
|
58
|
+
unless directories.empty?
|
59
59
|
output << ui.color("#{opts.fetch(:directories_name, 'Directories')}:", :bold)
|
60
60
|
directories.each do |dir|
|
61
61
|
valid[idx] = {:path => dir, :type => :directory}
|
@@ -63,7 +63,7 @@ module Sfn
|
|
63
63
|
idx += 1
|
64
64
|
end
|
65
65
|
end
|
66
|
-
unless
|
66
|
+
unless files.empty?
|
67
67
|
output << ui.color("#{opts.fetch(:files_name, 'Files')}:", :bold)
|
68
68
|
files.each do |file|
|
69
69
|
valid[idx] = {:path => file, :type => :file}
|
@@ -73,7 +73,7 @@ module Sfn
|
|
73
73
|
end
|
74
74
|
max = idx.to_s.length
|
75
75
|
output.map! do |o|
|
76
|
-
if
|
76
|
+
if o.is_a?(Array)
|
77
77
|
" #{o.first}.#{' ' * (max - o.first.to_s.length)} #{o.last}"
|
78
78
|
else
|
79
79
|
o
|
@@ -81,12 +81,12 @@ module Sfn
|
|
81
81
|
end
|
82
82
|
ui.info "#{output.join("\n")}\n"
|
83
83
|
response = ui.ask_question('Enter selection: ').to_i
|
84
|
-
unless
|
84
|
+
unless valid[response]
|
85
85
|
ui.fatal 'How about using a real value'
|
86
86
|
exit 1
|
87
87
|
else
|
88
88
|
entry = valid[response.to_i]
|
89
|
-
if
|
89
|
+
if entry[:type] == :directory
|
90
90
|
prompt_for_file(entry[:path], opts)
|
91
91
|
elsif Pathname(entry[:path]).absolute?
|
92
92
|
entry[:path]
|
@@ -96,7 +96,6 @@ module Sfn
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
end
|
99
|
-
|
100
99
|
end
|
101
100
|
end
|
102
101
|
end
|
data/lib/sfn/utils/ssher.rb
CHANGED
@@ -13,8 +13,8 @@ module Sfn
|
|
13
13
|
# @param path [String] remote file path
|
14
14
|
# @param ssh_opts [Hash]
|
15
15
|
# @return [String, NilClass]
|
16
|
-
def remote_file_contents(address, user, path, ssh_opts={})
|
17
|
-
if
|
16
|
+
def remote_file_contents(address, user, path, ssh_opts = {})
|
17
|
+
if path.to_s.strip.empty?
|
18
18
|
raise ArgumentError.new 'No file path provided!'
|
19
19
|
end
|
20
20
|
require 'net/ssh'
|
@@ -23,7 +23,6 @@ module Sfn
|
|
23
23
|
content = ssh_session.exec!("sudo cat #{path}")
|
24
24
|
content.empty? ? nil : content
|
25
25
|
end
|
26
|
-
|
27
26
|
end
|
28
27
|
end
|
29
28
|
end
|
@@ -10,7 +10,6 @@ module Sfn
|
|
10
10
|
|
11
11
|
# Stack serialization helper
|
12
12
|
class StackExporter
|
13
|
-
|
14
13
|
include Bogo::AnimalStrings
|
15
14
|
include Sfn::Utils::JSON
|
16
15
|
|
@@ -20,7 +19,7 @@ module Sfn
|
|
20
19
|
DEFAULT_OPTIONS = Mash.new(
|
21
20
|
:chef_popsicle => true,
|
22
21
|
:ignored_parameters => ['Environment', 'StackCreator', 'Creator'],
|
23
|
-
:chef_environment_parameter => 'Environment'
|
22
|
+
:chef_environment_parameter => 'Environment',
|
24
23
|
)
|
25
24
|
# default structure of export payload
|
26
25
|
DEFAULT_EXPORT_STRUCTURE = {
|
@@ -29,15 +28,15 @@ module Sfn
|
|
29
28
|
:options => {
|
30
29
|
:parameters => Mash.new,
|
31
30
|
:capabilities => [],
|
32
|
-
:notification_topics => []
|
33
|
-
}
|
31
|
+
:notification_topics => [],
|
32
|
+
},
|
34
33
|
),
|
35
34
|
:generator => {
|
36
35
|
:timestamp => Time.now.to_i,
|
37
36
|
:name => 'SparkleFormation',
|
38
37
|
:version => Sfn::VERSION.version,
|
39
|
-
:provider => nil
|
40
|
-
}
|
38
|
+
:provider => nil,
|
39
|
+
},
|
41
40
|
}
|
42
41
|
|
43
42
|
# @return [Miasma::Models::Orchestration::Stack]
|
@@ -55,7 +54,7 @@ module Sfn
|
|
55
54
|
# @option options [TrueClass, FalseClass] :chef_popsicle freeze run list
|
56
55
|
# @option options [Array<String>] :ignored_parameters
|
57
56
|
# @option options [String] :chef_environment_parameter
|
58
|
-
def initialize(stack, options={})
|
57
|
+
def initialize(stack, options = {})
|
59
58
|
@stack = stack
|
60
59
|
@options = DEFAULT_OPTIONS.merge(options)
|
61
60
|
@stack_export = Smash.new
|
@@ -67,14 +66,14 @@ module Sfn
|
|
67
66
|
def export
|
68
67
|
@stack_export = Smash.new(DEFAULT_EXPORT_STRUCTURE).tap do |stack_export|
|
69
68
|
[:parameters, :capabilities, :notification_topics].each do |key|
|
70
|
-
if
|
69
|
+
if val = stack.send(key)
|
71
70
|
stack_export[:stack][key] = val
|
72
71
|
end
|
73
72
|
end
|
74
73
|
stack_export[:stack][:template] = stack.template
|
75
74
|
stack_export[:generator][:timestamp] = Time.now.to_i
|
76
75
|
stack_export[:generator][:provider] = stack.provider.connection.provider
|
77
|
-
if
|
76
|
+
if chef_popsicle? && defined?(Chef)
|
78
77
|
freeze_runlists(stack_export)
|
79
78
|
end
|
80
79
|
remove_ignored_parameters(stack_export)
|
@@ -90,7 +89,7 @@ module Sfn
|
|
90
89
|
# @return [Object]
|
91
90
|
def method_missing(*args)
|
92
91
|
m = args.first.to_s
|
93
|
-
if
|
92
|
+
if m.end_with?('?') && options.has_key?(k = m.sub('?', '').to_sym)
|
94
93
|
!!options[k]
|
95
94
|
else
|
96
95
|
super
|
@@ -106,7 +105,7 @@ module Sfn
|
|
106
105
|
# @return [Hash]
|
107
106
|
def remove_ignored_parameters(export)
|
108
107
|
options[:ignored_parameters].each do |param|
|
109
|
-
if
|
108
|
+
if export[:stack][:options][:parameters]
|
110
109
|
export[:stack][:options][:parameters].delete(param)
|
111
110
|
end
|
112
111
|
end
|
@@ -118,7 +117,7 @@ module Sfn
|
|
118
117
|
# @param export [Hash] current export state
|
119
118
|
# @return [String] environment name
|
120
119
|
def chef_environment_name(export)
|
121
|
-
if
|
120
|
+
if chef_environment_parameter?
|
122
121
|
name = export[:stack][:options][:parameters][options[:chef_environment_parameter]]
|
123
122
|
end
|
124
123
|
name || DEFAULT_CHEF_ENVIRONMENT
|
@@ -126,7 +125,7 @@ module Sfn
|
|
126
125
|
|
127
126
|
# @return [Chef::Environment]
|
128
127
|
def environment
|
129
|
-
unless
|
128
|
+
unless @env
|
130
129
|
@env = Chef::Environment.load('_default')
|
131
130
|
end
|
132
131
|
@env
|
@@ -154,11 +153,11 @@ module Sfn
|
|
154
153
|
def extract_runlist_item(item)
|
155
154
|
rl_item = item.is_a?(Chef::RunList::RunListItem) ? item : Chef::RunList::RunListItem.new(item)
|
156
155
|
static_content = Mash.new(:run_list => [])
|
157
|
-
if
|
156
|
+
if rl_item.recipe?
|
158
157
|
cookbook, recipe = rl_item.name.split('::')
|
159
158
|
peg_version = allowed_cookbook_version(cookbook)
|
160
159
|
static_content[:run_list] << "recipe[#{[cookbook, recipe || 'default'].join('::')}@#{peg_version}]"
|
161
|
-
elsif
|
160
|
+
elsif rl_item.role?
|
162
161
|
role = Chef::Role.load(rl_item.name)
|
163
162
|
role.run_list.each do |item|
|
164
163
|
static_content = Chef::Mixin::DeepMerge.merge(static_content, extract_runlist_item(item))
|
@@ -209,10 +208,10 @@ module Sfn
|
|
209
208
|
result = []
|
210
209
|
case thing
|
211
210
|
when Hash
|
212
|
-
if
|
211
|
+
if thing['content'] && thing['content']['run_list']
|
213
212
|
result << thing['content']
|
214
213
|
else
|
215
|
-
thing.each do |k,v|
|
214
|
+
thing.each do |k, v|
|
216
215
|
result += locate_runlists(v)
|
217
216
|
end
|
218
217
|
end
|
@@ -229,7 +228,7 @@ module Sfn
|
|
229
228
|
# @param hsh [Object] stack template item
|
230
229
|
# @return [Object]
|
231
230
|
def cf_replace(hsh)
|
232
|
-
if
|
231
|
+
if hsh.is_a?(Hash)
|
233
232
|
case hsh.keys.first
|
234
233
|
when 'Fn::Join'
|
235
234
|
cf_join(*hsh.values.first)
|
@@ -248,11 +247,11 @@ module Sfn
|
|
248
247
|
# @param ref_name [Hash]
|
249
248
|
# @return [Object] value in parameters
|
250
249
|
def cf_ref(ref_name)
|
251
|
-
if
|
250
|
+
if stack.parameters.has_key?(ref_name)
|
252
251
|
stack.parameters[ref_name]
|
253
252
|
else
|
254
253
|
raise KeyError.new("No parameter found with given reference name (#{ref_name}). " <<
|
255
|
-
|
254
|
+
"Only parameter based references supported!")
|
256
255
|
end
|
257
256
|
end
|
258
257
|
|
@@ -263,7 +262,7 @@ module Sfn
|
|
263
262
|
# @return [String]
|
264
263
|
def cf_join(delim, args)
|
265
264
|
args.map do |arg|
|
266
|
-
if
|
265
|
+
if arg.is_a?(Hash)
|
267
266
|
cf_replace(arg)
|
268
267
|
else
|
269
268
|
arg.to_s
|