sfn 3.0.20 → 3.0.22
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 +6 -0
- data/README.md +1 -0
- data/lib/sfn/api_provider.rb +1 -0
- data/lib/sfn/api_provider/terraform.rb +71 -0
- data/lib/sfn/callback/stack_policy.rb +16 -7
- data/lib/sfn/command/conf.rb +9 -1
- data/lib/sfn/command/destroy.rb +8 -2
- data/lib/sfn/command/graph.rb +8 -9
- data/lib/sfn/command/update.rb +0 -1
- data/lib/sfn/command_module/stack.rb +27 -11
- data/lib/sfn/command_module/template.rb +27 -10
- data/lib/sfn/config/validate.rb +13 -4
- data/lib/sfn/planner/aws.rb +163 -39
- data/lib/sfn/provider.rb +1 -1
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +5 -2
- metadata +56 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 279982d00c24881c257eff78a3d14ed604952146
|
4
|
+
data.tar.gz: 9a093919f17154f3fc20920b933691f0438c0583
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01741b34e7ef10214fa4f8902d2d35d1f175752d822f632e8f21e20ffdf5721e0a667fdf2f5ed1d5d56c87e87d3c8afb24319622bcbd62af70aa8e4c509b1a45
|
7
|
+
data.tar.gz: 57220d7bc625e74aa0b7f9f5ecbbc4fc22e77f56d11a3fda68bd1d5583ef4b84bb0084322496f7188b16d061212c51eeaf839c731290bc12e85ec523733a61ec
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# v3.0.22
|
2
|
+
* [fix] Properly match compile time parameters (#235)
|
3
|
+
* [fix] Remove AWS policy statements for undefined resources (#240)
|
4
|
+
* [enhancement] Support conditions when possible within planner (#230)
|
5
|
+
* [feature] Add alpha support for Terraform (#236)
|
6
|
+
|
1
7
|
# v3.0.20
|
2
8
|
* [fix] Only dump templates when dumpable (#220, #223)
|
3
9
|
* [enhancement] Support NoEcho template parameters (#226)
|
data/README.md
CHANGED
data/lib/sfn/api_provider.rb
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
module ApiProvider
|
5
|
+
|
6
|
+
module Terraform
|
7
|
+
|
8
|
+
# Disable remote template storage
|
9
|
+
def store_template(*_)
|
10
|
+
end
|
11
|
+
|
12
|
+
# No formatting required on stack results
|
13
|
+
def format_nested_stack_results(*_)
|
14
|
+
{}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Extract current parameters from parent template
|
18
|
+
#
|
19
|
+
# @param stack [SparkleFormation]
|
20
|
+
# @param stack_name [String]
|
21
|
+
# @param c_stack [Miasma::Models::Orchestration::Stack]
|
22
|
+
# @return [Hash]
|
23
|
+
def extract_current_nested_template_parameters(stack, stack_name, c_stack)
|
24
|
+
if(c_stack && c_stack.data[:parent_stack])
|
25
|
+
c_stack.data[:parent_stack].sparkleish_template(:remove_wrapper).fetch(
|
26
|
+
:resources, stack_name, :properties, :parameters, Smash.new
|
27
|
+
)
|
28
|
+
elsif(stack.parent)
|
29
|
+
val = stack.parent.compile.resources.set!(stack_name).properties
|
30
|
+
val.nil? ? Smash.new : val._dump
|
31
|
+
else
|
32
|
+
Smash.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Disable parameter validate as we can't adjust them without template modifications
|
37
|
+
def validate_stack_parameter(*_)
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
# Determine if parameter was set via intrinsic function
|
42
|
+
#
|
43
|
+
# @param val [Object]
|
44
|
+
# @return [TrueClass, FalseClass]
|
45
|
+
def function_set_parameter?(val)
|
46
|
+
if(val)
|
47
|
+
val.start_with?('${')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Override requirement of nesting bucket
|
52
|
+
def validate_nesting_bucket!
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
# Override template content extraction to disable scrub behavior
|
57
|
+
#
|
58
|
+
# @param thing [SparkleFormation, Hash]
|
59
|
+
# @return [Hash]
|
60
|
+
def template_content(thing, *_)
|
61
|
+
if(thing.is_a?(SparkleFormation))
|
62
|
+
config[:sparkle_dump] ? thing.sparkle_dump : thing.dump
|
63
|
+
else
|
64
|
+
thing
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -74,19 +74,28 @@ module Sfn
|
|
74
74
|
# @param p_stack [Miasma::Models::Orchestration::Stack]
|
75
75
|
# @return [NilClass]
|
76
76
|
def save_stack_policy(p_stack)
|
77
|
+
valid_logical_ids = p_stack.resources.reload.all.map(&:logical_id)
|
78
|
+
stack_policy = @policies.fetch(p_stack.id,
|
79
|
+
@policies.fetch(p_stack.data[:logical_id]),
|
80
|
+
@policies[p_stack.name]
|
81
|
+
).to_smash
|
82
|
+
if(stack_policy)
|
83
|
+
stack_policy[:statement].delete_if do |policy_item|
|
84
|
+
policy_match = policy_item[:resource].to_s.match(
|
85
|
+
%r{LogicalResourceId/(?<logical_id>.+)$}
|
86
|
+
)
|
87
|
+
if(policy_match)
|
88
|
+
!valid_logical_ids.include?(policy_match["logical_id"])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
77
92
|
result = p_stack.api.request(
|
78
93
|
:path => '/',
|
79
94
|
:method => :post,
|
80
95
|
:form => Smash.new(
|
81
96
|
'Action' => 'SetStackPolicy',
|
82
97
|
'StackName' => p_stack.id,
|
83
|
-
'StackPolicyBody' => MultiJson.dump(
|
84
|
-
@policies.fetch(p_stack.id,
|
85
|
-
@policies.fetch(p_stack.data[:logical_id],
|
86
|
-
@policies[p_stack.name]
|
87
|
-
)
|
88
|
-
)
|
89
|
-
)
|
98
|
+
'StackPolicyBody' => MultiJson.dump(stack_policy)
|
90
99
|
)
|
91
100
|
)
|
92
101
|
end
|
data/lib/sfn/command/conf.rb
CHANGED
@@ -83,7 +83,7 @@ Configuration.new do
|
|
83
83
|
# nesting_prefix 'nested-templates'
|
84
84
|
# Remote provider credentials
|
85
85
|
credentials do
|
86
|
-
# Remote provider name (:aws, :azure, :google, :open_stack, :rackspace)
|
86
|
+
# Remote provider name (:aws, :azure, :google, :open_stack, :rackspace, :terraform)
|
87
87
|
provider :aws
|
88
88
|
# AWS credentials information
|
89
89
|
aws_access_key_id ENV['AWS_ACCESS_KEY_ID']
|
@@ -123,6 +123,14 @@ Configuration.new do
|
|
123
123
|
google_service_account_email ENV['GOOGLE_SERVICE_ACCOUNT_EMAIL']
|
124
124
|
google_service_account_private_key ENV['GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY']
|
125
125
|
google_project ENV['GOOGLE_PROJECT']
|
126
|
+
# Terraform credentials information
|
127
|
+
# Valid driver names: :tfe, :boule, :local
|
128
|
+
terraform_driver :local
|
129
|
+
terraform_tfe_endpoint ENV['TFE_URL']
|
130
|
+
terraform_tfe_token ENV['TFE_TOKEN']
|
131
|
+
terraform_boule_endpoint ENV['BOULE_URL']
|
132
|
+
terraform_local_directory './terraform-stacks'
|
133
|
+
terraform_local_scrub_destroyed false
|
126
134
|
end
|
127
135
|
end
|
128
136
|
EOF
|
data/lib/sfn/command/destroy.rb
CHANGED
@@ -30,8 +30,14 @@ module Sfn
|
|
30
30
|
stack = provider.connection.stacks.get(stack_name)
|
31
31
|
if(stack)
|
32
32
|
nested_stack_cleanup!(stack)
|
33
|
-
|
34
|
-
stack
|
33
|
+
begin
|
34
|
+
api_action!(:api_stack => stack) do
|
35
|
+
stack.destroy
|
36
|
+
end
|
37
|
+
rescue Miasma::Error::ApiError::RequestError => error
|
38
|
+
raise unless error.response.code == 404
|
39
|
+
# if stack is already gone, disable polling
|
40
|
+
config[:poll] = false
|
35
41
|
end
|
36
42
|
ui.info "Destroy request complete for stack: #{ui.color(stack_name, :red)}"
|
37
43
|
else
|
data/lib/sfn/command/graph.rb
CHANGED
@@ -21,9 +21,7 @@ module Sfn
|
|
21
21
|
config[:print_only] = true
|
22
22
|
validate_graph_style!
|
23
23
|
file = load_template_file
|
24
|
-
file = parameter_scrub!(file.sparkle_dump)
|
25
24
|
@outputs = Smash.new
|
26
|
-
file = file.to_smash
|
27
25
|
ui.info "Template resource graph generation - Style: #{ui.color(config[:graph_style], :bold)}"
|
28
26
|
if(config[:file])
|
29
27
|
ui.puts " -> path: #{config[:file]}"
|
@@ -38,14 +36,14 @@ module Sfn
|
|
38
36
|
end
|
39
37
|
graph = nil
|
40
38
|
run_action 'Generating resource graph' do
|
41
|
-
graph = generate_graph(file
|
39
|
+
graph = generate_graph(file)
|
42
40
|
nil
|
43
41
|
end
|
44
42
|
run_action 'Writing graph result' do
|
45
43
|
FileUtils.mkdir_p(File.dirname(config[:output_file]))
|
46
44
|
if(config[:output_type] == 'dot')
|
47
|
-
File.open("#{config[:output_file]}.dot", 'w') do |
|
48
|
-
|
45
|
+
File.open("#{config[:output_file]}.dot", 'w') do |o_file|
|
46
|
+
o_file.puts graph.to_s
|
49
47
|
end
|
50
48
|
else
|
51
49
|
graph.save config[:output_file], config[:output_type]
|
@@ -74,10 +72,11 @@ module Sfn
|
|
74
72
|
end
|
75
73
|
|
76
74
|
def output_discovery(template, outputs, resource_name, parent_template, name='')
|
77
|
-
|
78
|
-
template
|
79
|
-
|
80
|
-
|
75
|
+
unless(template.resources.nil?)
|
76
|
+
template.resources.keys!.each do |r_name|
|
77
|
+
r_info = template.resources[r_name]
|
78
|
+
if(r_info.type == template._self.stack_resource_name)
|
79
|
+
output_discovery(r_info.properties.stack, outputs, r_name, template, r_name)
|
81
80
|
end
|
82
81
|
end
|
83
82
|
end
|
data/lib/sfn/command/update.rb
CHANGED
@@ -16,6 +16,8 @@ module Sfn
|
|
16
16
|
TEMPLATE_PARAMETER_DEFAULTS = ['Default', 'defaultValue', 'default']
|
17
17
|
# Template parameter no echo locations
|
18
18
|
TEMPLATE_PARAMETER_NOECHO = ['NoEcho']
|
19
|
+
# Template parameter no echo custom
|
20
|
+
TEMPLATE_PARAMETER_SFN_NOECHO = ['Quiet', 'quiet']
|
19
21
|
|
20
22
|
# Apply any defined remote stacks
|
21
23
|
#
|
@@ -143,16 +145,19 @@ module Sfn
|
|
143
145
|
# @param parameter_prefix [Array<String>] nesting prefix names
|
144
146
|
# @param parameter_name [String] parameter name
|
145
147
|
# @return [Array<String>] [expected_template_key, configuration_used_key]
|
146
|
-
def locate_config_parameter_key(parameter_prefix, parameter_name)
|
148
|
+
def locate_config_parameter_key(parameter_prefix, parameter_name, root_name)
|
147
149
|
check_name = parameter_name.downcase.tr('-_', '')
|
148
150
|
check_prefix = parameter_prefix.map{|i| i.downcase.tr('-_', '') }
|
149
151
|
key_match = config[:parameters].keys.detect do |cp_key|
|
150
152
|
cp_key = cp_key.to_s.downcase.split('__').map{|i| i.tr('-_', '') }.join('__')
|
151
|
-
|
152
|
-
|
153
|
+
non_root_matcher = (check_prefix + [check_name]).join('__')
|
154
|
+
root_matcher = ([root_name] + check_prefix + [check_name]).join('__')
|
155
|
+
cp_key == non_root_matcher ||
|
156
|
+
cp_key == root_matcher
|
153
157
|
end
|
154
158
|
actual_key = (parameter_prefix + [parameter_name]).compact.join('__')
|
155
159
|
if(key_match)
|
160
|
+
ui.debug "Remapping configuration runtime parameter `#{key_match}` -> `#{actual_key}`"
|
156
161
|
config[:parameters][actual_key] = config[:parameters].delete(key_match)
|
157
162
|
end
|
158
163
|
actual_key
|
@@ -186,12 +191,19 @@ module Sfn
|
|
186
191
|
)
|
187
192
|
)
|
188
193
|
if(config[:interactive_parameters])
|
194
|
+
no_echo = !!TEMPLATE_PARAMETER_NOECHO.detect{|loc_key|
|
195
|
+
param_value[loc_key].to_s.downcase == 'true'
|
196
|
+
}
|
197
|
+
sfn_no_echo = TEMPLATE_PARAMETER_SFN_NOECHO.map do |loc_key|
|
198
|
+
res = param_value.delete(loc_key).to_s.downcase
|
199
|
+
res if !res.empty? && res != 'false'
|
200
|
+
end.compact.first
|
201
|
+
no_echo = sfn_no_echo if sfn_no_echo
|
189
202
|
answer = ui.ask_question(
|
190
203
|
"#{param_name.split(/([A-Z]+[^A-Z]*)/).find_all{|s|!s.empty?}.join(' ')}",
|
191
204
|
:default => default,
|
192
|
-
:
|
193
|
-
|
194
|
-
}
|
205
|
+
:hide_default => sfn_no_echo == 'all',
|
206
|
+
:no_echo => !!no_echo
|
195
207
|
)
|
196
208
|
else
|
197
209
|
answer = default
|
@@ -221,21 +233,25 @@ module Sfn
|
|
221
233
|
# @option opts [Miasma::Models::Orchestration::Stack] :stack existing stack
|
222
234
|
# @return [Hash]
|
223
235
|
def populate_parameters!(sparkle, opts={})
|
224
|
-
current_parameters = opts
|
236
|
+
current_parameters = opts[:current_parameters] || {}
|
225
237
|
current_stack = opts[:stack]
|
226
238
|
parameter_prefix, stack_parameters = prefix_parameters_setup(sparkle)
|
227
239
|
unless(stack_parameters.empty?)
|
228
240
|
format_config_parameters!
|
229
241
|
param_banner = false
|
230
242
|
stack_parameters.each do |param_name, param_value|
|
231
|
-
ns_key = locate_config_parameter_key(parameter_prefix, param_name)
|
243
|
+
ns_key = locate_config_parameter_key(parameter_prefix, param_name, sparkle.root.name)
|
232
244
|
# When parameter is a hash type, it is being set via
|
233
245
|
# intrinsic function and we don't modify
|
234
246
|
if(function_set_parameter?(current_parameters[param_name]))
|
235
|
-
if(
|
236
|
-
|
247
|
+
if(!config[:parameters][ns_key].nil?)
|
248
|
+
ui.warn "Overriding mapped parameter value with explicit assignment `#{ns_key}`!"
|
237
249
|
else
|
238
|
-
|
250
|
+
if(current_stack)
|
251
|
+
enable_set = validate_stack_parameter(current_stack, param_name, ns_key, current_parameters[param_name])
|
252
|
+
else
|
253
|
+
enable_set = true
|
254
|
+
end
|
239
255
|
end
|
240
256
|
if(enable_set)
|
241
257
|
# NOTE: direct set dumps the stack (nfi). Smash will
|
@@ -180,13 +180,30 @@ module Sfn
|
|
180
180
|
else
|
181
181
|
current_state = compile_state.fetch(f_name, Smash.new)
|
182
182
|
end
|
183
|
+
|
184
|
+
# NOTE: Prevent nesting stack compile state within stack compile state
|
185
|
+
current_state.delete("#{f_name}__#{f_name}")
|
186
|
+
|
183
187
|
if(formation.compile_state)
|
184
188
|
current_state = current_state.merge(formation.compile_state)
|
185
189
|
end
|
186
190
|
unless(formation.parameters.empty?)
|
187
191
|
ui.info "#{ui.color('Compile time parameters:', :bold)} - template: #{ui.color(pathed_name, :green, :bold)}" unless config[:print_only]
|
188
192
|
formation.parameters.each do |k,v|
|
189
|
-
|
193
|
+
valid_keys = [
|
194
|
+
"#{f_name}__#{k}",
|
195
|
+
Bogo::Utility.camel("#{f_name}__#{k}").downcase,
|
196
|
+
k,
|
197
|
+
Bogo::Utility.camel(k).downcase
|
198
|
+
]
|
199
|
+
current_value = valid_keys.map do |key|
|
200
|
+
current_state[key]
|
201
|
+
end.compact.first
|
202
|
+
primary_key, secondary_key = ["#{f_name}__#{k}", k]
|
203
|
+
current_state[k] = request_compile_parameter(k, v,
|
204
|
+
current_value,
|
205
|
+
!!formation.parent
|
206
|
+
)
|
190
207
|
end
|
191
208
|
formation.compile_state = current_state
|
192
209
|
end
|
@@ -231,19 +248,19 @@ module Sfn
|
|
231
248
|
# core parameter set
|
232
249
|
def merge_compile_time_parameters
|
233
250
|
compile_state = config.fetch(:compile_parameters, Smash.new)
|
251
|
+
ui.debug "Initial compile parameters - #{compile_state}"
|
234
252
|
compile_state.keys.each do |cs_key|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
253
|
+
unless(cs_key.to_s.start_with?("#{arguments.first}__"))
|
254
|
+
named_cs_key = "#{arguments.first}__#{cs_key}"
|
255
|
+
non_named = compile_state.delete(cs_key)
|
256
|
+
if(non_named && !compile_state.key?(named_cs_key))
|
257
|
+
ui.debug "Setting non-named compile parameter `#{cs_key}` into `#{named_cs_key}`"
|
258
|
+
compile_state[named_cs_key] = non_named
|
259
|
+
else
|
260
|
+
ui.debug "Discarding non-named compile parameter due to set named - `#{cs_key}` </> `#{named_cs_key}`"
|
239
261
|
end
|
240
262
|
end
|
241
263
|
end
|
242
|
-
compile_state.keys.each do |cs_key|
|
243
|
-
unless(cs_key.start_with?("#{arguments.first}__"))
|
244
|
-
compile_state["#{arguments.first}__#{cs_key}"] = compile_state.delete(cs_key)
|
245
|
-
end
|
246
|
-
end
|
247
264
|
ui.debug "Merged compile parameters - #{compile_state}"
|
248
265
|
compile_state
|
249
266
|
end
|
data/lib/sfn/config/validate.rb
CHANGED
@@ -82,13 +82,22 @@ module Sfn
|
|
82
82
|
result = Smash.new
|
83
83
|
v.split(',').each do |item_pair|
|
84
84
|
key, value = item_pair.split(/[=:]/, 2)
|
85
|
-
key =
|
86
|
-
key = [key.pop, key.join('__')].reverse
|
87
|
-
result.set(*key, value)
|
85
|
+
result[key] = value
|
88
86
|
end
|
89
87
|
result
|
90
88
|
when Hash
|
91
|
-
|
89
|
+
result = Smash.new
|
90
|
+
extractor = lambda do |data, prefix|
|
91
|
+
data.each_pair do |key, value|
|
92
|
+
local_key = "#{prefix}__#{key}"
|
93
|
+
if(value.is_a?(Hash))
|
94
|
+
extractor.call(value, local_key)
|
95
|
+
else
|
96
|
+
result[local_key] = data
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
result
|
92
101
|
else
|
93
102
|
v
|
94
103
|
end
|
data/lib/sfn/planner/aws.rb
CHANGED
@@ -14,6 +14,8 @@ module Sfn
|
|
14
14
|
REF_MAPPING = {}
|
15
15
|
FN_MAPPING = {}
|
16
16
|
|
17
|
+
UNKNOWN_RUNTIME_RESULT = '__UNKNOWN_RUNTIME_RESULT__'
|
18
|
+
|
17
19
|
# @return [Array<String>] flagged items for value replacement
|
18
20
|
attr_reader :flagged
|
19
21
|
|
@@ -23,6 +25,11 @@ module Sfn
|
|
23
25
|
@flagged = []
|
24
26
|
end
|
25
27
|
|
28
|
+
# @return [Hash] defined conditions
|
29
|
+
def conditions
|
30
|
+
@original.fetch('Conditions', {})
|
31
|
+
end
|
32
|
+
|
26
33
|
# Flag a reference as modified
|
27
34
|
#
|
28
35
|
# @param ref_name [String]
|
@@ -48,30 +55,25 @@ module Sfn
|
|
48
55
|
# @note also allows 'Ref' within funcs to provide mapping
|
49
56
|
# replacements using the REF_MAPPING constant
|
50
57
|
def apply_function(hash, funcs=[])
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
if(hash.is_a?(Hash))
|
59
|
+
k,v = hash.first
|
60
|
+
if(hash.size == 1 && (k.start_with?('Fn') || k == 'Ref') && (funcs.include?(:all) || funcs.empty? || funcs.include?(k) || funcs == ['DEREF']))
|
61
|
+
method_name = Bogo::Utility.snake(k.gsub('::', ''))
|
62
|
+
if((funcs.include?(k) || funcs.include?(:all)) && respond_to?(method_name))
|
63
|
+
apply_function(send(method_name, v), funcs)
|
64
|
+
else
|
65
|
+
case k
|
66
|
+
when 'Fn::GetAtt'
|
67
|
+
funcs.include?('DEREF') ? dereference(hash) : hash
|
68
|
+
when 'Ref'
|
69
|
+
if(funcs.include?('DEREF'))
|
70
|
+
dereference(hash)
|
71
|
+
else
|
72
|
+
{'Ref' => self.class.const_get(:REF_MAPPING).fetch(v, v)}
|
73
|
+
end
|
62
74
|
else
|
63
|
-
|
75
|
+
hash
|
64
76
|
end
|
65
|
-
else
|
66
|
-
raise "Failed to find mapping! (#{v[0]})"
|
67
|
-
end
|
68
|
-
when 'Fn::GetAtt'
|
69
|
-
func.include?('DEREF') ? dereference(hash) : hash
|
70
|
-
when 'Ref'
|
71
|
-
if(funcs.include?('DEREF'))
|
72
|
-
dereference(hash)
|
73
|
-
else
|
74
|
-
{'Ref' => self.class.const_get(:REF_MAPPING).fetch(v, v)}
|
75
77
|
end
|
76
78
|
else
|
77
79
|
hash
|
@@ -81,6 +83,113 @@ module Sfn
|
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
86
|
+
# Evaluate given condition
|
87
|
+
#
|
88
|
+
# @param name [String] condition name
|
89
|
+
# @return [TrueClass, FalseClass]
|
90
|
+
def apply_condition(name)
|
91
|
+
condition = conditions[name]
|
92
|
+
if(condition)
|
93
|
+
apply_function(condition, [:all, 'DEREF'])
|
94
|
+
else
|
95
|
+
raise "Failed to locate condition with name `#{name}`!"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Evaluate `if` conditional
|
100
|
+
#
|
101
|
+
# @param value [Array] {0: condition name, 1: true value, 2: false value}
|
102
|
+
# @return [Object] true or false value
|
103
|
+
def fn_if(value)
|
104
|
+
result = apply_condition(value[0])
|
105
|
+
if(result != UNKNOWN_RUNTIME_RESULT)
|
106
|
+
result ? value[1] : value[2]
|
107
|
+
else
|
108
|
+
UNKNOWN_RUNTIME_RESULT
|
109
|
+
result
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Determine if all conditions are true
|
114
|
+
#
|
115
|
+
# @param value [Array<String>] condition names
|
116
|
+
# @return [TrueClass, FalseClass]
|
117
|
+
def fn_and(value)
|
118
|
+
result = value.map do |val|
|
119
|
+
apply_condition(val)
|
120
|
+
end
|
121
|
+
if(result.to_s.include?(RUNTIME_MODIFIED))
|
122
|
+
UNKNOWN_RUNTIME_RESULT
|
123
|
+
else
|
124
|
+
result.all?
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Determine if any values are true
|
129
|
+
#
|
130
|
+
# @param value [Array<String>] condition names
|
131
|
+
# @return [TrueClass, FalseClass]
|
132
|
+
def fn_or(value)
|
133
|
+
result = value.map do |val|
|
134
|
+
apply_condition(val)
|
135
|
+
end
|
136
|
+
if(result.to_s.include?(RUNTIME_MODIFIED))
|
137
|
+
UNKNOWN_RUNTIME_RESULT
|
138
|
+
else
|
139
|
+
result.any?
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Negate given value
|
144
|
+
#
|
145
|
+
# @param value [Array<Hash>]
|
146
|
+
# @return [TrueClass, FalseClass]
|
147
|
+
def fn_not(value)
|
148
|
+
result = apply_function(value)
|
149
|
+
result == RUNTIME_MODIFIED ? UNKNOWN_RUNTIME_RESULT : !result
|
150
|
+
end
|
151
|
+
|
152
|
+
# Determine if values are equal
|
153
|
+
#
|
154
|
+
# @param value [Array] values
|
155
|
+
# @return [TrueClass, FalseClass]
|
156
|
+
def fn_equals(value)
|
157
|
+
value = value.map do |val|
|
158
|
+
apply_function(val)
|
159
|
+
end
|
160
|
+
if(value.to_s.include?(RUNTIME_MODIFIED))
|
161
|
+
UNKNOWN_RUNTIME_RESULT
|
162
|
+
else
|
163
|
+
value.first == value.last
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Join values with given delimiter
|
168
|
+
#
|
169
|
+
# @param value [Array<String,Array<String>>]
|
170
|
+
# @return [String]
|
171
|
+
def fn_join(value)
|
172
|
+
value.last.join(value.first)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Lookup value in mappings
|
176
|
+
#
|
177
|
+
# @param value [Array]
|
178
|
+
# @return [String, Fixnum]
|
179
|
+
def fn_find_in_map(value)
|
180
|
+
map_holder = mappings[value[0]]
|
181
|
+
if(map_holder)
|
182
|
+
map_item = map_holder[dereference(value[1])]
|
183
|
+
if(map_item)
|
184
|
+
map_item[value[2]]
|
185
|
+
else
|
186
|
+
raise "Failed to find mapping item! (#{value[0]} -> #{value[1]})"
|
187
|
+
end
|
188
|
+
else
|
189
|
+
raise "Failed to find mapping! (#{value[0]})"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
84
193
|
# Override the parent dereference behavior to return junk
|
85
194
|
# value on flagged resource match
|
86
195
|
#
|
@@ -416,15 +525,19 @@ module Sfn
|
|
416
525
|
]
|
417
526
|
)
|
418
527
|
begin
|
419
|
-
|
420
|
-
|
421
|
-
if(r_property)
|
422
|
-
effect = r_property.update_causes(
|
423
|
-
templates.get(:update, 'Resources', resource_name),
|
424
|
-
templates.get(:origin, 'Resources', resource_name)
|
425
|
-
)
|
528
|
+
if(templates.get(:update, 'Resources', resource_name, 'Properties', property_name) == Translator::UNKNOWN_RUNTIME_RESULT)
|
529
|
+
effect = :unknown
|
426
530
|
else
|
427
|
-
|
531
|
+
r_info = SparkleFormation::Resources::Aws.resource_lookup(type)
|
532
|
+
r_property = r_info.property(property_name)
|
533
|
+
if(r_property)
|
534
|
+
effect = r_property.update_causes(
|
535
|
+
templates.get(:update, 'Resources', resource_name),
|
536
|
+
templates.get(:origin, 'Resources', resource_name)
|
537
|
+
)
|
538
|
+
else
|
539
|
+
raise KeyError.new 'Unknown property'
|
540
|
+
end
|
428
541
|
end
|
429
542
|
case effect.to_sym
|
430
543
|
when :replacement
|
@@ -507,19 +620,30 @@ module Sfn
|
|
507
620
|
template.keys.each do |t_key|
|
508
621
|
next if ['Outputs', 'Resources'].include?(t_key)
|
509
622
|
template[t_key] = translator.dereference_processor(
|
510
|
-
template[t_key], ['
|
623
|
+
template[t_key], ['DEREF']
|
511
624
|
)
|
512
625
|
end
|
513
626
|
translator.original.replace(template)
|
514
|
-
|
515
|
-
template[
|
516
|
-
template[
|
517
|
-
|
627
|
+
['Outputs', 'Resources'].each do |t_key|
|
628
|
+
if(template[t_key])
|
629
|
+
template[t_key] = translator.dereference_processor(
|
630
|
+
template[t_key], ['DEREF', :all]
|
631
|
+
)
|
632
|
+
end
|
518
633
|
end
|
519
|
-
if(template['
|
520
|
-
template['
|
521
|
-
|
522
|
-
|
634
|
+
if(template['Resources'])
|
635
|
+
valid_resources = template['Resources'].map do |resource_name, resource_value|
|
636
|
+
if(resource_value['OnCondition'])
|
637
|
+
if(translator.apply_condition(resource_value['OnCondition']))
|
638
|
+
resource_name
|
639
|
+
end
|
640
|
+
else
|
641
|
+
resource_name
|
642
|
+
end
|
643
|
+
end.compact
|
644
|
+
(template['Resources'].keys - valid_resources).each do |resource_to_remove|
|
645
|
+
template['Resources'].delete(resource_to_remove)
|
646
|
+
end
|
523
647
|
end
|
524
648
|
translator.original.replace({})
|
525
649
|
template
|
data/lib/sfn/provider.rb
CHANGED
@@ -78,7 +78,7 @@ module Sfn
|
|
78
78
|
)
|
79
79
|
@cache = args.fetch(:cache, Cache.new(:local))
|
80
80
|
@async = args.fetch(:async, true)
|
81
|
-
@
|
81
|
+
@miasma_args = args[:miasma].dup
|
82
82
|
cache.init(:stacks_lock, :lock, :timeout => 0.1)
|
83
83
|
cache.init(:stacks, :stamped)
|
84
84
|
cache.init(:stack_expansion_lock, :lock, :timeout => 0.1)
|
data/lib/sfn/version.rb
CHANGED
data/sfn.gemspec
CHANGED
@@ -11,20 +11,23 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.license = 'Apache-2.0'
|
12
12
|
s.require_path = 'lib'
|
13
13
|
s.add_runtime_dependency 'bogo-cli', '>= 0.2.5', '< 0.4'
|
14
|
-
s.add_runtime_dependency 'bogo-ui', '>= 0.1.
|
14
|
+
s.add_runtime_dependency 'bogo-ui', '>= 0.1.22', '< 0.4'
|
15
15
|
s.add_runtime_dependency 'miasma', '>= 0.3.0', '< 0.4'
|
16
16
|
s.add_runtime_dependency 'miasma-aws', '>= 0.3.6', '< 0.4'
|
17
17
|
s.add_runtime_dependency 'miasma-azure', '>= 0.1.0', '< 0.3'
|
18
18
|
s.add_runtime_dependency 'miasma-open-stack', '>= 0.1.0', '< 0.3'
|
19
19
|
s.add_runtime_dependency 'miasma-rackspace', '>= 0.1.0', '< 0.3'
|
20
20
|
s.add_runtime_dependency 'miasma-google', '>= 0.1.0', '< 0.3'
|
21
|
+
s.add_runtime_dependency 'miasma-terraform', '>= 0.1.0', '< 0.2.0'
|
21
22
|
s.add_runtime_dependency 'jmespath'
|
22
23
|
s.add_runtime_dependency 'net-ssh'
|
23
|
-
s.add_runtime_dependency 'sparkle_formation', '>= 3.0.
|
24
|
+
s.add_runtime_dependency 'sparkle_formation', '>= 3.0.11', '< 4'
|
24
25
|
s.add_runtime_dependency 'hashdiff', '~> 0.2.2'
|
25
26
|
s.add_runtime_dependency 'graph', '~> 2.8.1'
|
26
27
|
s.add_development_dependency 'rake', '~> 10'
|
27
28
|
s.add_development_dependency 'minitest'
|
29
|
+
s.add_development_dependency 'rspec', '~> 3.5'
|
30
|
+
s.add_development_dependency 'rubocop', '0.38.0'
|
28
31
|
s.add_development_dependency 'mocha'
|
29
32
|
s.add_development_dependency 'yard'
|
30
33
|
s.executables << 'sfn'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sfn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bogo-cli
|
@@ -36,7 +36,7 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.1.
|
39
|
+
version: 0.1.22
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '0.4'
|
@@ -46,7 +46,7 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 0.1.
|
49
|
+
version: 0.1.22
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '0.4'
|
@@ -170,6 +170,26 @@ dependencies:
|
|
170
170
|
- - "<"
|
171
171
|
- !ruby/object:Gem::Version
|
172
172
|
version: '0.3'
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: miasma-terraform
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: 0.1.0
|
180
|
+
- - "<"
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: 0.2.0
|
183
|
+
type: :runtime
|
184
|
+
prerelease: false
|
185
|
+
version_requirements: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: 0.1.0
|
190
|
+
- - "<"
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: 0.2.0
|
173
193
|
- !ruby/object:Gem::Dependency
|
174
194
|
name: jmespath
|
175
195
|
requirement: !ruby/object:Gem::Requirement
|
@@ -204,7 +224,7 @@ dependencies:
|
|
204
224
|
requirements:
|
205
225
|
- - ">="
|
206
226
|
- !ruby/object:Gem::Version
|
207
|
-
version: 3.0.
|
227
|
+
version: 3.0.11
|
208
228
|
- - "<"
|
209
229
|
- !ruby/object:Gem::Version
|
210
230
|
version: '4'
|
@@ -214,7 +234,7 @@ dependencies:
|
|
214
234
|
requirements:
|
215
235
|
- - ">="
|
216
236
|
- !ruby/object:Gem::Version
|
217
|
-
version: 3.0.
|
237
|
+
version: 3.0.11
|
218
238
|
- - "<"
|
219
239
|
- !ruby/object:Gem::Version
|
220
240
|
version: '4'
|
@@ -274,6 +294,34 @@ dependencies:
|
|
274
294
|
- - ">="
|
275
295
|
- !ruby/object:Gem::Version
|
276
296
|
version: '0'
|
297
|
+
- !ruby/object:Gem::Dependency
|
298
|
+
name: rspec
|
299
|
+
requirement: !ruby/object:Gem::Requirement
|
300
|
+
requirements:
|
301
|
+
- - "~>"
|
302
|
+
- !ruby/object:Gem::Version
|
303
|
+
version: '3.5'
|
304
|
+
type: :development
|
305
|
+
prerelease: false
|
306
|
+
version_requirements: !ruby/object:Gem::Requirement
|
307
|
+
requirements:
|
308
|
+
- - "~>"
|
309
|
+
- !ruby/object:Gem::Version
|
310
|
+
version: '3.5'
|
311
|
+
- !ruby/object:Gem::Dependency
|
312
|
+
name: rubocop
|
313
|
+
requirement: !ruby/object:Gem::Requirement
|
314
|
+
requirements:
|
315
|
+
- - '='
|
316
|
+
- !ruby/object:Gem::Version
|
317
|
+
version: 0.38.0
|
318
|
+
type: :development
|
319
|
+
prerelease: false
|
320
|
+
version_requirements: !ruby/object:Gem::Requirement
|
321
|
+
requirements:
|
322
|
+
- - '='
|
323
|
+
- !ruby/object:Gem::Version
|
324
|
+
version: 0.38.0
|
277
325
|
- !ruby/object:Gem::Dependency
|
278
326
|
name: mocha
|
279
327
|
requirement: !ruby/object:Gem::Requirement
|
@@ -346,6 +394,7 @@ files:
|
|
346
394
|
- lib/sfn.rb
|
347
395
|
- lib/sfn/api_provider.rb
|
348
396
|
- lib/sfn/api_provider/google.rb
|
397
|
+
- lib/sfn/api_provider/terraform.rb
|
349
398
|
- lib/sfn/cache.rb
|
350
399
|
- lib/sfn/callback.rb
|
351
400
|
- lib/sfn/callback/aws_assume_role.rb
|
@@ -435,7 +484,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
435
484
|
version: '0'
|
436
485
|
requirements: []
|
437
486
|
rubyforge_project:
|
438
|
-
rubygems_version: 2.
|
487
|
+
rubygems_version: 2.4.8
|
439
488
|
signing_key:
|
440
489
|
specification_version: 4
|
441
490
|
summary: SparkleFormation CLI
|