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,99 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
-
6
- # Helper methods for path selection
7
- module PathSelector
8
-
9
- # Humanize the base name of path
10
- #
11
- # @param path [String]
12
- # @return [String]
13
- def humanize_path_basename(path)
14
- File.basename(path).sub(
15
- File.extname(path), ''
16
- ).split(/[-_]/).map(&:capitalize).join(' ')
17
- end
18
-
19
- # Prompt user for file selection
20
- #
21
- # @param directory [String] path to directory
22
- # @param opts [Hash] options
23
- # @option opts [Array<String>] :ignore_directories directory names
24
- # @option opts [String] :directories_name title for directories
25
- # @option opts [String] :files_name title for files
26
- # @option opts [String] :filter_prefix only return results matching filter
27
- # @return [String] file path
28
- def prompt_for_file(directory, opts={})
29
- file_list = Dir.glob(File.join(directory, '**', '**', '*')).find_all do |file|
30
- File.file?(file)
31
- end
32
- if(opts[:filter_prefix])
33
- file_list = file_list.find_all do |file|
34
- file.start_with?(options[:filter_prefix])
35
- end
36
- end
37
- directories = file_list.map do |file|
38
- File.dirname(file)
39
- end.uniq
40
- files = file_list.find_all do |path|
41
- path.sub(directory, '').split('/').size == 2
42
- end
43
- if(opts[:ignore_directories])
44
- directories.delete_if do |dir|
45
- opts[:ignore_directories].include?(File.basename(dir))
46
- end
47
- end
48
- if(directories.empty? && files.empty?)
49
- ui.fatal 'No formation paths discoverable!'
50
- else
51
- output = ['Please select an entry']
52
- output << '(or directory to list):' unless directories.empty?
53
- ui.info output.join(' ')
54
- output.clear
55
- idx = 1
56
- valid = {}
57
- unless(directories.empty?)
58
- output << ui.color("#{opts.fetch(:directories_name, 'Directories')}:", :bold)
59
- directories.each do |dir|
60
- valid[idx] = {:path => dir, :type => :directory}
61
- output << [idx, humanize_path_basename(dir)]
62
- idx += 1
63
- end
64
- end
65
- unless(files.empty?)
66
- output << ui.color("#{opts.fetch(:files_name, 'Files')}:", :bold)
67
- files.each do |file|
68
- valid[idx] = {:path => file, :type => :file}
69
- output << [idx, humanize_path_basename(file)]
70
- idx += 1
71
- end
72
- end
73
- max = idx.to_s.length
74
- output.map! do |o|
75
- if(o.is_a?(Array))
76
- " #{o.first}.#{' ' * (max - o.first.to_s.length)} #{o.last}"
77
- else
78
- o
79
- end
80
- end
81
- ui.info "#{output.join("\n")}\n"
82
- response = ask_question('Enter selection: ').to_i
83
- unless(valid[response])
84
- ui.fatal 'How about using a real value'
85
- exit 1
86
- else
87
- entry = valid[response.to_i]
88
- if(entry[:type] == :directory)
89
- prompt_for_file(entry[:path], opts)
90
- else
91
- "/#{entry[:path]}"
92
- end
93
- end
94
- end
95
- end
96
-
97
- end
98
- end
99
- end
@@ -1,29 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
-
6
- # Helper methods for SSH interactions
7
- module Ssher
8
-
9
- # Retrieve file from remote node
10
- #
11
- # @param address [String]
12
- # @param user [String]
13
- # @param path [String] remote file path
14
- # @param ssh_opts [Hash]
15
- # @return [String, NilClass]
16
- def remote_file_contents(address, user, path, ssh_opts={})
17
- if(path.to_s.strip.empty?)
18
- raise ArgumentError.new 'No file path provided!'
19
- end
20
- require 'net/ssh'
21
- content = ''
22
- ssh_session = Net::SSH.start(address, user, ssh_opts)
23
- content = ssh_session.exec!("sudo cat #{path}")
24
- content.empty? ? nil : content
25
- end
26
-
27
- end
28
- end
29
- end
@@ -1,271 +0,0 @@
1
- require 'chef'
2
- require 'knife-cloudformation'
3
-
4
- module KnifeCloudformation
5
- module Utils
6
-
7
- # Stack serialization helper
8
- class StackExporter
9
-
10
- include KnifeCloudformation::Utils::AnimalStrings
11
- include KnifeCloudformation::Utils::JSON
12
-
13
- # default chef environment name
14
- DEFAULT_CHEF_ENVIRONMENT = '_default'
15
- # default instance options
16
- DEFAULT_OPTIONS = Mash.new(
17
- :chef_popsicle => true,
18
- :ignored_parameters => ['Environment', 'StackCreator', 'Creator'],
19
- :chef_environment_parameter => 'Environment'
20
- )
21
- # default structure of export payload
22
- DEFAULT_EXPORT_STRUCTURE = {
23
- :stack => Mash.new(
24
- :template => nil,
25
- :options => {
26
- :parameters => Mash.new,
27
- :capabilities => [],
28
- :notification_topics => []
29
- }
30
- ),
31
- :generator => {
32
- :timestamp => Time.now.to_i,
33
- :name => 'knife-cloudformation',
34
- :version => KnifeCloudformation::VERSION.version,
35
- :provider => nil
36
- }
37
- }
38
-
39
- # @return [Miasma::Models::Orchestration::Stack]
40
- attr_reader :stack
41
- # @return [Hash]
42
- attr_reader :options
43
- # @return [Hash]
44
- attr_reader :stack_export
45
-
46
- # Create new instance
47
- #
48
- # @param stack [Miasma::Models::Orchestration::Stack]
49
- # @param options [Hash]
50
- # @option options [KnifeCloudformation::Provider] :provider
51
- # @option options [TrueClass, FalseClass] :chef_popsicle freeze run list
52
- # @option options [Array<String>] :ignored_parameters
53
- # @option options [String] :chef_environment_parameter
54
- def initialize(stack, options={})
55
- @stack = stack
56
- @options = DEFAULT_OPTIONS.merge(options)
57
- @stack_export = Mash.new
58
- end
59
-
60
- # Export stack
61
- #
62
- # @return [Hash] exported stack
63
- def export
64
- @stack_export = Mash.new(DEFAULT_EXPORT_STRUCTURE).tap do |stack_export|
65
- [:parameters, :capabilities, :notification_topics].each do |key|
66
- if(val = stack.send(key))
67
- stack_export[:stack][key] = val
68
- end
69
- end
70
- stack_export[:stack][:template] = stack.template
71
- stack_export[:generator][:timestamp] = Time.now.to_i
72
- stack_export[:generator][:provider] = stack.provider.connection.provider
73
- if(chef_popsicle?)
74
- freeze_runlists(stack_export)
75
- end
76
- remove_ignored_parameters(stack_export)
77
- stack_export[:stack][:template] = _to_json(
78
- stack_export[:stack][:template]
79
- )
80
- end
81
- end
82
-
83
- # Provide query methods on options hash
84
- #
85
- # @param args [Object] argument list
86
- # @return [Object]
87
- def method_missing(*args)
88
- m = args.first.to_s
89
- if(m.end_with?('?') && options.has_key?(k = m.sub('?', '').to_sym))
90
- !!options[k]
91
- else
92
- super
93
- end
94
- end
95
-
96
- protected
97
-
98
- # Remove parameter values from export that are configured to be
99
- # ignored
100
- #
101
- # @param export [Hash] stack export
102
- # @return [Hash]
103
- def remove_ignored_parameters(export)
104
- options[:ignored_parameters].each do |param|
105
- if(export[:stack][:options][:parameters])
106
- export[:stack][:options][:parameters].delete(param)
107
- end
108
- end
109
- export
110
- end
111
-
112
- # Environment name to use when interacting with Chef
113
- #
114
- # @param export [Hash] current export state
115
- # @return [String] environment name
116
- def chef_environment_name(export)
117
- if(chef_environment_parameter?)
118
- name = export[:stack][:options][:parameters][options[:chef_environment_parameter]]
119
- end
120
- name || DEFAULT_CHEF_ENVIRONMENT
121
- end
122
-
123
- # @return [Chef::Environment]
124
- def environment
125
- unless(@env)
126
- @env = Chef::Environment.load('_default')
127
- end
128
- @env
129
- end
130
-
131
- # Find latest available cookbook version within
132
- # the configured environment
133
- #
134
- # @param cookbook [String] name of cookbook
135
- # @return [Chef::Version]
136
- def allowed_cookbook_version(cookbook)
137
- restriction = environment.cookbook_versions[cookbook]
138
- requirement = Gem::Requirement.new(restriction)
139
- Chef::CookbookVersion.available_versions(cookbook).detect do |v|
140
- requirement.satisfied_by?(Gem::Version.new(v))
141
- end
142
- end
143
-
144
- # Extract the runlist item. Fully expands roles and provides
145
- # version pegged runlist.
146
- #
147
- # @param item [Chef::RunList::RunListItem, Array<String>]
148
- # @return [Hash] new chef configuration hash
149
- # @note this will expand all roles
150
- def extract_runlist_item(item)
151
- rl_item = item.is_a?(Chef::RunList::RunListItem) ? item : Chef::RunList::RunListItem.new(item)
152
- static_content = Mash.new(:run_list => [])
153
- if(rl_item.recipe?)
154
- cookbook, recipe = rl_item.name.split('::')
155
- peg_version = allowed_cookbook_version(cookbook)
156
- static_content[:run_list] << "recipe[#{[cookbook, recipe || 'default'].join('::')}@#{peg_version}]"
157
- elsif(rl_item.role?)
158
- role = Chef::Role.load(rl_item.name)
159
- role.run_list.each do |item|
160
- static_content = Chef::Mixin::DeepMerge.merge(static_content, extract_runlist_item(item))
161
- end
162
- static_content = Chef::Mixin::DeepMerge.merge(
163
- static_content, Chef::Mixin::DeepMerge.merge(role.default_attributes, role.override_attributes)
164
- )
165
- else
166
- raise TypeError.new("Unknown chef run list item encountered: #{rl_item.inspect}")
167
- end
168
- static_content
169
- end
170
-
171
- # Expand any detected chef run lists and freeze them within the
172
- # stack template
173
- #
174
- # @param first_run [Hash] chef first run hash
175
- # @return [Hash]
176
- def unpack_and_freeze_runlist(first_run)
177
- extracted_runlists = first_run['run_list'].map do |item|
178
- extract_runlist_item(cf_replace(item))
179
- end
180
- first_run.delete('run_list')
181
- first_run.replace(
182
- extracted_runlists.inject(first_run) do |memo, first_run_item|
183
- Chef::Mixin::DeepMerge.merge(memo, first_run_item)
184
- end
185
- )
186
- end
187
-
188
- # Freeze chef run lists
189
- #
190
- # @param exported [Hash] stack export
191
- # @return [Hash]
192
- def freeze_runlists(exported)
193
- first_runs = locate_runlists(exported)
194
- first_runs.each do |first_run|
195
- unpack_and_freeze_runlist(first_run)
196
- end
197
- exported
198
- end
199
-
200
- # Locate chef run lists within data collection
201
- #
202
- # @param thing [Enumerable] collection from export
203
- # @return [Enumerable] updated collection from export
204
- def locate_runlists(thing)
205
- result = []
206
- case thing
207
- when Hash
208
- if(thing['content'] && thing['content']['run_list'])
209
- result << thing['content']
210
- else
211
- thing.each do |k,v|
212
- result += locate_runlists(v)
213
- end
214
- end
215
- when Array
216
- thing.each do |v|
217
- result += locate_runlists(v)
218
- end
219
- end
220
- result
221
- end
222
-
223
- # Apply cloudformation function to data
224
- #
225
- # @param hsh [Object] stack template item
226
- # @return [Object]
227
- def cf_replace(hsh)
228
- if(hsh.is_a?(Hash))
229
- case hsh.keys.first
230
- when 'Fn::Join'
231
- cf_join(*hsh.values.first)
232
- when 'Ref'
233
- cf_ref(hsh.values.first)
234
- else
235
- hsh
236
- end
237
- else
238
- hsh
239
- end
240
- end
241
-
242
- # Apply Ref function
243
- #
244
- # @param ref_name [Hash]
245
- # @return [Object] value in parameters
246
- def cf_ref(ref_name)
247
- if(stack.parameters.has_key?(ref_name))
248
- stack.parameters[ref_name]
249
- else
250
- raise KeyError.new("No parameter found with given reference name (#{ref_name}). " <<
251
- "Only parameter based references supported!")
252
- end
253
- end
254
-
255
- # Apply Join function
256
- #
257
- # @param delim [String] join delimiter
258
- # @param args [String, Hash] items to join
259
- # @return [String]
260
- def cf_join(delim, args)
261
- args.map do |arg|
262
- if(arg.is_a?(Hash))
263
- cf_replace(arg)
264
- else
265
- arg.to_s
266
- end
267
- end.join(delim)
268
- end
269
- end
270
- end
271
- end
@@ -1,37 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
- # Helper for scrubbing stack parameters
6
- class StackParameterScrubber
7
-
8
- class << self
9
-
10
- # Validate attributes within Parameter blocks
11
- ALLOWED_PARAMETER_ATTRIBUTES = %w(
12
- Type Default NoEcho AllowedValues AllowedPattern
13
- MaxLength MinLength MaxValue MinValue Description
14
- ConstraintDescription
15
- )
16
-
17
- # Clean the parameters of the template
18
- #
19
- # @param template [Hash]
20
- # @return [Hash] template
21
- def scrub!(template)
22
- parameters = template['Parameters']
23
- if(parameters)
24
- parameters.each do |name, options|
25
- options.delete_if do |attribute, value|
26
- !ALLOWED_PARAMETER_ATTRIBUTES.include?(attribute)
27
- end
28
- end
29
- template['Parameters'] = parameters
30
- end
31
- template
32
- end
33
-
34
- end
35
- end
36
- end
37
- end
@@ -1,124 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
-
6
- # Helper utility for validating stack parameters
7
- class StackParameterValidator
8
- class << self
9
-
10
- include KnifeCloudformation::Utils::AnimalStrings
11
-
12
- # Validate a parameters
13
- #
14
- # @param value [Object] value for parameter
15
- # @param parameter_definition [Hash]
16
- # @option parameter_definition [Array<String>] 'AllowedValues'
17
- # @option parameter_definition [String] 'AllowedPattern'
18
- # @option parameter_definition [String, Integer] 'MaxLength'
19
- # @option parameter_definition [String, Integer] 'MinLength'
20
- # @option parameter_definition [String, Integer] 'MaxValue'
21
- # @option parameter_definition [String, Integer] 'MinValue'
22
- # @return [TrueClass, Array<String>] true if valid. array of string errors if invalid
23
- def validate(value, parameter_definition)
24
- return [[:blank, 'Value cannot be blank']] if value.to_s.strip.empty?
25
- result = %w(AllowedValues AllowedPattern MaxLength MinLength MaxValue MinValue).map do |key|
26
- if(parameter_definition[key])
27
- res = self.send(snake(key), value, parameter_definition)
28
- res == true ? true : [snake(key), res]
29
- else
30
- true
31
- end
32
- end
33
- result.delete_if{|x| x == true}
34
- result.empty? ? true : result
35
- end
36
-
37
- # Parameter is within allowed values
38
- #
39
- # @param value [String]
40
- # @param pdef [Hash] parameter definition
41
- # @option pdef [Array<String>] 'AllowedValues'
42
- # @return [TrueClass, String]
43
- def allowed_values(value, pdef)
44
- if(pdef['AllowedValues'].include?(value))
45
- true
46
- else
47
- "Not an allowed value: #{pdef['AllowedValues'].join(', ')}"
48
- end
49
- end
50
-
51
- # Parameter matches allowed pattern
52
- #
53
- # @param value [String]
54
- # @param pdef [Hash] parameter definition
55
- # @option pdef [String] 'AllowedPattern'
56
- # @return [TrueClass, String]
57
- def allowed_pattern(value, pdef)
58
- if(value.match(/#{pdef['AllowedPattern']}/))
59
- true
60
- else
61
- "Not a valid pattern. Must match: #{pdef['AllowedPattern']}"
62
- end
63
- end
64
-
65
- # Parameter length is less than or equal to max length
66
- #
67
- # @param value [String, Integer]
68
- # @param pdef [Hash] parameter definition
69
- # @option pdef [String] 'MaxLength'
70
- # @return [TrueClass, String]
71
- def max_length(value, pdef)
72
- if(value.length <= pdef['MaxLength'].to_i)
73
- true
74
- else
75
- "Value must not exceed #{pdef['MaxLength']} characters"
76
- end
77
- end
78
-
79
- # Parameter length is greater than or equal to min length
80
- #
81
- # @param value [String]
82
- # @param pdef [Hash] parameter definition
83
- # @option pdef [String] 'MinLength'
84
- # @return [TrueClass, String]
85
- def min_length(value, pdef)
86
- if(value.length >= pdef['MinLength'].to_i)
87
- true
88
- else
89
- "Value must be at least #{pdef['MinLength']} characters"
90
- end
91
- end
92
-
93
- # Parameter value is less than or equal to max value
94
- #
95
- # @param value [String]
96
- # @param pdef [Hash] parameter definition
97
- # @option pdef [String] 'MaxValue'
98
- # @return [TrueClass, String]
99
- def max_value(value, pdef)
100
- if(value.to_i <= pdef['MaxValue'].to_i)
101
- true
102
- else
103
- "Value must not be greater than #{pdef['MaxValue']}"
104
- end
105
- end
106
-
107
- # Parameter value is greater than or equal to min value
108
- #
109
- # @param value [String]
110
- # @param pdef [Hash] parameter definition
111
- # @option pdef [String] 'MinValue'
112
- # @return [TrueClass, String]
113
- def min_value(value, pdef)
114
- if(value.to_i >= pdef['MinValue'].to_i)
115
- true
116
- else
117
- "Value must not be less than #{pdef['MinValue']}"
118
- end
119
- end
120
-
121
- end
122
- end
123
- end
124
- end