sfn 3.0.28 → 3.0.30
Sign up to get free protection for your applications and to get access to all the features.
- 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
|