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/command/destroy.rb
CHANGED
@@ -3,7 +3,6 @@ require 'sfn'
|
|
3
3
|
module Sfn
|
4
4
|
class Command
|
5
5
|
class Destroy < Command
|
6
|
-
|
7
6
|
include Sfn::CommandModule::Base
|
8
7
|
|
9
8
|
# Run the stack destruction action
|
@@ -14,7 +13,7 @@ module Sfn
|
|
14
13
|
globs = stacks.find_all do |s|
|
15
14
|
s !~ /^[a-zA-Z0-9-]+$/
|
16
15
|
end
|
17
|
-
unless
|
16
|
+
unless globs.empty?
|
18
17
|
glob_stacks = provider.connection.stacks.all.find_all do |remote_stack|
|
19
18
|
globs.detect do |glob|
|
20
19
|
File.fnmatch(glob, remote_stack.name)
|
@@ -28,7 +27,7 @@ module Sfn
|
|
28
27
|
ui.confirm "Destroy listed stack#{plural}?"
|
29
28
|
stacks.each do |stack_name|
|
30
29
|
stack = provider.connection.stacks.get(stack_name)
|
31
|
-
if
|
30
|
+
if stack
|
32
31
|
nested_stack_cleanup!(stack)
|
33
32
|
begin
|
34
33
|
api_action!(:api_stack => stack) do
|
@@ -44,12 +43,12 @@ module Sfn
|
|
44
43
|
ui.warn "Failed to locate requested stack: #{ui.color(stack_name, :bold)}"
|
45
44
|
end
|
46
45
|
end
|
47
|
-
if
|
48
|
-
if
|
46
|
+
if config[:poll]
|
47
|
+
if stacks.size == 1
|
49
48
|
begin
|
50
49
|
poll_stack(stacks.first)
|
51
50
|
rescue Miasma::Error::ApiError::RequestError => error
|
52
|
-
unless
|
51
|
+
unless error.response.code == 404
|
53
52
|
raise error
|
54
53
|
end
|
55
54
|
end
|
@@ -69,12 +68,12 @@ module Sfn
|
|
69
68
|
provider.connection.data[:stack_types].include?(resource['Type'])
|
70
69
|
end.each do |resource|
|
71
70
|
url = resource['Properties']['TemplateURL']
|
72
|
-
if
|
71
|
+
if url && url.is_a?(String)
|
73
72
|
_, bucket_name, path = URI.parse(url).path.split('/', 3)
|
74
73
|
bucket = provider.connection.api_for(:storage).buckets.get(bucket_name)
|
75
|
-
if
|
74
|
+
if bucket
|
76
75
|
file = bucket.files.get(path)
|
77
|
-
if
|
76
|
+
if file
|
78
77
|
file.destroy
|
79
78
|
ui.info "Deleted nested stack template! (Bucket: #{bucket_name} Template: #{path})"
|
80
79
|
else
|
@@ -86,7 +85,6 @@ module Sfn
|
|
86
85
|
end
|
87
86
|
end
|
88
87
|
end
|
89
|
-
|
90
88
|
end
|
91
89
|
end
|
92
90
|
end
|
data/lib/sfn/command/diff.rb
CHANGED
@@ -6,7 +6,6 @@ module Sfn
|
|
6
6
|
class Command
|
7
7
|
# Diff command
|
8
8
|
class Diff < Command
|
9
|
-
|
10
9
|
include Sfn::CommandModule::Base
|
11
10
|
include Sfn::CommandModule::Template
|
12
11
|
include Sfn::CommandModule::Stack
|
@@ -22,7 +21,7 @@ module Sfn
|
|
22
21
|
stack = nil
|
23
22
|
end
|
24
23
|
|
25
|
-
if
|
24
|
+
if stack
|
26
25
|
config[:print_only] = true
|
27
26
|
file = load_template_file
|
28
27
|
file = parameter_scrub!(file.dump)
|
@@ -38,7 +37,7 @@ module Sfn
|
|
38
37
|
end
|
39
38
|
|
40
39
|
# @todo needs updates for better provider compat
|
41
|
-
def diff_stack(stack, file, parent_names=[])
|
40
|
+
def diff_stack(stack, file, parent_names = [])
|
42
41
|
stack_template = stack.template
|
43
42
|
nested_stacks = Hash[
|
44
43
|
file.fetch('Resources', file.fetch('resources', {})).find_all do |name, value|
|
@@ -49,7 +48,7 @@ module Sfn
|
|
49
48
|
n_stack = stack.nested_stacks(false).detect do |ns|
|
50
49
|
ns.data[:logical_id] == name
|
51
50
|
end
|
52
|
-
if
|
51
|
+
if n_stack
|
53
52
|
diff_stack(n_stack, value['Properties']['Stack'], [*parent_names, stack.data.fetch(:logical_id, stack.name)].compact)
|
54
53
|
end
|
55
54
|
file['Resources'][name]['Properties'].delete('Stack')
|
@@ -59,12 +58,11 @@ module Sfn
|
|
59
58
|
|
60
59
|
stack_diff = HashDiff.diff(stack.template, file)
|
61
60
|
|
62
|
-
if
|
61
|
+
if config[:raw_diff]
|
63
62
|
ui.info "Dumping raw template diff:"
|
64
63
|
require 'pp'
|
65
64
|
pp stack_diff
|
66
65
|
else
|
67
|
-
|
68
66
|
added_resources = stack_diff.find_all do |item|
|
69
67
|
item.first == '+' && item[1].match(/Resources\.[^.]+$/)
|
70
68
|
end
|
@@ -77,12 +75,11 @@ module Sfn
|
|
77
75
|
!item[1].include?('Properties.Parameters')
|
78
76
|
end - added_resources - removed_resources
|
79
77
|
|
80
|
-
if
|
78
|
+
if added_resources.empty? && removed_resources.empty? && modified_resources.empty?
|
81
79
|
ui.info 'No changes detected'
|
82
80
|
ui.puts
|
83
81
|
else
|
84
|
-
|
85
|
-
unless(added_resources.empty?)
|
82
|
+
unless added_resources.empty?
|
86
83
|
ui.info ui.color('Added Resources:', :green, :bold)
|
87
84
|
added_resources.each do |item|
|
88
85
|
ui.print ui.color(" -> #{item[1].split('.').last}", :green)
|
@@ -91,7 +88,7 @@ module Sfn
|
|
91
88
|
ui.puts
|
92
89
|
end
|
93
90
|
|
94
|
-
unless
|
91
|
+
unless modified_resources.empty?
|
95
92
|
ui.info ui.color('Modified Resources:', :yellow, :bold)
|
96
93
|
m_resources = Hash.new.tap do |hash|
|
97
94
|
modified_resources.each do |item|
|
@@ -102,8 +99,8 @@ module Sfn
|
|
102
99
|
matched = hash[key][prefix].detect do |i|
|
103
100
|
i[:path] == a_key
|
104
101
|
end
|
105
|
-
if
|
106
|
-
if
|
102
|
+
if matched
|
103
|
+
if item.first == '-'
|
107
104
|
matched[:original] = item[2]
|
108
105
|
else
|
109
106
|
matched[:new] = item[2]
|
@@ -137,7 +134,7 @@ module Sfn
|
|
137
134
|
ui.puts
|
138
135
|
end
|
139
136
|
|
140
|
-
unless
|
137
|
+
unless removed_resources.empty?
|
141
138
|
ui.info ui.color('Removed Resources:', :red, :bold)
|
142
139
|
removed_resources.each do |item|
|
143
140
|
ui.print ui.color(" <- #{item[1].split('.').last}", :red)
|
@@ -147,21 +144,17 @@ module Sfn
|
|
147
144
|
end
|
148
145
|
|
149
146
|
run_callbacks_for(:after_stack_diff,
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
)
|
147
|
+
:diff => stack_diff,
|
148
|
+
:diff_info => {
|
149
|
+
:added => added_resources,
|
150
|
+
:modified => modified_resources,
|
151
|
+
:removed => removed_resources,
|
152
|
+
},
|
153
|
+
:api_stack => stack,
|
154
|
+
:new_template => file)
|
159
155
|
end
|
160
|
-
|
161
156
|
end
|
162
|
-
|
163
157
|
end
|
164
|
-
|
165
158
|
end
|
166
159
|
end
|
167
160
|
end
|
data/lib/sfn/command/events.rb
CHANGED
@@ -4,7 +4,6 @@ module Sfn
|
|
4
4
|
class Command
|
5
5
|
# Events command
|
6
6
|
class Events < Command
|
7
|
-
|
8
7
|
include Sfn::CommandModule::Base
|
9
8
|
|
10
9
|
# @return [Miasma::Models::Orchestration::Stack]
|
@@ -17,14 +16,14 @@ module Sfn
|
|
17
16
|
ui.info "Events for Stack: #{ui.color(name, :bold)}\n"
|
18
17
|
@seen_events = []
|
19
18
|
@stack = provider.stack(name)
|
20
|
-
if
|
19
|
+
if stack
|
21
20
|
api_action!(:api_stack => stack) do
|
22
21
|
table = ui.table(self) do
|
23
22
|
table(:border => false) do
|
24
23
|
events = get_events
|
25
24
|
row(:header => true) do
|
26
25
|
allowed_attributes.each do |attr|
|
27
|
-
width_val = events.map{|e| e[attr].to_s.length}.push(attr.length).max + 2
|
26
|
+
width_val = events.map { |e| e[attr].to_s.length }.push(attr.length).max + 2
|
28
27
|
width_val = width_val > 70 ? 70 : width_val < 20 ? 20 : width_val
|
29
28
|
column attr.split('_').map(&:capitalize).join(' '), :width => width_val
|
30
29
|
end
|
@@ -38,10 +37,10 @@ module Sfn
|
|
38
37
|
end
|
39
38
|
end
|
40
39
|
end.display
|
41
|
-
if
|
42
|
-
while(stack.reload.in_progress?)
|
40
|
+
if config[:poll]
|
41
|
+
while (stack.reload.in_progress?)
|
43
42
|
to_wait = config.fetch(:poll_wait_time, 10).to_f
|
44
|
-
while(to_wait > 0)
|
43
|
+
while (to_wait > 0)
|
45
44
|
sleep(0.1)
|
46
45
|
to_wait -= 0.1
|
47
46
|
end
|
@@ -65,13 +64,13 @@ module Sfn
|
|
65
64
|
stack_events = discover_stacks(stack).map do |i_stack|
|
66
65
|
i_events = []
|
67
66
|
begin
|
68
|
-
if
|
67
|
+
if @initial_complete && i_stack.in_progress?
|
69
68
|
i_events = i_stack.events.update!
|
70
69
|
else
|
71
70
|
i_events = i_stack.events.all
|
72
71
|
end
|
73
72
|
rescue => e
|
74
|
-
if
|
73
|
+
if e.class.to_s.start_with?('Errno')
|
75
74
|
ui.warn "Connection error encountered: #{e.message} (retrying)"
|
76
75
|
ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
77
76
|
else
|
@@ -81,23 +80,23 @@ module Sfn
|
|
81
80
|
sleep(5)
|
82
81
|
retry
|
83
82
|
end
|
84
|
-
if
|
83
|
+
if i_events
|
85
84
|
i_events.map do |e|
|
86
85
|
e.attributes.merge(:stack_name => i_stack.name).to_smash
|
87
86
|
end
|
88
87
|
end
|
89
|
-
end.flatten.compact.find_all{|e| e[:time] }.reverse
|
90
|
-
stack_events.delete_if{|evt| @seen_events.include?(evt)}
|
88
|
+
end.flatten.compact.find_all { |e| e[:time] }.reverse
|
89
|
+
stack_events.delete_if { |evt| @seen_events.include?(evt) }
|
91
90
|
@seen_events.concat(stack_events)
|
92
|
-
unless
|
93
|
-
stack_events = stack_events.sort_by{|e| e[:time] }
|
94
|
-
unless
|
91
|
+
unless @initial_complete
|
92
|
+
stack_events = stack_events.sort_by { |e| e[:time] }
|
93
|
+
unless config[:all_events]
|
95
94
|
start_index = stack_events.rindex do |item|
|
96
95
|
item[:stack_name] == stack.name &&
|
97
96
|
item[:resource_state].to_s.end_with?('in_progress') &&
|
98
97
|
item[:resource_status_reason].to_s.downcase.include?('user init')
|
99
98
|
end
|
100
|
-
if
|
99
|
+
if start_index
|
101
100
|
stack_events.slice!(0, start_index)
|
102
101
|
end
|
103
102
|
end
|
@@ -121,7 +120,7 @@ module Sfn
|
|
121
120
|
# @return [Array<String>] allowed attributes for events
|
122
121
|
def allowed_attributes
|
123
122
|
result = super
|
124
|
-
unless
|
123
|
+
unless @stacks.size > 1
|
125
124
|
result.delete('stack_name')
|
126
125
|
end
|
127
126
|
result
|
data/lib/sfn/command/export.rb
CHANGED
@@ -4,7 +4,6 @@ module Sfn
|
|
4
4
|
class Command
|
5
5
|
# Export command
|
6
6
|
class Export < Command
|
7
|
-
|
8
7
|
include Sfn::CommandModule::Base
|
9
8
|
include Sfn::Utils::ObjectStorage
|
10
9
|
|
@@ -15,7 +14,7 @@ module Sfn
|
|
15
14
|
ui.info "#{ui.color('Stack Export:', :bold)} #{stack_name}"
|
16
15
|
ui.confirm 'Perform export'
|
17
16
|
stack = provider.stacks.get(stack_name)
|
18
|
-
if
|
17
|
+
if stack
|
19
18
|
export_options = Smash.new.tap do |opts|
|
20
19
|
[:chef_popsicle, :chef_environment_parameter, :ignore_parameters].each do |key|
|
21
20
|
opts[key] = config[key] unless config[key].nil?
|
@@ -25,14 +24,14 @@ module Sfn
|
|
25
24
|
result = exporter.export
|
26
25
|
outputs = [
|
27
26
|
write_to_file(result, stack),
|
28
|
-
write_to_bucket(result, stack)
|
27
|
+
write_to_bucket(result, stack),
|
29
28
|
].compact
|
30
|
-
if
|
29
|
+
if outputs.empty?
|
31
30
|
ui.warn 'No persistent output location defined. Printing export:'
|
32
31
|
ui.info _format_json(result)
|
33
32
|
end
|
34
33
|
ui.info "#{ui.color('Stack export', :bold)} (#{name_args.first}): #{ui.color('complete', :green)}"
|
35
|
-
unless
|
34
|
+
unless outputs.empty?
|
36
35
|
outputs.each do |output|
|
37
36
|
ui.info ui.color(" -> #{output}", :blue)
|
38
37
|
end
|
@@ -49,8 +48,8 @@ module Sfn
|
|
49
48
|
# @return [String] file name
|
50
49
|
def export_file_name(stack)
|
51
50
|
name = config[:file]
|
52
|
-
if
|
53
|
-
if
|
51
|
+
if name
|
52
|
+
if name.respond_to?(:call)
|
54
53
|
name.call(stack)
|
55
54
|
else
|
56
55
|
name.to_s
|
@@ -67,16 +66,15 @@ module Sfn
|
|
67
66
|
# @return [String, NilClass] path to file
|
68
67
|
def write_to_file(payload, stack)
|
69
68
|
raise NotImplementedError
|
70
|
-
if
|
69
|
+
if config[:path]
|
71
70
|
full_path = File.join(
|
72
71
|
config[:path],
|
73
72
|
export_file_name(stack)
|
74
73
|
)
|
75
74
|
_, bucket, path = full_path.split('/', 3)
|
76
75
|
directory = provider.service_for(:storage,
|
77
|
-
|
78
|
-
|
79
|
-
).directories.get(bucket)
|
76
|
+
:provider => :local,
|
77
|
+
:local_root => '/').directories.get(bucket)
|
80
78
|
file_store(payload, path, directory)
|
81
79
|
end
|
82
80
|
end
|
@@ -88,16 +86,14 @@ module Sfn
|
|
88
86
|
# @return [String, NilClass] remote bucket key
|
89
87
|
def write_to_bucket(payload, stack)
|
90
88
|
raise NotImplementedError
|
91
|
-
if
|
89
|
+
if bucket = config[:bucket]
|
92
90
|
key_path = File.join(*[
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
)
|
91
|
+
bucket_prefix(stack),
|
92
|
+
export_file_name(stack),
|
93
|
+
].compact)
|
97
94
|
file_store(payload, key_path, provider.service_for(:storage).directories.get(bucket))
|
98
95
|
end
|
99
96
|
end
|
100
|
-
|
101
97
|
end
|
102
98
|
end
|
103
99
|
end
|
data/lib/sfn/command/graph.rb
CHANGED
@@ -5,7 +5,6 @@ module Sfn
|
|
5
5
|
class Command
|
6
6
|
# Graph command
|
7
7
|
class Graph < Command
|
8
|
-
|
9
8
|
autoload :Provider, 'sfn/command/graph/provider'
|
10
9
|
|
11
10
|
include Sfn::CommandModule::Base
|
@@ -15,7 +14,7 @@ module Sfn
|
|
15
14
|
# Valid graph styles
|
16
15
|
GRAPH_STYLES = [
|
17
16
|
'creation',
|
18
|
-
'dependency'
|
17
|
+
'dependency',
|
19
18
|
]
|
20
19
|
|
21
20
|
# Generate graph
|
@@ -24,13 +23,13 @@ module Sfn
|
|
24
23
|
validate_graph_style!
|
25
24
|
file = load_template_file
|
26
25
|
provider = Bogo::Utility.camel(file.provider).to_sym
|
27
|
-
if
|
26
|
+
if Provider.constants.include?(provider)
|
28
27
|
graph_const = Provider.const_get(provider)
|
29
28
|
ui.debug "Loading provider graph implementation - #{graph_const}"
|
30
29
|
extend graph_const
|
31
30
|
@outputs = Smash.new
|
32
31
|
ui.info "Template resource graph generation - Style: #{ui.color(config[:graph_style], :bold)}"
|
33
|
-
if
|
32
|
+
if config[:file]
|
34
33
|
ui.puts " -> path: #{config[:file]}"
|
35
34
|
end
|
36
35
|
template_dump = file.compile.sparkle_dump!.to_smash
|
@@ -49,7 +48,7 @@ module Sfn
|
|
49
48
|
end
|
50
49
|
run_action 'Writing graph result' do
|
51
50
|
FileUtils.mkdir_p(File.dirname(config[:output_file]))
|
52
|
-
if
|
51
|
+
if config[:output_type] == 'dot'
|
53
52
|
File.open("#{config[:output_file]}.dot", 'w') do |o_file|
|
54
53
|
o_file.puts graph.to_s
|
55
54
|
end
|
@@ -59,7 +58,7 @@ module Sfn
|
|
59
58
|
nil
|
60
59
|
end
|
61
60
|
else
|
62
|
-
valid_providers = Provider.constants.sort.map{ |provider|
|
61
|
+
valid_providers = Provider.constants.sort.map { |provider|
|
63
62
|
Bogo::Utility.snake(provider)
|
64
63
|
}.join('`, `')
|
65
64
|
ui.error "Graphing for provider `#{file.provider}` not currently supported."
|
@@ -67,14 +66,14 @@ module Sfn
|
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
70
|
-
def generate_graph(template, args={})
|
69
|
+
def generate_graph(template, args = {})
|
71
70
|
graph = ::Graph.new
|
72
71
|
@root_graph = graph unless @root_graph
|
73
72
|
graph.graph_attribs << ::Graph::Attribute.new('overlap = false')
|
74
73
|
graph.graph_attribs << ::Graph::Attribute.new('splines = true')
|
75
74
|
graph.graph_attribs << ::Graph::Attribute.new('pack = true')
|
76
75
|
graph.graph_attribs << ::Graph::Attribute.new('start = "random"')
|
77
|
-
if
|
76
|
+
if args[:name]
|
78
77
|
graph.name = "cluster_#{args[:name]}"
|
79
78
|
labelnode_key = "cluster_#{args[:name]}"
|
80
79
|
graph.plaintext << graph.node(labelnode_key)
|
@@ -88,7 +87,7 @@ module Sfn
|
|
88
87
|
|
89
88
|
def colorize(string)
|
90
89
|
hash = string.chars.inject(0) do |memo, chr|
|
91
|
-
if
|
90
|
+
if memo + chr.ord > 127
|
92
91
|
(memo - chr.ord).abs
|
93
92
|
else
|
94
93
|
memo + chr.ord
|
@@ -98,7 +97,7 @@ module Sfn
|
|
98
97
|
3.times do |i|
|
99
98
|
color << (255 ^ hash).to_s(16)
|
100
99
|
new_val = hash + (hash * (1 / (i + 1.to_f))).to_i
|
101
|
-
if
|
100
|
+
if hash * (i + 1) < 127
|
102
101
|
hash = new_val
|
103
102
|
else
|
104
103
|
hash = hash / (i + 1)
|
@@ -108,16 +107,15 @@ module Sfn
|
|
108
107
|
end
|
109
108
|
|
110
109
|
def validate_graph_style!
|
111
|
-
if
|
110
|
+
if config[:luckymike]
|
112
111
|
ui.warn 'Detected luckymike power override. Forcing `dependency` style!'
|
113
112
|
config[:graph_style] = 'dependency'
|
114
113
|
end
|
115
114
|
config[:graph_style] = config[:graph_style].to_s
|
116
|
-
unless
|
115
|
+
unless GRAPH_STYLES.include?(config[:graph_style])
|
117
116
|
raise ArgumentError.new "Invalid graph style provided `#{config[:graph_style]}`. Valid: `#{GRAPH_STYLES.join('`, `')}`"
|
118
117
|
end
|
119
118
|
end
|
120
|
-
|
121
119
|
end
|
122
120
|
end
|
123
121
|
end
|