knife-cloudformation 0.2.12 → 0.2.14

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