knife-cloudformation 0.2.24 → 0.5.0

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/README.md +16 -0
  4. data/knife-cloudformation.gemspec +14 -4
  5. data/lib/knife-cloudformation.rb +0 -28
  6. data/lib/knife-cloudformation/version.rb +1 -1
  7. metadata +18 -80
  8. data/lib/chef/knife/cloudformation_create.rb +0 -147
  9. data/lib/chef/knife/cloudformation_describe.rb +0 -99
  10. data/lib/chef/knife/cloudformation_destroy.rb +0 -84
  11. data/lib/chef/knife/cloudformation_events.rb +0 -117
  12. data/lib/chef/knife/cloudformation_export.rb +0 -162
  13. data/lib/chef/knife/cloudformation_import.rb +0 -141
  14. data/lib/chef/knife/cloudformation_inspect.rb +0 -206
  15. data/lib/chef/knife/cloudformation_list.rb +0 -72
  16. data/lib/chef/knife/cloudformation_promote.rb +0 -40
  17. data/lib/chef/knife/cloudformation_update.rb +0 -137
  18. data/lib/chef/knife/cloudformation_validate.rb +0 -36
  19. data/lib/knife-cloudformation/cache.rb +0 -385
  20. data/lib/knife-cloudformation/knife.rb +0 -9
  21. data/lib/knife-cloudformation/knife/base.rb +0 -195
  22. data/lib/knife-cloudformation/knife/stack.rb +0 -197
  23. data/lib/knife-cloudformation/knife/template.rb +0 -213
  24. data/lib/knife-cloudformation/monkey_patch.rb +0 -8
  25. data/lib/knife-cloudformation/monkey_patch/stack.rb +0 -195
  26. data/lib/knife-cloudformation/provider.rb +0 -225
  27. data/lib/knife-cloudformation/utils.rb +0 -24
  28. data/lib/knife-cloudformation/utils/animal_strings.rb +0 -28
  29. data/lib/knife-cloudformation/utils/debug.rb +0 -31
  30. data/lib/knife-cloudformation/utils/json.rb +0 -64
  31. data/lib/knife-cloudformation/utils/object_storage.rb +0 -28
  32. data/lib/knife-cloudformation/utils/output.rb +0 -79
  33. data/lib/knife-cloudformation/utils/path_selector.rb +0 -99
  34. data/lib/knife-cloudformation/utils/ssher.rb +0 -29
  35. data/lib/knife-cloudformation/utils/stack_exporter.rb +0 -271
  36. data/lib/knife-cloudformation/utils/stack_parameter_scrubber.rb +0 -37
  37. data/lib/knife-cloudformation/utils/stack_parameter_validator.rb +0 -124
@@ -1,206 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- class Chef
4
- class Knife
5
- # Cloudformation inspect command
6
- class CloudformationInspect < Knife
7
-
8
- include KnifeCloudformation::Knife::Base
9
- include KnifeCloudformation::Utils::Ssher
10
-
11
- banner 'knife cloudformation inspect NAME'
12
-
13
- option(:attribute,
14
- :short => '-a ATTR',
15
- :long => '--attribute ATTR',
16
- :description => 'Dot delimited attribute to view'
17
- )
18
-
19
- option(:nodes,
20
- :short => '-N',
21
- :long => '--[no-]nodes',
22
- :boolean => true,
23
- :description => 'Locate all instances'
24
- )
25
-
26
- option(:instance_failure,
27
- :short => '-I [LOG_FILE_PATH]',
28
- :long => '--instance-failure [LOG_FILE_PATH]',
29
- :descrption => 'Display chef log file (defaults /var/log/chef/client.log)',
30
- :proc => lambda{|val|
31
- Chef::Config[:knife][:cloudformation][:failure_log_path] = val
32
- }
33
- )
34
-
35
- option(:identity_file,
36
- :short => '-i IDENTITY_FILE',
37
- :long => '--identity-file IDENTITY_FILE',
38
- :description => 'SSH identity file for authentication',
39
- :proc => lambda{|val|
40
- Chef::Config[:knife][:cloudformation][:identity_file] = val
41
- }
42
- )
43
-
44
- option(:ssh_user,
45
- :short => '-x SSH_USER',
46
- :long => '--ssh-user SSH_USER',
47
- :description => 'SSH username for inspection connect',
48
- :proc => lambda{|val|
49
- Chef::Config[:knife][:cloudformation][:ssh_user] = val
50
- }
51
- )
52
-
53
- # Run the stack inspection action
54
- def _run
55
- stack_name = name_args.last
56
- stack = provider.connection.stacks.get(stack_name)
57
- ui.info "Stack inspection #{ui.color(stack_name, :bold)}:"
58
- outputs = [:attribute, :nodes, :instance_failure].map do |key|
59
- if(config.has_key?(key))
60
- send("display_#{key}", stack)
61
- key
62
- end
63
- end.compact
64
- if(outputs.empty?)
65
- ui.info ' Stack dump:'
66
- ui.info MultiJson.dump(
67
- MultiJson.load(
68
- stack.reload.to_json
69
- ),
70
- :pretty => true
71
- )
72
- end
73
- end
74
-
75
- def display_instance_failure(stack)
76
- instances = stack.resources.all.find_all do |resource|
77
- resource.state.to_s.end_with?('failed')
78
- end.map do |resource|
79
- # If compute instance, simply expand
80
- if(resource.within?(:compute, :servers))
81
- resource.instance
82
- # If a waitcondition, check for instance ID
83
- elsif(resource.type.to_s.downcase.end_with?('waitcondition'))
84
- if(resource.status_reason.to_s.include?('uniqueId'))
85
- srv_id = resource.status_reason.split(' ').last.strip
86
- provider.connection.api_for(:compute).servers.get(srv_id)
87
- end
88
- end
89
- end.compact
90
- if(instances.empty?)
91
- ui.error 'Failed to locate any failed instances'
92
- else
93
- log_path = Chef::Config[:knife][:cloudformation][:failure_log_path]
94
- if(log_path.to_s.empty?)
95
- log_path = '/var/log/chef/client.log'
96
- end
97
- opts = ssh_key ? {:keys => [ssh_key]} : {}
98
- instances.each do |instance|
99
- ui.info " -> Log inspect for #{instance.id}:"
100
- address = instance.addresses_public.map do |address|
101
- if(address.version == 4)
102
- address.address
103
- end
104
- end
105
- if(address)
106
- ssh_attempt_users.each do |user|
107
- begin
108
- ui.info remote_file_contents(address.first, user, log_path, opts)
109
- break
110
- rescue Net::SSH::AuthenticationFailed
111
- ui.warn "Authentication failed for user #{user} on instance #{address}"
112
- rescue => e
113
- ui.error "Failed to retrieve log: #{e}"
114
- _debug e
115
- break
116
- end
117
- end
118
- end
119
- end
120
- end
121
- end
122
-
123
- # Users to attempt SSH connection
124
- #
125
- # @return [Array<String>] usernames for ssh connect attempt
126
- def ssh_attempt_users
127
- base_user = Chef::Config[:knife][:cloudformation][:ssh_user] ||
128
- Chef::Config[:knife][:ssh_user] ||
129
- ENV['USER']
130
- [base_user, Chef::Config[:knife][:cloudformation][:ssh_attempt_users]].flatten.compact
131
- end
132
-
133
- def ssh_key
134
- Chef::Config[:knife][:cloudformation][:identity_file] ||
135
- Chef::Config[:knife][:identity_file]
136
- end
137
-
138
- def display_attribute(stack)
139
- attr = config[:attribute].split('.').inject(stack) do |memo, key|
140
- args = key.scan(/\(([^)]*)\)/).flatten.first.to_s
141
- if(args)
142
- args = args.split(',').map{|a| a.to_i.to_s == a ? a.to_i : a}
143
- key = key.split('(').first
144
- end
145
- if(memo.public_methods.include?(key.to_sym))
146
- if(args.size == 1 && args.first.to_s.start_with?('&'))
147
- memo.send(key, &args.first.slice(2, args.first.size).to_sym)
148
- else
149
- memo.send(*[key, args].flatten.compact)
150
- end
151
- else
152
- raise NoMethodError.new "Invalid attribute requested! (#{memo.class}##{key})"
153
- end
154
- end
155
- ui.info " Attribute Lookup -> #{config[:attribute]}:"
156
- ui.info MultiJson.dump(
157
- MultiJson.load(
158
- MultiJson.dump(attr)
159
- ),
160
- :pretty => true
161
- )
162
- end
163
-
164
- def display_nodes(stack)
165
- asg_nodes = Smash[
166
- stack.resources.all.find_all do |resource|
167
- resource.within?(:auto_scale, :groups)
168
- end.map do |group_resource|
169
- asg = group_resource.expand
170
- [
171
- asg.name,
172
- Smash[
173
- asg.servers.map(&:expand).map{|s|
174
- [s.id, Smash.new(
175
- :name => s.name,
176
- :addresses => s.addresses.map(&:address)
177
- )]
178
- }
179
- ]
180
- ]
181
- end
182
- ]
183
- compute_nodes = Smash[
184
- stack.resources.all.find_all do |resource|
185
- resource.within?(:compute, :servers)
186
- end.map do |srv|
187
- srv = srv.instance
188
- [srv.id, Smash.new(
189
- :name => srv.name,
190
- :addresses => srv.addresses.map(&:address)
191
- )]
192
- end
193
- ]
194
- unless(asg_nodes.empty?)
195
- ui.info ' AutoScale Group Instances:'
196
- ui.info MultiJson.dump(asg_nodes, :pretty => true)
197
- end
198
- unless(compute_nodes.empty?)
199
- ui.info ' Compute Instances:'
200
- ui.info MultiJson.dump(compute_nodes, :pretty => true)
201
- end
202
- end
203
-
204
- end
205
- end
206
- end
@@ -1,72 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- class Chef
4
- class Knife
5
- # Cloudformation list command
6
- class CloudformationList < Knife
7
-
8
- include KnifeCloudformation::Knife::Base
9
-
10
- banner 'knife cloudformation list NAME'
11
-
12
- option(:attribute,
13
- :short => '-a ATTR',
14
- :long => '--attribute ATTR',
15
- :description => 'Attribute to print. Can be used multiple times.',
16
- :proc => lambda {|val|
17
- Chef::Config[:knife][:cloudformation][:attributes] ||= []
18
- Chef::Config[:knife][:cloudformation][:attributes].push(val).uniq!
19
- }
20
- )
21
-
22
- option(:all,
23
- :long => '--all-attributes',
24
- :description => 'Print all attributes'
25
- )
26
-
27
- option(:status,
28
- :short => '-S STATUS',
29
- :long => '--status STATUS',
30
- :description => 'Match given status. Use "none" to disable. Can be used multiple times.',
31
- :proc => lambda {|val|
32
- Chef::Config[:knife][:cloudformation][:status] ||= []
33
- Chef::Config[:knife][:cloudformation][:status].push(val).uniq!
34
- }
35
- )
36
-
37
- # Run the list command
38
- def _run
39
- things_output(nil, get_list, nil)
40
- end
41
-
42
- # Get the list of stacks to display
43
- #
44
- # @return [Array<Hash>]
45
- def get_list
46
- get_things do
47
- provider.stacks.all.map do |stack|
48
- Mash.new(stack.attributes)
49
- end.sort do |x, y|
50
- if(y[:created].to_s.empty?)
51
- -1
52
- elsif(x[:created].to_s.empty?)
53
- 1
54
- else
55
- Time.parse(y['created'].to_s) <=> Time.parse(x['created'].to_s)
56
- end
57
- end
58
- end
59
- end
60
-
61
- # @return [Array<String>] default attributes to display
62
- def default_attributes
63
- if(provider.connection.provider == :aws)
64
- %w(name created status template_description)
65
- else
66
- %w(name created status description)
67
- end
68
- end
69
-
70
- end
71
- end
72
- end
@@ -1,40 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- class Chef
4
- class Knife
5
- class CloudformationPromote < Knife
6
-
7
- include KnifeCloudformation::Knife::Base
8
-
9
- banner 'knife cloudformation promote NEW_STACK_NAME DESTINATION'
10
-
11
- option(:accounts,
12
- :long => '--accounts-file PATH',
13
- :short => '-A PATH',
14
- :description => 'JSON account file',
15
- :proc => lambda{|v|
16
- Chef::Config[:knife][:cloudformation][:promote_accounts] = JSON.load(File.read(v))
17
- }
18
- )
19
-
20
- option(:storage_bucket,
21
- :long => '--exports-bucket NAME',
22
- :description => 'Bucket name containing the exports',
23
- :proc => lambda{|v| Chef::Config[:knife][:cloudformation][:promote_exports_bucket] = v }
24
- )
25
-
26
- option(:storage_prefix,
27
- :long => '--exports-prefix PREFIX',
28
- :description => 'Prefix of stack key',
29
- :proc => lambda{|v| Chef::Config[:knife][:cloudformation][:promote_exports_prefix] = v }
30
- )
31
-
32
-
33
- def _run
34
- stack_name, destination = name_args
35
-
36
- end
37
-
38
- end
39
- end
40
- end
@@ -1,137 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- class Chef
4
- class Knife
5
- class CloudformationUpdate < Knife
6
-
7
- include KnifeCloudformation::Knife::Base
8
- include KnifeCloudformation::Knife::Template
9
- include KnifeCloudformation::Knife::Stack
10
-
11
- option(:file_path_prompt,
12
- :long => '--[no-]file-path-prompt',
13
- :description => 'Interactive prompt for template path discovery',
14
- :boolean => true,
15
- :default => false,
16
- :proc => lambda {|val|
17
- Chef::Config[:knife][:cloudformation][:file_path_prompt] = val
18
- }
19
- )
20
- option(:apply_stacks,
21
- :long => '--apply-stack NAME_OR_ID',
22
- :description => 'Autofill parameters using existing stack outputs. Can be used multiple times',
23
- :proc => lambda {|val|
24
- Chef::Config[:knife][:cloudformation][:update] ||= Mash.new
25
- Chef::Config[:knife][:cloudformation][:update][:apply_stacks] ||= []
26
- Chef::Config[:knife][:cloudformation][:update][:apply_stacks].push(val).uniq!
27
- }
28
- )
29
-
30
- banner 'knife cloudformation update NAME'
31
-
32
- # Run the stack creation command
33
- def _run
34
- name = name_args.first
35
- unless(name)
36
- ui.fatal "Formation name must be specified!"
37
- exit 1
38
- end
39
-
40
- stack_info = "#{ui.color('Name:', :bold)} #{name}"
41
-
42
- if(Chef::Config[:knife][:cloudformation][:file])
43
- file = load_template_file
44
- stack_info << " #{ui.color('Path:', :bold)} #{Chef::Config[:knife][:cloudformation][:file]}"
45
- nested_stacks = file.delete('sfn_nested_stack')
46
- end
47
-
48
- if(nested_stacks)
49
-
50
- unpack_nesting(name, file, :update)
51
-
52
- else
53
- stack = provider.connection.stacks.get(name)
54
-
55
- if(stack)
56
- ui.info "#{ui.color('Cloud Formation:', :bold)} #{ui.color('update', :green)}"
57
-
58
- unless(file)
59
- if(Chef::Config[:knife][:cloudformation][:template])
60
- file = Chef::Config[:knife][:cloudformation][:template]
61
- stack_info << " #{ui.color('(template provided)', :green)}"
62
- else
63
- stack_info << " #{ui.color('(no template update)', :yellow)}"
64
- end
65
- end
66
- ui.info " -> #{stack_info}"
67
-
68
- apply_stacks!(stack)
69
-
70
- if(file)
71
- populate_parameters!(file, stack.parameters)
72
- stack.template = translate_template(file)
73
- stack.parameters = Chef::Config[:knife][:cloudformation][:options][:parameters]
74
- stack.template = KnifeCloudformation::Utils::StackParameterScrubber.scrub!(stack.template)
75
- else
76
- populate_parameters!(stack.template, stack.parameters)
77
- stack.parameters = Chef::Config[:knife][:cloudformation][:options][:parameters]
78
- end
79
-
80
- begin
81
- stack.save
82
- rescue Miasma::Error::ApiError::RequestError => e
83
- if(e.message.downcase.include?('no updates')) # :'(
84
- ui.warn "No updates detected for stack (#{stack.name})"
85
- else
86
- raise
87
- end
88
- end
89
-
90
- if(Chef::Config[:knife][:cloudformation][:poll])
91
- poll_stack(stack.name)
92
- if(stack.success?)
93
- ui.info "Stack update complete: #{ui.color('SUCCESS', :green)}"
94
- knife_output = Chef::Knife::CloudformationDescribe.new
95
- knife_output.name_args.push(name)
96
- knife_output.config[:outputs] = true
97
- knife_output.run
98
- else
99
- ui.fatal "Update of stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
100
- ui.info ""
101
- knife_inspect = Chef::Knife::CloudformationInspect.new
102
- knife_inspect.name_args.push(name)
103
- knife_inspect.config[:instance_failure] = true
104
- knife_inspect.run
105
- exit 1
106
- end
107
- else
108
- ui.warn 'Stack state polling has been disabled.'
109
- ui.info "Stack update initialized for #{ui.color(name, :green)}"
110
- end
111
- else
112
- ui.fatal "Failed to locate requested stack: #{ui.color(name, :red, :bold)}"
113
- exit -1
114
- end
115
-
116
- end
117
- end
118
-
119
- # Update default values for parameters in template with
120
- # currently used parameters on the existing stack
121
- #
122
- # @param template [Hash] stack template
123
- # @param stack [Fog::Orchestration::Stack]
124
- # @return [Hash]
125
- # @todo to be scrubbed
126
- def redefault_stack_parameters(template, stack)
127
- stack.parameters.each do |key, value|
128
- if(template['Parameters'][key])
129
- template['Parameters'][key]['Default'] = value
130
- end
131
- end
132
- template
133
- end
134
-
135
- end
136
- end
137
- end