knife-cloudformation 0.2.12 → 0.2.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23cf366cd18f3224855b2d3e09863a0695dbb7eb
4
- data.tar.gz: 2e0f8941b6131cdfcc5eadbcb9f50681b8d0119d
3
+ metadata.gz: b30587ee32086876e78507495f1b16ceff7313c0
4
+ data.tar.gz: 996465e857261b97b0e5c095793a77a8f95058f1
5
5
  SHA512:
6
- metadata.gz: e69f7ec1cab91bcf3805ac23771a9162e41bd3b52fe921992821af2bd256043e1edafd8c422a338c8a05966de2e743152d1c06a260e29d36401fa0aa52180f43
7
- data.tar.gz: 7c0de5e87fc4c5631037dc1a115dd3ca3dac39c89836e5664c9df5edfac2f92705b6a776c6f4a6d0178adf98699663f7145f28fb511f39f328969959efb4f7ea
6
+ metadata.gz: bcdf25a7f2ff0749235cf6069c3614e4e01a39464be4d403f64ef886f07c3e060d0930516a99ad24f59c9f6ea1b5971457d69dbfcdc845d016495dbee1e74489
7
+ data.tar.gz: d91141b3eecffb0a776090e52b88ced51fd87a9bf515763635e11cbdd0a307e4d19b595b2e948626a265bb0d5cbc4e4b2100f0bb60440632e0a37555a41e7974
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## v0.2.14
2
+ * Pass command configuration through when unpacking
3
+ * Force stack list reload prior to polling to prevent lookup errors
4
+ * Add glob support on name arguments provided for `destroy`
5
+ * Add unpacked stack support to `--apply-stack` flag
6
+ * Retry events polling when started from different command
7
+
1
8
  ## v0.2.12
2
9
  * Use template to provide logical parameter ordering on stack update
3
10
  * Only set parameters when not the default template value
@@ -71,7 +71,7 @@ class Chef
71
71
  file = Chef::Config[:knife][:cloudformation][:template]
72
72
  else
73
73
  file = load_template_file
74
- nested_stacks = file.delete('sfn_nested_stack')
74
+ nested_stacks_unpack = file.delete('sfn_nested_stack')
75
75
  end
76
76
  ui.info "#{ui.color('Cloud Formation:', :bold)} #{ui.color('create', :green)}"
77
77
  stack_info = "#{ui.color('Name:', :bold)} #{name}"
@@ -86,12 +86,7 @@ class Chef
86
86
  ui.info " -> #{stack_info}"
87
87
  end
88
88
 
89
- if(nested_stacks)
90
-
91
- if(config[:print_only])
92
- ui.info _format_json(translate_template(file))
93
- exit 0
94
- end
89
+ if(nested_stacks_unpack)
95
90
 
96
91
  unpack_nesting(name, file, :create)
97
92
 
@@ -109,7 +104,7 @@ class Chef
109
104
 
110
105
  if(config[:print_only])
111
106
  ui.info _format_json(translate_template(stack.template))
112
- exit 0
107
+ return
113
108
  end
114
109
 
115
110
  populate_parameters!(stack.template)
@@ -120,48 +115,31 @@ class Chef
120
115
 
121
116
  end
122
117
 
123
- if(Chef::Config[:knife][:cloudformation][:poll])
124
- poll_stack(stack.name)
125
- stack = provider.connection.stacks.get(name)
126
-
127
- if(stack.reload.success?)
128
- ui.info "Stack create complete: #{ui.color('SUCCESS', :green)}"
129
- knife_output = Chef::Knife::CloudformationDescribe.new
130
- knife_output.name_args.push(name)
131
- knife_output.config[:outputs] = true
132
- knife_output.run
133
- else
134
- ui.fatal "Create of new stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
135
- ui.info ""
136
- knife_inspect = Chef::Knife::CloudformationInspect.new
137
- knife_inspect.name_args.push(name)
138
- knife_inspect.config[:instance_failure] = true
139
- knife_inspect.run
140
- exit 1
141
- end
142
- else
143
- ui.warn 'Stack state polling has been disabled.'
144
- ui.info "Stack creation initialized for #{ui.color(name, :green)}"
145
- end
146
- end
147
-
148
- # Apply any defined remote stacks
149
- #
150
- # @param stack [Miasma::Models::Orchestration::Stack]
151
- # @return [Miasma::Models::Orchestration::Stack]
152
- def apply_stacks!(stack)
153
- remote_stacks = Chef::Config[:knife][:cloudformation].
154
- fetch(:create, {}).fetch(:apply_stacks, [])
155
- remote_stacks.each do |stack_name|
156
- remote_stack = provider.connection.stacks.get(stack_name)
157
- if(remote_stack)
158
- stack.apply_stack(remote_stack)
118
+ if(stack)
119
+ if(Chef::Config[:knife][:cloudformation][:poll])
120
+ poll_stack(stack.name)
121
+ stack = provider.connection.stacks.get(name)
122
+
123
+ if(stack.reload.success?)
124
+ ui.info "Stack create complete: #{ui.color('SUCCESS', :green)}"
125
+ knife_output = Chef::Knife::CloudformationDescribe.new
126
+ knife_output.name_args.push(name)
127
+ knife_output.config[:outputs] = true
128
+ knife_output.run
129
+ else
130
+ ui.fatal "Create of new stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
131
+ ui.info ""
132
+ knife_inspect = Chef::Knife::CloudformationInspect.new
133
+ knife_inspect.name_args.push(name)
134
+ knife_inspect.config[:instance_failure] = true
135
+ knife_inspect.run
136
+ exit 1
137
+ end
159
138
  else
160
- ui.error "Failed to apply requested stack. Unable to locate. (#{stack_name})"
161
- exit 1
139
+ ui.warn 'Stack state polling has been disabled.'
140
+ ui.info "Stack creation initialized for #{ui.color(name, :green)}"
162
141
  end
163
142
  end
164
- stack
165
143
  end
166
144
 
167
145
  end
@@ -21,6 +21,19 @@ class Chef
21
21
  def _run
22
22
  stacks = name_args.sort
23
23
  plural = 's' if stacks.size > 1
24
+ globs = stacks.find_all do |s|
25
+ s !~ /^[a-zA-Z0-9-]+$/
26
+ end
27
+ unless(globs.empty?)
28
+ glob_stacks = provider.connection.stacks.all.find_all do |remote_stack|
29
+ globs.detect do |glob|
30
+ File.fnmatch(glob, remote_stack.name)
31
+ end
32
+ end
33
+ stacks += glob_stacks.map(&:name)
34
+ stacks -= globs
35
+ stacks.sort!
36
+ end
24
37
  ui.warn "Destroying Cloud Formation#{plural}: #{ui.color(stacks.join(', '), :bold)}"
25
38
  ui.confirm "Destroy formation#{plural}"
26
39
  stacks.each do |stack_name|
@@ -122,6 +122,7 @@ class Chef
122
122
  # @param template [Hash] stack template
123
123
  # @param stack [Fog::Orchestration::Stack]
124
124
  # @return [Hash]
125
+ # @todo to be scrubbed
125
126
  def redefault_stack_parameters(template, stack)
126
127
  stack.parameters.each do |key, value|
127
128
  if(template['Parameters'][key])
@@ -131,30 +132,6 @@ class Chef
131
132
  template
132
133
  end
133
134
 
134
- # Apply any defined remote stacks
135
- #
136
- # @param stack [Miasma::Models::Orchestration::Stack]
137
- # @return [Miasma::Models::Orchestration::Stack]
138
- def apply_stacks!(stack)
139
- remote_stacks = Chef::Config[:knife][:cloudformation].
140
- fetch(:update, {}).fetch(:apply_stacks, [])
141
- remote_stacks.each do |stack_name|
142
- remote_stack = provider.connection.stacks.get(stack_name)
143
- if(remote_stack)
144
- remote_stack.parameters.each do |key, value|
145
- next if Chef::Config[:knife][:cloudformation].fetch(:stacks, {}).fetch(:ignore_parameters, []).include?(key)
146
- if(stack.parameters.has_key?(key))
147
- stack.parameters[key] = value
148
- end
149
- end
150
- else
151
- ui.error "Failed to apply requested stack. Unable to locate. (#{stack_name})"
152
- exit 1
153
- end
154
- end
155
- stack
156
- end
157
-
158
135
  end
159
136
  end
160
137
  end
@@ -60,10 +60,23 @@ module KnifeCloudformation
60
60
  #
61
61
  # @param name [String] name of stack
62
62
  def poll_stack(name)
63
- knife_events = Chef::Knife::CloudformationEvents.new
64
- knife_events.name_args.push(name)
65
- Chef::Config[:knife][:cloudformation][:poll] = true
66
- knife_events.run
63
+ retry_attempts = 0
64
+ begin
65
+ provider.connection.stacks.reload
66
+ knife_events = Chef::Knife::CloudformationEvents.new
67
+ knife_events.name_args.push(name)
68
+ Chef::Config[:knife][:cloudformation][:poll] = true
69
+ knife_events.run
70
+ rescue => e
71
+ if(retry_attempts < Chef::Config[:knife][:cloudformation].fetch(:max_poll_retries, 5))
72
+ retry_attempts += 1
73
+ warn "Unexpected error encountered (#{e.class}: #{e}) Retrying [retry count: #{retry_attempts}]"
74
+ sleep(1)
75
+ retry
76
+ else
77
+ raise
78
+ end
79
+ end
67
80
  end
68
81
 
69
82
  # Wrapper for information retrieval. Provides consistent error
@@ -8,9 +8,49 @@ module KnifeCloudformation
8
8
 
9
9
  module InstanceMethods
10
10
 
11
+ # un-packed stack name joiner/identifier
12
+ UNPACK_NAME_JOINER = '-sfn-'
11
13
  # maximum number of attempts to get valid parameter value
12
14
  MAX_PARAMETER_ATTEMPTS = 5
13
15
 
16
+ # Apply any defined remote stacks
17
+ #
18
+ # @param stack [Miasma::Models::Orchestration::Stack]
19
+ # @return [Miasma::Models::Orchestration::Stack]
20
+ def apply_stacks!(stack)
21
+ action = self.class.name.downcase.end_with?('create') ? :create : :update
22
+ remote_stacks = Chef::Config[:knife][:cloudformation].
23
+ fetch(action, {}).fetch(:apply_stacks, [])
24
+ remote_stacks.each do |stack_name|
25
+ remote_stack = provider.connection.stacks.get(stack_name)
26
+ if(remote_stack)
27
+ stack.apply_stack(remote_stack)
28
+ else
29
+ apply_unpacked_stack!(stack_name, stack)
30
+ end
31
+ end
32
+ stack
33
+ end
34
+
35
+ # Apply all stacks from an unpacked stack
36
+ #
37
+ # @param stack_name [String] name of parent stack
38
+ # @param stack [Miasma::Models::Orchestration::Stack]
39
+ # @return [Miasma::Models::Orchestration::Stack]
40
+ def apply_unpacked_stack!(stack_name, stack)
41
+ result = provider.connection.stacks.all.find_all do |remote_stack|
42
+ remote_stack.name.start_with?("#{stack_name}#{UNPACK_NAME_JOINER}")
43
+ end.sort_by(&:name).map do |remote_stack|
44
+ stack.apply_stack(remote_stack)
45
+ end
46
+ unless(result.empty?)
47
+ stack
48
+ else
49
+ ui.error "Failed to apply requested stack. Unable to locate. (#{stack_name})"
50
+ exit 1
51
+ end
52
+ end
53
+
14
54
  # Unpack nested stack and run action on each stack, applying
15
55
  # the previous stacks automatically
16
56
  #
@@ -24,20 +64,24 @@ module KnifeCloudformation
24
64
  Chef::Config[:knife][:cloudformation][action.to_sym] ||= Mash.new
25
65
  Chef::Config[:knife][:cloudformation][action.to_sym][:apply_stacks] ||= []
26
66
 
27
- orig_params = Chef::Config[:knife][:cloudformation][:options][:parameters]
67
+ orig_options = Chef::Config[:knife][:cloudformation][:options].dup
68
+ stack_count = 0
28
69
 
29
70
  file['Resources'].each do |stack_resource_name, stack_resource|
30
71
 
31
- nested_stack_name = "#{name}-#{stack_resource_name}"
72
+ nested_stack_name = "#{name}#{UNPACK_NAME_JOINER}#{stack_count}-#{stack_resource_name}"
32
73
  nested_stack_template = stack_resource['Properties']['Stack']
33
- Chef::Config[:knife][:cloudformation][:options][:parameters] = orig_params
74
+ Chef::Config[:knife][:cloudformation][:options] = orig_options.dup
34
75
 
35
76
  klass = Chef::Knife.const_get("Cloudformation#{action.to_s.capitalize}")
36
77
  nested_stack_runner = klass.new
78
+ nested_stack_runner.config = config.dup
37
79
  nested_stack_runner.name_args.push(nested_stack_name)
38
80
  Chef::Config[:knife][:cloudformation][:template] = nested_stack_template
39
81
  nested_stack_runner.run
40
- Chef::Config[:knife][:cloudformation][action.to_sym][:apply_stacks].push(nested_stack_name).uniq!
82
+ unless(config[:print_only])
83
+ Chef::Config[:knife][:cloudformation][action.to_sym][:apply_stacks].push(nested_stack_name).uniq!
84
+ end
41
85
  Chef::Config[:knife][:cloudformation][:template] = nil
42
86
  provider.connection.stacks.reload
43
87
 
@@ -53,9 +53,9 @@ module KnifeCloudformation
53
53
  url = URI.parse(file.url)
54
54
  "#{url.scheme}://#{url.host}#{url.path}"
55
55
  end
56
- end.merge('sfn_nested_stack' => !!sf.nested?)
56
+ end
57
57
  else
58
- sf.dump
58
+ sf.dump.merge('sfn_nested_stack' => !!sf.nested?)
59
59
  end
60
60
  else
61
61
  _from_json(File.read(Chef::Config[:knife][:cloudformation][:file]))
@@ -1,4 +1,4 @@
1
1
  module KnifeCloudformation
2
2
  # Current library version
3
- VERSION = Gem::Version.new('0.2.12')
3
+ VERSION = Gem::Version.new('0.2.14')
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-cloudformation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.12
4
+ version: 0.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-12 00:00:00.000000000 Z
11
+ date: 2015-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef