knife-cloudformation 0.2.24 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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,225 +0,0 @@
1
- require 'chef/mash'
2
- require 'logger'
3
- require 'chef/mixin/deep_merge'
4
- require 'knife-cloudformation'
5
-
6
- module KnifeCloudformation
7
- # Remote provider interface
8
- class Provider
9
-
10
- include KnifeCloudformation::Utils::AnimalStrings
11
-
12
- # Minimum number of seconds to wait before re-expanding in
13
- # progress stack
14
- STACK_EXPAND_INTERVAL = 45
15
-
16
- # Default interval for refreshing stack list in cache
17
- STACK_LIST_INTERVAL = 120
18
-
19
- # @return [Miasma::Models::Orchestration]
20
- attr_reader :connection
21
- # @return [Cache]
22
- attr_reader :cache
23
- # @return [Thread, NilClass] stack list updater
24
- attr_accessor :updater
25
- # @return [TrueClass, FalseClass] async updates
26
- attr_reader :async
27
- # @return [Logger, NilClass] logger in use
28
- attr_reader :logger
29
- # @return [Numeric] interval between stack expansions
30
- attr_reader :stack_expansion_interval
31
- # @return [Numeric] interval between stack list updates
32
- attr_reader :stack_list_interval
33
-
34
- # Create new instance
35
- #
36
- # @param args [Hash]
37
- # @option args [Hash] :miasma miasma connection hash
38
- # @option args [Cache] :cache
39
- # @option args [TrueClass, FalseClass] :async fetch stacks async (defaults true)
40
- # @option args [Logger] :logger use custom logger
41
- # @option args [Numeric] :stack_expansion_interval interval to wait between stack data expands
42
- # @option args [Numeric] :stack_list_interval interval to wait between stack list refresh
43
- def initialize(args={})
44
- unless(args[:miasma][:provider])
45
- best_guess = args[:miasma].keys.group_by do |key|
46
- key.to_s.split('_').first
47
- end.sort do |x, y|
48
- y.size <=> x.size
49
- end.first
50
- if(best_guess)
51
- provider = best_guess.first.to_sym
52
- else
53
- raise ArgumentError.new 'Cannot auto determine :provider value for credentials'
54
- end
55
- else
56
- provider = args[:miasma].delete(:provider).to_sym
57
- end
58
- if(provider == :aws)
59
- if(args[:miasma][:region])
60
- args[:miasma][:aws_region] = args[:miasma].delete(:region)
61
- end
62
- end
63
- if(ENV['DEBUG'].to_s.downcase == 'true')
64
- log_to = STDOUT
65
- else
66
- if(Gem.win_platform?)
67
- log_to = 'NUL'
68
- else
69
- log_to = '/dev/null'
70
- end
71
- end
72
- @logger = args.fetch(:logger, Logger.new(log_to))
73
- @stack_expansion_interval = args.fetch(:stack_expansion_interval, STACK_EXPAND_INTERVAL)
74
- @stack_list_interval = args.fetch(:stack_list_interval, STACK_LIST_INTERVAL)
75
- @connection = Miasma.api(
76
- :provider => provider,
77
- :type => :orchestration,
78
- :credentials => args[:miasma]
79
- )
80
- @cache = args.fetch(:cache, Cache.new(:local))
81
- @async = args.fetch(:async, true)
82
- @miamsa_args = args[:miasma].dup
83
- cache.init(:stacks_lock, :lock, :timeout => 0.1)
84
- cache.init(:stacks, :stamped)
85
- cache.init(:stack_expansion_lock, :lock, :timeout => 0.1)
86
- if(args.fetch(:fetch, false))
87
- async ? update_stack_list! : fetch_stacks
88
- end
89
- end
90
-
91
- # @return [Miasma::Orchestration::Stacks]
92
- def stacks
93
- connection.stacks.from_json(cached_stacks)
94
- end
95
-
96
- # @return [String] json representation of cached stacks
97
- def cached_stacks
98
- fetch_stacks unless @initial_fetch_complete
99
- value = cache[:stacks].value
100
- value ? MultiJson.dump(MultiJson.load(value).values) : '[]'
101
- end
102
-
103
- # @return [Miasma::Orchestration::Stack, NilClass]
104
- def stack(stack_id)
105
- stacks.get(stack_id)
106
- end
107
-
108
- # Store stack attribute changes
109
- #
110
- # @param stack_id [String]
111
- # @param stack_attributes [Hash]
112
- # @return [TrueClass]
113
- def save_expanded_stack(stack_id, stack_attributes)
114
- current_stacks = MultiJson.load(cached_stacks)
115
- cache.locked_action(:stacks_lock) do
116
- logger.info "Saving expanded stack attributes in cache (#{stack_id})"
117
- current_stacks[stack_id] = stack_attributes.merge('Cached' => Time.now.to_i)
118
- cache[:stacks].value = MultiJson.dump(current_stacks)
119
- end
120
- true
121
- end
122
-
123
- # Remove stack from the cache
124
- #
125
- # @param stack_id [String]
126
- # @return [TrueClass, FalseClass]
127
- def remove_stack(stack_id)
128
- current_stacks = MultiJson.load(cached_stacks)
129
- logger.info "Attempting to remove stack from internal cache (#{stack_id})"
130
- cache.locked_action(:stacks_lock) do
131
- val = current_stacks.delete(stack_id)
132
- logger.info "Successfully removed stack from internal cache (#{stack_id})"
133
- cache[:stacks].value = MultiJson.dump(current_stacks)
134
- !!val
135
- end
136
- end
137
-
138
- # Expand all lazy loaded attributes within stack
139
- #
140
- # @param stack [Miasma::Models::Orchestration::Stack]
141
- def expand_stack(stack)
142
- logger.info "Stack expansion requested (#{stack.id})"
143
- if((stack.in_progress? && Time.now.to_i - stack.attributes['Cached'].to_i > stack_expansion_interval) ||
144
- !stack.attributes['Cached'])
145
- begin
146
- expanded = false
147
- cache.locked_action(:stack_expansion_lock) do
148
- expanded = true
149
- stack.reload
150
- stack.data['Cached'] = Time.now.to_i
151
- end
152
- if(expanded)
153
- save_expanded_stack(stack.id, stack.to_json)
154
- end
155
- rescue => e
156
- logger.error "Stack expansion failed (#{stack.id}) - #{e.class}: #{e}"
157
- end
158
- else
159
- logger.info "Stack has been cached within expand interval. Expansion prevented. (#{stack.id})"
160
- end
161
- end
162
-
163
- # Request stack information and store in cache
164
- #
165
- # @return [TrueClass]
166
- def fetch_stacks
167
- cache.locked_action(:stacks_lock) do
168
- logger.info "Lock aquired for stack update. Requesting stacks from upstream. (#{Thread.current})"
169
- stacks = Hash[
170
- connection.stacks.reload.all.map do |stack|
171
- [stack.id, stack.attributes]
172
- end
173
- ]
174
- if(cache[:stacks].value)
175
- existing_stacks = MultiJson.load(cache[:stacks].value)
176
- # Force common types
177
- stacks = MultiJson.load(MultiJson.dump(stacks))
178
- # Remove stacks that have been deleted
179
- stale_ids = existing_stacks.keys - stacks.keys
180
- stacks = Chef::Mixin::DeepMerge.merge(existing_stacks, stacks)
181
- stale_ids.each do |stale_id|
182
- stacks.delete(stale_id)
183
- end
184
- end
185
- cache[:stacks].value = stacks.to_json
186
- logger.info 'Stack list has been updated from upstream and cached locally'
187
- end
188
- @initial_fetch_complete = true
189
- end
190
-
191
- # Start async stack list update. Creates thread that loops every
192
- # `self.stack_list_interval` seconds and refreshes stack list in cache
193
- #
194
- # @return [TrueClass, FalseClass]
195
- def update_stack_list!
196
- if(updater.nil? || !updater.alive?)
197
- self.updater = Thread.new{
198
- loop do
199
- begin
200
- fetch_stacks
201
- sleep(stack_list_interval)
202
- rescue => e
203
- logger.error "Failure encountered on stack fetch: #{e.class} - #{e}"
204
- end
205
- end
206
- }
207
- true
208
- else
209
- false
210
- end
211
- end
212
-
213
- # Build API connection for service type
214
- #
215
- # @param service [String, Symbol]
216
- # @return [Miasma::Model]
217
- def service_for(service)
218
- connection.api_for(service)
219
- end
220
-
221
- end
222
- end
223
-
224
- # Release the monkeys!
225
- KnifeCloudformation::MonkeyPatch::Stack
@@ -1,24 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- # Utility classes and modules
5
- module Utils
6
-
7
- autoload :Output, 'knife-cloudformation/utils/output'
8
- autoload :StackParameterValidator, 'knife-cloudformation/utils/stack_parameter_validator'
9
- autoload :StackParameterScrubber, 'knife-cloudformation/utils/stack_parameter_scrubber'
10
- autoload :StackExporter, 'knife-cloudformation/utils/stack_exporter'
11
- autoload :Debug, 'knife-cloudformation/utils/debug'
12
- autoload :JSON, 'knife-cloudformation/utils/json'
13
- autoload :AnimalStrings, 'knife-cloudformation/utils/animal_strings'
14
- autoload :Ssher, 'knife-cloudformation/utils/ssher'
15
- autoload :ObjectStorage, 'knife-cloudformation/utils/object_storage'
16
- autoload :PathSelector, 'knife-cloudformation/utils/path_selector'
17
-
18
- # Provide methods directly from module for previous version compatibility
19
- extend JSON
20
- extend AnimalStrings
21
- extend ObjectStorage
22
-
23
- end
24
- end
@@ -1,28 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
-
6
- # Helper methods for string format modification
7
- module AnimalStrings
8
-
9
- # Camel case string
10
- #
11
- # @param string [String]
12
- # @return [String]
13
- def camel(string)
14
- string.to_s.split('_').map{|k| "#{k.slice(0,1).upcase}#{k.slice(1,k.length)}"}.join
15
- end
16
-
17
- # Snake case string
18
- #
19
- # @param string [String]
20
- # @return [Symbol]
21
- def snake(string)
22
- string.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym
23
- end
24
-
25
- end
26
-
27
- end
28
- end
@@ -1,31 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
- # Debug helpers
6
- module Debug
7
- # Output helpers
8
- module Output
9
- # Write debug message
10
- #
11
- # @param msg [String]
12
- def debug(msg)
13
- puts "<KnifeCloudformation>: #{msg}" if ENV['DEBUG']
14
- end
15
- end
16
-
17
- class << self
18
- # Load module into class
19
- #
20
- # @param klass [Class]
21
- def included(klass)
22
- klass.class_eval do
23
- include Output
24
- extend Output
25
- end
26
- end
27
- end
28
- end
29
-
30
- end
31
- end
@@ -1,64 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
-
6
- # JSON helper methods
7
- module JSON
8
-
9
- # Attempt to load chef JSON compat helper
10
- #
11
- # @return [TrueClass, FalseClass] chef compat helper available
12
- def try_json_compat
13
- unless(@_json_loaded)
14
- begin
15
- require 'chef/json_compat'
16
- rescue
17
- require "#{ENV['RUBY_JSON_LIB'] || 'json'}"
18
- end
19
- @_json_loaded = true
20
- end
21
- defined?(Chef::JSONCompat)
22
- end
23
-
24
- # Convert to JSON
25
- #
26
- # @param thing [Object]
27
- # @return [String]
28
- def _to_json(thing)
29
- if(try_json_compat)
30
- Chef::JSONCompat.to_json(thing)
31
- else
32
- JSON.dump(thing)
33
- end
34
- end
35
-
36
- # Load JSON data
37
- #
38
- # @param thing [String]
39
- # @return [Object]
40
- def _from_json(thing)
41
- if(try_json_compat)
42
- Chef::JSONCompat.from_json(thing)
43
- else
44
- JSON.read(thing)
45
- end
46
- end
47
-
48
- # Format object into pretty JSON
49
- #
50
- # @param thing [Object]
51
- # @return [String]
52
- def _format_json(thing)
53
- thing = _from_json(thing) if thing.is_a?(String)
54
- if(try_json_compat)
55
- Chef::JSONCompat.to_json_pretty(thing)
56
- else
57
- JSON.pretty_generate(thing)
58
- end
59
- end
60
-
61
- end
62
-
63
- end
64
- end
@@ -1,28 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
-
6
- # Storage helpers
7
- module ObjectStorage
8
-
9
- # Write to file
10
- #
11
- # @param object [Object]
12
- # @param path [String] path to write object
13
- # @param directory [Miasma::Models::Storage::Directory]
14
- # @return [String] file path
15
- def file_store(object, path, directory)
16
- raise NotImplementedError.new 'Internal updated required! :('
17
- content = object.is_a?(String) ? object : Utils._format_json(object)
18
- directory.files.create(
19
- :identity => path,
20
- :body => content
21
- )
22
- loc = directory.service.service.name.split('::').last.downcase
23
- "#{loc}://#{directory.identity}/#{path}"
24
- end
25
-
26
- end
27
- end
28
- end
@@ -1,79 +0,0 @@
1
- require 'knife-cloudformation'
2
-
3
- module KnifeCloudformation
4
- module Utils
5
- # Output Helpers
6
- module Output
7
-
8
- # Process things and return items
9
- #
10
- # @param things [Array] items to process
11
- # @param args [Hash] options
12
- # @option args [TrueClass, FalseClass] :flat flatten result array
13
- # @option args [Array] :attributes attributes to extract
14
- # @todo this was extracted from events and needs to be cleaned up
15
- def process(things, args={})
16
- @event_ids ||= []
17
- processed = things.reverse.map do |thing|
18
- next if @event_ids.include?(thing['id'])
19
- @event_ids.push(thing['id']).compact!
20
- if(args[:attributes])
21
- args[:attributes].map do |key|
22
- thing[key].to_s
23
- end
24
- else
25
- thing.values
26
- end
27
- end
28
- args[:flat] ? processed.flatten : processed
29
- end
30
-
31
- # Generate formatted titles
32
- #
33
- # @param thing [Object] thing being processed
34
- # @param args [Hash]
35
- # @option args [Array] :attributes
36
- # @return [Array<String>] formatted titles
37
- def get_titles(thing, args={})
38
- attrs = args[:attributes] || []
39
- if(attrs.empty?)
40
- hash = thing.is_a?(Array) ? thing.first : thing
41
- hash ||= {}
42
- attrs = hash.keys
43
- end
44
- titles = attrs.map do |key|
45
- camel(key).gsub(/([a-z])([A-Z])/, '\1 \2')
46
- end.compact
47
- if(args[:format])
48
- titles.map{|s| @ui.color(s, :bold)}
49
- else
50
- titles
51
- end
52
- end
53
-
54
- # Output stack related things in nice format
55
- #
56
- # @param stack [String] name of stack
57
- # @param things [Array] things to display
58
- # @param what [String] description of things for output
59
- # @param args [Symbol] options (:ignore_empty_output)
60
- def things_output(stack, things, what, *args)
61
- unless(args.include?(:no_title))
62
- output = get_titles(things, :format => true, :attributes => allowed_attributes)
63
- else
64
- output = []
65
- end
66
- columns = allowed_attributes.size
67
- output += process(things, :flat => true, :attributes => allowed_attributes)
68
- output.compact!
69
- if(output.empty?)
70
- ui.warn 'No information found' unless args.include?(:ignore_empty_output)
71
- else
72
- ui.info "#{what.to_s.capitalize} for stack: #{ui.color(stack, :bold)}" if stack
73
- ui.info "#{ui.list(output, :uneven_columns_across, columns)}"
74
- end
75
- end
76
-
77
- end
78
- end
79
- end