sfn 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -61,109 +61,4 @@ can be accessed via:
61
61
  $ knife sparkleformation --help
62
62
  ~~~
63
63
 
64
- ### Configuration Options
65
-
66
- | Option | Attribute | Value
67
- |----------------------------|---------------|---------------------------------------------------------------
68
- | `processing` | Description | Enable SparkleFormation processing
69
- | | Valid | `TrueClass`, `FalseClass`
70
- | | Default | `true`
71
- |----------------------------|---------------|---------------------------------------------------------------
72
- | `apply_nesting` | Description | Style of nested stack processing
73
- | | Valid | `"shallow"`, `"deep"`
74
- | | Default | `"deep"`
75
- |----------------------------|---------------|---------------------------------------------------------------
76
- | `options` | Description | API options for target API (see miasma)
77
- | | Valid | `Hash`
78
- | | Default | none
79
- |----------------------------|---------------|---------------------------------------------------------------
80
- | `merge_api_options` | Description | Merges API options on stack update
81
- | | Valid | `TrueClass`, `FalseClass`
82
- | | Default | `false`
83
- |----------------------------|---------------|---------------------------------------------------------------
84
- | `ssh_attempt_users` | Description | List of users to attempt SSH connection on node failure
85
- | | Valid | `Array<String>`
86
- | | Default | none
87
- |----------------------------|---------------|---------------------------------------------------------------
88
- | `identity_file` | Description | Custom SSH identity file for node failure connection
89
- | | Valid | `String`
90
- | | Default | none
91
- |----------------------------|---------------|---------------------------------------------------------------
92
- | `nesting_bucket` | Description | Name of bucket to store nested stack templates
93
- | | Valid | `String`
94
- | | Default | none
95
- |----------------------------|---------------|---------------------------------------------------------------
96
- | `nesting_prefix` | Description | Prefix to prepend to template file name within object store
97
- | | Valid | `String`
98
- | | Default | none
99
- |----------------------------|---------------|---------------------------------------------------------------
100
- | `sparkle_pack` | Description | SparklePacks to load
101
- | | Valid | `Array<String>`
102
- | | Default | none
103
- |----------------------------|---------------|---------------------------------------------------------------
104
- | `parameters` | Description | Stack runtime parameters
105
- | | Valid | `Hash`
106
- | | Default | none
107
- |----------------------------|---------------|---------------------------------------------------------------
108
- | `credentials` | Description | API credentials for target orchestration API
109
- | | Valid | `Hash`
110
- | | Default | none
111
- |----------------------------|---------------|---------------------------------------------------------------
112
- | `callbacks` | Description | Callbacks to execute around API calls
113
- | | Valid | `Hash`
114
- | | Default | none
115
- |----------------------------|---------------|---------------------------------------------------------------
116
- | `callbacks.before` | Description | Callbacks to execute before _any_ API call
117
- | | Valid | `Array<String>`
118
- | | Default | none
119
- |----------------------------|---------------|---------------------------------------------------------------
120
- | `callbacks.after` | Description | Callbacks to execute after _any_ API call
121
- | | Valid | `Array<String>`
122
- | | Default | none
123
- |----------------------------|---------------|---------------------------------------------------------------
124
- | `callbacks.before_COMMAND` | Description | Callbacks to execute before specific `COMMAND` API call
125
- | | Valid | `Array<String>`
126
- | | Default | none
127
- |----------------------------|---------------|---------------------------------------------------------------
128
- | `callbacks.after_COMMAND` | Description | Callbacks to execute after specific `COMMAND` API call
129
- | | Valid | `Array<String>`
130
- | | Default | none
131
- |----------------------------|---------------|---------------------------------------------------------------
132
- | `callbacks.template` | Description | Callbacks to execute on template
133
- | | Valid | `Array<String>`
134
- | | Default | none
135
- |----------------------------|---------------|---------------------------------------------------------------
136
- | `callbacks.default` | Description | Callbacks to always execute
137
- | | Valid | `Array<String>`
138
- | | Default | none
139
- |----------------------------|---------------|---------------------------------------------------------------
140
- | `callbacks.require` | Description | List of custom libraries to load
141
- | | Valid | `Array<String>`
142
- | | Default | none
143
- |----------------------------|---------------|---------------------------------------------------------------
144
- | `retries` | Description | Configuration of API request retries
145
- | | Valid | `Hash`
146
- | | Default | none
147
- |----------------------------|---------------|---------------------------------------------------------------
148
- | `retries.type` | Description | Retry implementation
149
- | | Valid | `"flat"`, `"linear"`, `"exponential"`
150
- | | Default | `"exponential"`
151
- |----------------------------|---------------|---------------------------------------------------------------
152
- | `retries.interval` | Description | Base wait interval for retry
153
- | | Valid | `Numeric`
154
- | | Default | `5`
155
- |----------------------------|---------------|---------------------------------------------------------------
156
- | `retries.max_attempts` | Description | Maximum number of attempts allowed (`nil` for infinite retry)
157
- | | Valid | `Numeric`, `NilClass`
158
- | | Default | `20`
159
- |----------------------------|---------------|---------------------------------------------------------------
160
- | `stack_types` | Description | Define customized stack resource types
161
- | | Valid | `Array<String>`
162
- | | Default | `[DEFAULT_PROVIDER_TYPE]`
163
- |----------------------------|---------------|---------------------------------------------------------------
164
- | `locations` | Description | API credentials for named locations (JackalStack resources)
165
- | | Valid | `Hash`
166
- | | Default | none
167
- |----------------------------|---------------|---------------------------------------------------------------
168
-
169
64
  [knife]: https://docs.chef.io/knife.html
@@ -22,6 +22,7 @@ Notable features available via the SparkleFormation CLI:
22
22
  - Eucalyptus
23
23
  - Rackspace Orchestration
24
24
  - OpenStack Heat
25
+ - Google Cloud Deployment Manager
25
26
  - Chef `knife` plugin support
26
27
  - Deep resource inspection
27
28
 
data/lib/sfn.rb CHANGED
@@ -5,6 +5,7 @@ require 'sparkle_formation'
5
5
 
6
6
  module Sfn
7
7
 
8
+ autoload :ApiProvider, 'sfn/api_provider'
8
9
  autoload :Callback, 'sfn/callback'
9
10
  autoload :Provider, 'sfn/provider'
10
11
  autoload :Cache, 'sfn/cache'
@@ -0,0 +1,9 @@
1
+ require 'sfn'
2
+
3
+ module Sfn
4
+ module ApiProvider
5
+
6
+ autoload :Google, 'sfn/api_provider/google'
7
+
8
+ end
9
+ end
@@ -0,0 +1,84 @@
1
+ require 'sfn'
2
+
3
+ module Sfn
4
+ module ApiProvider
5
+
6
+ module Google
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?('$(') || val.start_with?('{{')
48
+ end
49
+ end
50
+
51
+ # Set parameters into parent resource properites
52
+ def populate_parameters!(template, opts={})
53
+ result = super
54
+ result.each_pair do |key, value|
55
+ if(template.parent)
56
+ template.parent.compile.resources.set!(template.name).properties.set!(key, value)
57
+ else
58
+ template.compile.resources.set!(template.name).properties.set!(key, value)
59
+ end
60
+ end
61
+ {}
62
+ end
63
+
64
+ # Override requirement of nesting bucket
65
+ def validate_nesting_bucket!
66
+ true
67
+ end
68
+
69
+ # Override template content extraction to disable scrub behavior
70
+ #
71
+ # @param thing [SparkleFormation, Hash]
72
+ # @return [Hash]
73
+ def template_content(thing, *_)
74
+ if(thing.is_a?(SparkleFormation))
75
+ config[:sparkle_dump] ? thing.sparkle_dump : thing.dump
76
+ else
77
+ thing
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -45,6 +45,7 @@ module Sfn
45
45
  ENV['DEBUG'] = 'true' if cli_opts[:debug]
46
46
  end
47
47
  super(cli_opts, args)
48
+ load_api_provider_extensions!
48
49
  run_callbacks_for(:after_config)
49
50
  run_callbacks_for("after_config_#{Bogo::Utility.snake(self.class.name.split('::').last)}")
50
51
  end
@@ -58,6 +59,27 @@ module Sfn
58
59
 
59
60
  protected
60
61
 
62
+ # Load API provider specific overrides to customize behavior
63
+ #
64
+ # @return [TrueClass, FalseClass]
65
+ def load_api_provider_extensions!
66
+ if(config.get(:credentials, :provider))
67
+ base_ext = Bogo::Utility.camel(config.get(:credentials, :provider))
68
+ targ_ext = self.class.name.split('::').last
69
+ if(ApiProvider.const_defined?(base_ext))
70
+ base_module = ApiProvider.const_get(base_ext)
71
+ ui.debug "Loading core provider extensions via `#{base_module}`"
72
+ extend base_module
73
+ if(base_module.const_defined?(targ_ext))
74
+ targ_module = base_module.const_get(targ_ext)
75
+ ui.debug "Loading targeted provider extensions via `#{targ_module}`"
76
+ extend targ_module
77
+ end
78
+ true
79
+ end
80
+ end
81
+ end
82
+
61
83
  # Start with current working directory and traverse to root
62
84
  # looking for a `.sfn` configuration file
63
85
  #
@@ -22,7 +22,6 @@ module Sfn
22
22
  file = config[:template]
23
23
  else
24
24
  file = load_template_file
25
- nested_stacks_unpack = file.delete('sfn_nested_stack')
26
25
  end
27
26
 
28
27
  unless(config[:print_only])
@@ -34,66 +33,55 @@ module Sfn
34
33
  stack_info << " #{ui.color('Path:', :bold)} #{config[:file]}"
35
34
  end
36
35
 
37
- unless(config[:print_only])
36
+ if(config[:print_only])
37
+ ui.puts format_json(parameter_scrub!(template_content(file)))
38
+ return
39
+ else
38
40
  ui.info " -> #{stack_info}"
39
41
  end
40
42
 
41
- if(nested_stacks_unpack)
42
- unpack_nesting(name, file, :create)
43
- else
44
-
45
- if(config[:print_only] && !config[:apply_stacks])
46
- ui.puts _format_json(
47
- translate_template(
48
- Sfn::Utils::StackParameterScrubber.scrub!(file)
49
- )
50
- )
51
- return
52
- end
53
-
54
- stack = provider.connection.stacks.build(
55
- config.fetch(:options, Smash.new).dup.merge(
56
- :name => name,
57
- :template => file
58
- )
43
+ stack = provider.connection.stacks.build(
44
+ config.fetch(:options, Smash.new).dup.merge(
45
+ :name => name,
46
+ :template => template_content(file),
47
+ :parameters => Smash.new
59
48
  )
49
+ )
60
50
 
61
- apply_stacks!(stack)
62
- stack.template = Sfn::Utils::StackParameterScrubber.scrub!(scrub_template(stack.template))
51
+ apply_stacks!(stack)
52
+ populate_parameters!(file, :current_parameters => stack.parameters)
63
53
 
64
- if(config[:print_only])
65
- ui.puts _format_json(translate_template(stack.template))
66
- return
67
- end
68
-
69
- populate_parameters!(stack.template)
70
- stack.parameters = config_root_parameters
54
+ stack.parameters = config_root_parameters
71
55
 
72
- stack.template = translate_template(stack.template)
56
+ if(config[:upload_root_template])
57
+ upload_result = store_template(name, file, Smash.new)
58
+ stack.template_url = upload_result[:url]
59
+ else
60
+ stack.template = parameter_scrub!(template_content(file, :scrub))
61
+ end
73
62
 
74
- api_action!(:api_stack => stack) do
75
- stack.save
76
- if(config[:poll])
77
- poll_stack(stack.name)
78
- stack = provider.connection.stacks.get(name)
63
+ api_action!(:api_stack => stack) do
64
+ stack.save
65
+ if(config[:poll])
66
+ poll_stack(stack.name)
67
+ stack = provider.stack(name)
79
68
 
80
- if(stack.reload.state == :create_complete)
81
- ui.info "Stack create complete: #{ui.color('SUCCESS', :green)}"
82
- namespace.const_get(:Describe).new({:outputs => true}, [name]).execute!
83
- else
84
- ui.fatal "Create of new stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
85
- raise 'Stack did not reach a successful completion state.'
86
- end
69
+ if(stack.reload.state == :create_complete)
70
+ ui.info "Stack create complete: #{ui.color('SUCCESS', :green)}"
71
+ namespace.const_get(:Describe).new({:outputs => true}, [name]).execute!
87
72
  else
88
- ui.warn 'Stack state polling has been disabled.'
89
- ui.info "Stack creation initialized for #{ui.color(name, :green)}"
73
+ ui.fatal "Create of new stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
74
+ raise 'Stack did not reach a successful completion state.'
90
75
  end
76
+ else
77
+ ui.warn 'Stack state polling has been disabled.'
78
+ ui.info "Stack creation initialized for #{ui.color(name, :green)}"
91
79
  end
92
-
93
80
  end
94
81
 
95
82
  end
96
83
 
97
84
  end
85
+
98
86
  end
99
87
  end
@@ -73,7 +73,7 @@ module Sfn
73
73
  # @param stack [Miasma::Models::Orchestration::Stack]
74
74
  def outputs(stack)
75
75
  ui.info "Outputs for stack: #{ui.color(stack.name, :bold)}"
76
- unless(stack.outputs.empty?)
76
+ unless(stack.outputs.nil? || stack.outputs.empty?)
77
77
  stack.outputs.each do |output|
78
78
  key, value = output.key, output.value
79
79
  key = snake(key).to_s.split('_').map(&:capitalize).join(' ')
@@ -40,7 +40,13 @@ module Sfn
40
40
  end
41
41
  if(config[:poll])
42
42
  if(stacks.size == 1)
43
- poll_stack(stacks.first)
43
+ begin
44
+ poll_stack(stacks.first)
45
+ rescue Miasma::Error::ApiError::RequestError => error
46
+ unless(error.response.code == 404)
47
+ raise error
48
+ end
49
+ end
44
50
  else
45
51
  ui.error "Stack polling is not available when multiple stack deletion is requested!"
46
52
  end
@@ -17,7 +17,7 @@ module Sfn
17
17
  name = name_args.first
18
18
 
19
19
  begin
20
- stack = provider.connection.stacks.get(name)
20
+ stack = provider.stack(name)
21
21
  rescue Miasma::Error::ApiError::RequestError
22
22
  stack = nil
23
23
  end
@@ -25,9 +25,7 @@ module Sfn
25
25
  if(stack)
26
26
  config[:print_only] = true
27
27
  file = load_template_file
28
- file.delete('sfn_nested_stack')
29
- file = Sfn::Utils::StackParameterScrubber.scrub!(file)
30
- file = translate_template(file)
28
+ file = parameter_scrub!(file.dump)
31
29
 
32
30
  ui.info "#{ui.color('SparkleFormation:', :bold)} #{ui.color('diff', :blue)} - #{name}"
33
31
  ui.puts
@@ -39,10 +37,11 @@ module Sfn
39
37
  end
40
38
  end
41
39
 
40
+ # @todo needs updates for better provider compat
42
41
  def diff_stack(stack, file, parent_names=[])
43
42
  stack_template = stack.template
44
43
  nested_stacks = Hash[
45
- file['Resources'].find_all do |name, value|
44
+ file.fetch('Resources', file.fetch('resources', {})).find_all do |name, value|
46
45
  value.fetch('Properties', {})['Stack']
47
46
  end
48
47
  ]
@@ -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.delete('sfn_nested_stack')
25
- file = Sfn::Utils::StackParameterScrubber.scrub!(file)
26
- file = translate_template(file)
24
+ file = parameter_scrub!(file.sparkle_dump)
27
25
  @outputs = Smash.new
28
26
  file = file.to_smash
29
27
  ui.info "Template resource graph generation - Style: #{ui.color(config[:graph_style], :bold)}"
@@ -10,14 +10,13 @@ module Sfn
10
10
  include Sfn::CommandModule::Template
11
11
  include Sfn::CommandModule::Stack
12
12
 
13
+ # Print the requested template
13
14
  def execute!
14
15
  config[:print_only] = true
15
16
  file = load_template_file
16
- file.delete('sfn_nested_stack')
17
- file = Sfn::Utils::StackParameterScrubber.scrub!(file)
18
- file = translate_template(file)
19
17
 
20
- json_content = _format_json(file)
18
+ json_content = format_json(parameter_scrub!(template_content(file)))
19
+
21
20
  if(config[:write_to_file])
22
21
  unless(File.directory?(File.dirname(config[:write_to_file])))
23
22
  run_action 'Creating parent directory' do