knife-spork 1.7.2 → 1.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +35 -35
  3. data/lib/chef/knife/spork-bump.rb +100 -100
  4. data/lib/chef/knife/spork-check.rb +165 -161
  5. data/lib/chef/knife/spork-databag-create.rb +54 -54
  6. data/lib/chef/knife/spork-databag-delete.rb +51 -51
  7. data/lib/chef/knife/spork-databag-edit.rb +54 -54
  8. data/lib/chef/knife/spork-databag-fromfile.rb +88 -88
  9. data/lib/chef/knife/spork-delete.rb +132 -132
  10. data/lib/chef/knife/spork-environment-check.rb +90 -90
  11. data/lib/chef/knife/spork-environment-create.rb +63 -63
  12. data/lib/chef/knife/spork-environment-delete.rb +38 -38
  13. data/lib/chef/knife/spork-environment-edit.rb +40 -40
  14. data/lib/chef/knife/spork-environment-fromfile.rb +46 -46
  15. data/lib/chef/knife/spork-info.rb +34 -34
  16. data/lib/chef/knife/spork-node-create.rb +41 -41
  17. data/lib/chef/knife/spork-node-delete.rb +41 -41
  18. data/lib/chef/knife/spork-node-edit.rb +48 -48
  19. data/lib/chef/knife/spork-node-fromfile.rb +46 -46
  20. data/lib/chef/knife/spork-node-runlistadd.rb +51 -51
  21. data/lib/chef/knife/spork-node-runlistremove.rb +44 -44
  22. data/lib/chef/knife/spork-node-runlistset.rb +44 -44
  23. data/lib/chef/knife/spork-omni.rb +112 -112
  24. data/lib/chef/knife/spork-promote.rb +197 -197
  25. data/lib/chef/knife/spork-role-create.rb +46 -46
  26. data/lib/chef/knife/spork-role-delete.rb +50 -50
  27. data/lib/chef/knife/spork-role-edit.rb +40 -40
  28. data/lib/chef/knife/spork-role-fromfile.rb +65 -65
  29. data/lib/chef/knife/spork-upload.rb +151 -151
  30. data/lib/chef/knife/spork-version.rb +12 -12
  31. data/lib/knife-spork.rb +3 -3
  32. data/lib/knife-spork/plugins.rb +27 -27
  33. data/lib/knife-spork/plugins/campfire.rb +219 -219
  34. data/lib/knife-spork/plugins/eventinator.rb +329 -329
  35. data/lib/knife-spork/plugins/foodcritic.rb +46 -46
  36. data/lib/knife-spork/plugins/git.rb +393 -399
  37. data/lib/knife-spork/plugins/graphite.rb +25 -25
  38. data/lib/knife-spork/plugins/grove.rb +167 -167
  39. data/lib/knife-spork/plugins/hipchat.rb +171 -171
  40. data/lib/knife-spork/plugins/influxdb.rb +28 -28
  41. data/lib/knife-spork/plugins/irccat.rb +332 -332
  42. data/lib/knife-spork/plugins/jabber.rb +133 -133
  43. data/lib/knife-spork/plugins/plugin.rb +117 -117
  44. data/lib/knife-spork/plugins/rubocop.rb +56 -56
  45. data/lib/knife-spork/plugins/slack.rb +125 -125
  46. data/lib/knife-spork/plugins/statusnet.rb +122 -122
  47. data/lib/knife-spork/runner.rb +342 -342
  48. data/lib/knife-spork/version.rb +5 -5
  49. metadata +4 -51
  50. data/.gitignore +0 -21
  51. data/.ruby-gemset +0 -1
  52. data/.ruby-version +0 -1
  53. data/.travis.yml +0 -3
  54. data/CHANGELOG.md +0 -445
  55. data/Gemfile +0 -3
  56. data/README.md +0 -544
  57. data/Rakefile +0 -35
  58. data/knife-spork.gemspec +0 -28
  59. data/plugins/Campfire.md +0 -43
  60. data/plugins/Eventinator.md +0 -30
  61. data/plugins/Foodcritic.md +0 -53
  62. data/plugins/Git.md +0 -53
  63. data/plugins/Graphite.md +0 -30
  64. data/plugins/Grove.md +0 -31
  65. data/plugins/HipChat.md +0 -69
  66. data/plugins/Influxdb.md +0 -25
  67. data/plugins/Irccat.md +0 -50
  68. data/plugins/Jabber.md +0 -61
  69. data/plugins/README.md +0 -70
  70. data/plugins/Rubocop.md +0 -110
  71. data/plugins/Slack.md +0 -48
  72. data/plugins/StatusNet.md +0 -41
  73. data/plugins/Template.md +0 -34
  74. data/spec/spec_helper.rb +0 -10
  75. data/spec/test_helpers.rb +0 -46
  76. data/spec/unit/fixtures/config/spork-config.yml +0 -1
  77. data/spec/unit/fixtures/cookbooks/example/metadata.rb +0 -8
  78. data/spec/unit/fixtures/environments/example.json +0 -12
  79. data/spec/unit/fixtures/knife.rb +0 -6
  80. data/spec/unit/fixtures/test_client.pem +0 -27
  81. data/spec/unit/spork_bump_spec.rb +0 -75
  82. data/spec/unit/spork_info_spec.rb +0 -40
  83. data/spec/unit/spork_promote_spec.rb +0 -77
  84. data/spec/unit/spork_upload_spec.rb +0 -46
@@ -1,342 +1,342 @@
1
- require 'app_conf'
2
- require 'diffy'
3
- require 'json'
4
-
5
- require 'chef/cookbook_loader'
6
- require 'chef/environment'
7
- require 'chef/data_bag_item'
8
- require 'chef/knife/core/object_loader'
9
- require 'knife-spork/plugins'
10
-
11
- module KnifeSpork
12
- module Runner
13
- module ClassMethods; end
14
-
15
- module InstanceMethods
16
- def spork_config
17
- return @spork_config unless @spork_config.nil?
18
-
19
- @spork_config = AppConf.new
20
- load_paths = [ File.expand_path("#{cookbook_path.gsub('cookbooks','')}/config/spork-config.yml"), File.expand_path('config/spork-config.yml'), '/etc/spork-config.yml', File.expand_path('~/.chef/spork-config.yml'), File.expand_path("#{cookbook_path.gsub('cookbooks','')}/.chef/spork-config.yml") ]
21
- load_paths.each do |load_path|
22
- if File.exists?(load_path)
23
- @spork_config.load(load_path)
24
- end
25
- end
26
-
27
- @spork_config
28
- end
29
-
30
- def run_plugins(hook)
31
- cookbooks = [ @cookbooks || @cookbook ].flatten.compact.collect{|cookbook| cookbook.is_a?(::Chef::CookbookVersion) ? cookbook : load_cookbook(cookbook)}.sort{|a,b| a.name.to_s <=> b.name.to_s}
32
-
33
- # Affects promote only:
34
- # Set loaded cookbook version if the -v or --version parameter was specified
35
- # Otherwise the version on disk, often more recent will be used.
36
- # We know cookbooks will only contain one cookbook in the case of promote.
37
- cookbooks.map{|c|c.version = config[:version]} if config[:version]
38
-
39
- environments = [ @environments || @environment ].flatten.compact.collect{|environment| environment.is_a?(::Chef::Environment) ? environment : load_environment_from_file(environment)}.sort{|a,b| a.name.to_s <=> b.name.to_s}
40
- environment_diffs = @environment_diffs
41
-
42
- KnifeSpork::Plugins.run(
43
- :config => spork_config,
44
- :hook => hook.to_sym,
45
- :cookbooks => cookbooks,
46
- :environments => environments,
47
- :environment_diffs => environment_diffs,
48
- :environment_path => environment_path,
49
- :cookbook_path => cookbook_path,
50
- :object_name => @object_name,
51
- :object_secondary_name => @object_secondary_name,
52
- :object_difference => @object_difference,
53
- :misc_output => @misc_output,
54
- :ui => ui
55
- )
56
- end
57
-
58
- def load_environments_and_cookbook
59
- ensure_environment_and_cookbook_provided!
60
-
61
- if @name_args.size == 2
62
- environments = @name_args[0].split(",").map{ |env| load_specified_environment_group(env) }
63
- [ environments.flatten, @name_args[1] ]
64
- elsif @name_args.size == 1
65
- [ [default_environments].flatten, @name_args[0] ]
66
- end
67
- end
68
-
69
- def verify_and_load_environments
70
- ensure_environment_provided!
71
-
72
- if @name_args.size == 0
73
- default_environments
74
- elsif @name_args.size == 1
75
- [@name_args[0]]
76
- end
77
- end
78
-
79
- def load_specified_environment_group(name)
80
- if !spork_config.environment_groups.nil? && spork_config.environment_groups.keys.include?(name)
81
- spork_config.environment_groups[name]
82
- else
83
- [name]
84
- end
85
- end
86
-
87
- def ensure_environment_and_cookbook_provided!
88
- if default_environments.empty? && @name_args.size < 2
89
- ui.error('You must specify an environment or environment group and a cookbook name')
90
- exit(1)
91
- end
92
- end
93
-
94
- def ensure_environment_provided!
95
- if default_environments.empty? && @name_args.size < 1
96
- ui.error('You must specify an environment or configure default environments.')
97
- exit(1)
98
- end
99
- end
100
-
101
- def default_environments
102
- [ spork_config.default_environment || spork_config.default_environments ].flatten.compact
103
- end
104
-
105
- def pretty_print_json(json)
106
- options = spork_config[:json_options] || {}
107
- # generate requires a hash where the keys are symbols
108
- options = Hash[ options.to_hash.map {|(k,v)| [k.to_sym,v] }] unless options == {}
109
- JSON.pretty_generate(json, options.to_hash)
110
- end
111
-
112
- def save_environment_changes(environment, json)
113
- if spork_config[:environment_path]
114
- environments_path = spork_config[:environment_path]
115
- elsif @config[:environment_path]
116
- # environment_path can be an Array or String. If Array, let's just
117
- # take the first value as we have done in other similar circumstances
118
- environments_path = if @config[:environment_path].is_a? Array
119
- @config[:environment_path].first
120
- else
121
- @config[:environment_path]
122
- end
123
- else
124
- split_cb_path = cookbook_path.split("/")
125
- environments_path = (split_cb_path[0..-2] << split_cb_path[-1].gsub("cookbooks","environments")).join("/")
126
- end
127
-
128
- environment_path = File.expand_path( File.join(environments_path, "#{environment}.json") )
129
-
130
- File.open(environment_path, 'w'){ |f| f.puts(json) }
131
- end
132
-
133
- def valid_version?(version)
134
- version_keys = version.split('.')
135
- return false unless version_keys.size == 3 && version_keys.any?{ |k| begin Float(k); rescue false; else true; end }
136
- true
137
- end
138
-
139
- def validate_version!(version)
140
- if version && !valid_version?(version)
141
- ui.error("#{version} is not a valid version!")
142
- exit(1)
143
- end
144
- end
145
-
146
- def environment_loader
147
- @environment_loader ||= Chef::Knife::Core::ObjectLoader.new(::Chef::Environment, ui)
148
- end
149
-
150
- def role_loader
151
- @role_loader ||= Chef::Knife::Core::ObjectLoader.new(::Chef::Role, ui)
152
- end
153
-
154
- # It's not feasible to try and "guess" which cookbook path to use, so we will
155
- # always just use the first one in the path.
156
- def cookbook_path
157
- ensure_cookbook_path!
158
- [config[:cookbook_path] ||= ::Chef::Config.cookbook_path].flatten[0]
159
- end
160
-
161
- def environment_path
162
- if spork_config[:environment_path]
163
- if spork_config[:environment_path].kind_of?(Array)
164
- spork_config[:environment_path].first
165
- else
166
- spork_config[:environment_path]
167
- end
168
- elsif Chef::Config.environment_path && Chef::Config.environment_path.kind_of?(Array)
169
- Chef::Config.environment_path.first
170
- elsif Chef::Config.environment_path && Chef::Config.environment_path.kind_of?(String)
171
- Chef::Config.environment_path
172
- else
173
- cookbook_path.gsub("/cookbooks","/environments")
174
- end
175
- end
176
-
177
- def role_path
178
- spork_config[:role_path] || cookbook_path.gsub("/cookbooks","/roles")
179
- end
180
-
181
- def all_cookbooks
182
- ::Chef::CookbookLoader.new(::Chef::Config.cookbook_path)
183
- end
184
-
185
- def load_cookbook(name)
186
- return name if name.is_a?(Chef::CookbookVersion)
187
-
188
- cookbook = load_from_chef(name) || load_from_berkshelf(name) || load_from_librarian(name)
189
-
190
- cookbook || raise(Chef::Exceptions::CookbookNotFound,
191
- "Could not find cookbook '#{name}' in any of the sources!")
192
- end
193
-
194
- def load_from_chef(name)
195
- all_cookbooks[name]
196
- rescue Chef::Exceptions::CookbookNotFound,
197
- Chef::Exceptions::CookbookNotFoundInRepo
198
- nil
199
- end
200
-
201
- def load_from_berkshelf(name)
202
- return unless defined?(::Berkshelf)
203
- return unless self.config[:berksfile] && ::File.exist?(self.config[:berksfile])
204
- berksfile = ::Berkshelf::Berksfile.from_file(self.config[:berksfile])
205
- lockfile = ::Berkshelf::Lockfile.new(berksfile)
206
-
207
- raise Berkshelf::BerkshelfError, "LockFileNotFound" unless File.exists?(lockfile.filepath)
208
-
209
- cookbook = Berkshelf.ui.mute {
210
- self.config[:skip_dependencies] ||= false
211
- berksfile.resolve(lockfile.find(name), {skip_dependencies: self.config[:skip_dependencies]})[:solution].first
212
- }
213
-
214
- #convert Berkshelf::CachedCookbook to Chef::CookbookVersion
215
- ::Chef::CookbookLoader.new(File.dirname(cookbook.path))[name]
216
-
217
- end
218
-
219
- # @todo #opensource
220
- def load_from_librarian(name)
221
- # Your code here :)
222
- nil
223
- end
224
-
225
- def load_cookbooks(cookbook_names)
226
- cookbook_names = [cookbook_names].flatten
227
- cookbook_names.collect{ |cookbook_name| load_cookbook(cookbook_name) }
228
- end
229
-
230
-
231
- def load_role_from_file(role_name)
232
- role_loader.object_from_file("#{role_path}/#{role_name}.json")
233
- end
234
-
235
- def load_role(role_name)
236
- Chef::Role.load(role_name)
237
- end
238
-
239
- def load_node(node)
240
- Chef::Node.load(node)
241
- end
242
-
243
- def load_databag(bag)
244
- Chef::DataBag.load(bag)
245
- end
246
-
247
- def load_databag_item(bag, item_name)
248
- Chef::DataBagItem.load(bag, item_name)
249
- end
250
-
251
- def load_environment(environment_name)
252
- Chef::Environment.load(environment_name)
253
- end
254
-
255
- def load_environment_from_file(environment_name)
256
- begin
257
- environment_loader.object_from_file("#{environment_path}/#{environment_name}.json")
258
- rescue FFI_Yajl::ParseError => e
259
- raise "#{environment_name} environment file has syntactically incorrect json.\n #{e.to_s}"
260
- end
261
- end
262
-
263
- def load_remote_environment(environment_name)
264
- begin
265
- Chef::Environment.load(environment_name)
266
- rescue Net::HTTPServerException => e
267
- ui.error "Could not load #{environment_name} from Chef Server. You must upload the environment manually the first time."
268
- exit(1)
269
- end
270
- end
271
-
272
- def environment_diff(local_environment, remote_environment)
273
- local_environment_versions = local_environment.to_hash['cookbook_versions']
274
- remote_environment_versions = remote_environment.to_hash['cookbook_versions']
275
- hash_diff remote_environment_versions, local_environment_versions
276
- end
277
-
278
- def json_diff(a, b)
279
- pre_json = JSON.parse(a.respond_to?(:to_json) ? a.to_json : a)
280
- post_json = JSON.parse(b.respond_to?(:to_json) ? b.to_json : b)
281
- diff = Diffy::Diff.new(JSON.pretty_generate(pre_json), JSON.pretty_generate(post_json), :diff=>"-U 3")
282
- if spork_config.stdout_diffs
283
- ui.info "Diff:"
284
- ui.info diff.to_s(:color)
285
- end
286
- return diff.to_s.gsub(/[()]/, '\\\\\0')
287
- end
288
-
289
- def hash_diff(hash, other)
290
- hash.keys.inject({}) do |memo, key|
291
- unless hash[key] == other[key]
292
- memo[key] = "#{hash[key]} changed to #{other[key]}"
293
- end
294
- memo
295
- end
296
- end
297
-
298
- def constraints_diff (environment_diff)
299
- Hash[Hash[environment_diff.map{|k,v| [k, v.split(" changed to ").map{|x|x.gsub("= ","")}]}].map{|k,v|[k,calc_diff(k,v)]}]
300
- end
301
-
302
- def calc_diff(cookbook, version)
303
- components = version.map{|v|v.split(".")}
304
-
305
- if components.length < 2
306
- ui.warn "#{cookbook} has no remote version to diff against!"
307
- return 0
308
- end
309
-
310
- if components[1][0].to_i != components[0][0].to_i
311
- return (components[1][0].to_i - components[0][0].to_i)*100
312
- elsif components[1][1].to_i != components[0][1].to_i
313
- return (components[1][1].to_i - components[0][1].to_i)*10
314
- else
315
- return (components[1][2].to_i - components[0][2].to_i)
316
- end
317
- end
318
-
319
- def ensure_cookbook_path!
320
- if config[:cookbook_path].nil?
321
- ui.fatal "No default cookbook_path; Specify with -o or fix your knife.rb."
322
- show_usage
323
- exit(1)
324
- end
325
- end
326
-
327
- def unload_berkshelf_if_specified
328
- # Temporary fix for #138 to allow Berkshelf functionality
329
- # to be bypassed until #85 has been completed and Berkshelf 3 support added
330
- if spork_config.skip_berkshelf
331
- ui.warn "Unloading Berkshelf as skip_berkshelf option found in config"
332
- Object.send(:remove_const, :Berkshelf) if defined?(::Berkshelf)
333
- end
334
- end
335
- end
336
-
337
- def self.included(receiver)
338
- receiver.extend(ClassMethods)
339
- receiver.send(:include, InstanceMethods)
340
- end
341
- end
342
- end
1
+ require 'app_conf'
2
+ require 'diffy'
3
+ require 'json'
4
+
5
+ require 'chef/cookbook_loader'
6
+ require 'chef/environment'
7
+ require 'chef/data_bag_item'
8
+ require 'chef/knife/core/object_loader'
9
+ require 'knife-spork/plugins'
10
+
11
+ module KnifeSpork
12
+ module Runner
13
+ module ClassMethods; end
14
+
15
+ module InstanceMethods
16
+ def spork_config
17
+ return @spork_config unless @spork_config.nil?
18
+
19
+ @spork_config = AppConf.new
20
+ load_paths = [ File.expand_path("#{cookbook_path.gsub('cookbooks','')}/config/spork-config.yml"), File.expand_path('config/spork-config.yml'), '/etc/spork-config.yml', File.expand_path('~/.chef/spork-config.yml'), File.expand_path("#{cookbook_path.gsub('cookbooks','')}/.chef/spork-config.yml") ]
21
+ load_paths.each do |load_path|
22
+ if File.exists?(load_path)
23
+ @spork_config.load(load_path)
24
+ end
25
+ end
26
+
27
+ @spork_config
28
+ end
29
+
30
+ def run_plugins(hook)
31
+ cookbooks = [ @cookbooks || @cookbook ].flatten.compact.collect{|cookbook| cookbook.is_a?(::Chef::CookbookVersion) ? cookbook : load_cookbook(cookbook)}.sort{|a,b| a.name.to_s <=> b.name.to_s}
32
+
33
+ # Affects promote only:
34
+ # Set loaded cookbook version if the -v or --version parameter was specified
35
+ # Otherwise the version on disk, often more recent will be used.
36
+ # We know cookbooks will only contain one cookbook in the case of promote.
37
+ cookbooks.map{|c|c.version = config[:version]} if config[:version]
38
+
39
+ environments = [ @environments || @environment ].flatten.compact.collect{|environment| environment.is_a?(::Chef::Environment) ? environment : load_environment_from_file(environment)}.sort{|a,b| a.name.to_s <=> b.name.to_s}
40
+ environment_diffs = @environment_diffs
41
+
42
+ KnifeSpork::Plugins.run(
43
+ :config => spork_config,
44
+ :hook => hook.to_sym,
45
+ :cookbooks => cookbooks,
46
+ :environments => environments,
47
+ :environment_diffs => environment_diffs,
48
+ :environment_path => environment_path,
49
+ :cookbook_path => cookbook_path,
50
+ :object_name => @object_name,
51
+ :object_secondary_name => @object_secondary_name,
52
+ :object_difference => @object_difference,
53
+ :misc_output => @misc_output,
54
+ :ui => ui
55
+ )
56
+ end
57
+
58
+ def load_environments_and_cookbook
59
+ ensure_environment_and_cookbook_provided!
60
+
61
+ if @name_args.size == 2
62
+ environments = @name_args[0].split(",").map{ |env| load_specified_environment_group(env) }
63
+ [ environments.flatten, @name_args[1] ]
64
+ elsif @name_args.size == 1
65
+ [ [default_environments].flatten, @name_args[0] ]
66
+ end
67
+ end
68
+
69
+ def verify_and_load_environments
70
+ ensure_environment_provided!
71
+
72
+ if @name_args.size == 0
73
+ default_environments
74
+ elsif @name_args.size == 1
75
+ [@name_args[0]]
76
+ end
77
+ end
78
+
79
+ def load_specified_environment_group(name)
80
+ if !spork_config.environment_groups.nil? && spork_config.environment_groups.keys.include?(name)
81
+ spork_config.environment_groups[name]
82
+ else
83
+ [name]
84
+ end
85
+ end
86
+
87
+ def ensure_environment_and_cookbook_provided!
88
+ if default_environments.empty? && @name_args.size < 2
89
+ ui.error('You must specify an environment or environment group and a cookbook name')
90
+ exit(1)
91
+ end
92
+ end
93
+
94
+ def ensure_environment_provided!
95
+ if default_environments.empty? && @name_args.size < 1
96
+ ui.error('You must specify an environment or configure default environments.')
97
+ exit(1)
98
+ end
99
+ end
100
+
101
+ def default_environments
102
+ [ spork_config.default_environment || spork_config.default_environments ].flatten.compact
103
+ end
104
+
105
+ def pretty_print_json(json)
106
+ options = spork_config[:json_options] || {}
107
+ # generate requires a hash where the keys are symbols
108
+ options = Hash[ options.to_hash.map {|(k,v)| [k.to_sym,v] }] unless options == {}
109
+ JSON.pretty_generate(json, options.to_hash)
110
+ end
111
+
112
+ def save_environment_changes(environment, json)
113
+ if spork_config[:environment_path]
114
+ environments_path = spork_config[:environment_path]
115
+ elsif @config[:environment_path]
116
+ # environment_path can be an Array or String. If Array, let's just
117
+ # take the first value as we have done in other similar circumstances
118
+ environments_path = if @config[:environment_path].is_a? Array
119
+ @config[:environment_path].first
120
+ else
121
+ @config[:environment_path]
122
+ end
123
+ else
124
+ split_cb_path = cookbook_path.split("/")
125
+ environments_path = (split_cb_path[0..-2] << split_cb_path[-1].gsub("cookbooks","environments")).join("/")
126
+ end
127
+
128
+ environment_path = File.expand_path( File.join(environments_path, "#{environment}.json") )
129
+
130
+ File.open(environment_path, 'w'){ |f| f.puts(json) }
131
+ end
132
+
133
+ def valid_version?(version)
134
+ version_keys = version.split('.')
135
+ return false unless version_keys.size == 3 && version_keys.any?{ |k| begin Float(k); rescue false; else true; end }
136
+ true
137
+ end
138
+
139
+ def validate_version!(version)
140
+ if version && !valid_version?(version)
141
+ ui.error("#{version} is not a valid version!")
142
+ exit(1)
143
+ end
144
+ end
145
+
146
+ def environment_loader
147
+ @environment_loader ||= Chef::Knife::Core::ObjectLoader.new(::Chef::Environment, ui)
148
+ end
149
+
150
+ def role_loader
151
+ @role_loader ||= Chef::Knife::Core::ObjectLoader.new(::Chef::Role, ui)
152
+ end
153
+
154
+ # It's not feasible to try and "guess" which cookbook path to use, so we will
155
+ # always just use the first one in the path.
156
+ def cookbook_path
157
+ ensure_cookbook_path!
158
+ [config[:cookbook_path] ||= ::Chef::Config.cookbook_path].flatten[0]
159
+ end
160
+
161
+ def environment_path
162
+ if spork_config[:environment_path]
163
+ if spork_config[:environment_path].kind_of?(Array)
164
+ spork_config[:environment_path].first
165
+ else
166
+ spork_config[:environment_path]
167
+ end
168
+ elsif Chef::Config.environment_path && Chef::Config.environment_path.kind_of?(Array)
169
+ Chef::Config.environment_path.first
170
+ elsif Chef::Config.environment_path && Chef::Config.environment_path.kind_of?(String)
171
+ Chef::Config.environment_path
172
+ else
173
+ cookbook_path.gsub("/cookbooks","/environments")
174
+ end
175
+ end
176
+
177
+ def role_path
178
+ spork_config[:role_path] || cookbook_path.gsub("/cookbooks","/roles")
179
+ end
180
+
181
+ def all_cookbooks
182
+ ::Chef::CookbookLoader.new(::Chef::Config.cookbook_path)
183
+ end
184
+
185
+ def load_cookbook(name)
186
+ return name if name.is_a?(Chef::CookbookVersion)
187
+
188
+ cookbook = load_from_chef(name) || load_from_berkshelf(name) || load_from_librarian(name)
189
+
190
+ cookbook || raise(Chef::Exceptions::CookbookNotFound,
191
+ "Could not find cookbook '#{name}' in any of the sources!")
192
+ end
193
+
194
+ def load_from_chef(name)
195
+ all_cookbooks[name]
196
+ rescue Chef::Exceptions::CookbookNotFound,
197
+ Chef::Exceptions::CookbookNotFoundInRepo
198
+ nil
199
+ end
200
+
201
+ def load_from_berkshelf(name)
202
+ return unless defined?(::Berkshelf)
203
+ return unless self.config[:berksfile] && ::File.exist?(self.config[:berksfile])
204
+ berksfile = ::Berkshelf::Berksfile.from_file(self.config[:berksfile])
205
+ lockfile = ::Berkshelf::Lockfile.new(berksfile)
206
+
207
+ raise Berkshelf::BerkshelfError, "LockFileNotFound" unless File.exists?(lockfile.filepath)
208
+
209
+ cookbook = Berkshelf.ui.mute {
210
+ self.config[:skip_dependencies] ||= false
211
+ berksfile.resolve(lockfile.find(name), {skip_dependencies: self.config[:skip_dependencies]})[:solution].first
212
+ }
213
+
214
+ #convert Berkshelf::CachedCookbook to Chef::CookbookVersion
215
+ ::Chef::CookbookLoader.new(File.dirname(cookbook.path))[name]
216
+
217
+ end
218
+
219
+ # @todo #opensource
220
+ def load_from_librarian(name)
221
+ # Your code here :)
222
+ nil
223
+ end
224
+
225
+ def load_cookbooks(cookbook_names)
226
+ cookbook_names = [cookbook_names].flatten
227
+ cookbook_names.collect{ |cookbook_name| load_cookbook(cookbook_name) }
228
+ end
229
+
230
+
231
+ def load_role_from_file(role_name)
232
+ role_loader.object_from_file("#{role_path}/#{role_name}.json")
233
+ end
234
+
235
+ def load_role(role_name)
236
+ Chef::Role.load(role_name)
237
+ end
238
+
239
+ def load_node(node)
240
+ Chef::Node.load(node)
241
+ end
242
+
243
+ def load_databag(bag)
244
+ Chef::DataBag.load(bag)
245
+ end
246
+
247
+ def load_databag_item(bag, item_name)
248
+ Chef::DataBagItem.load(bag, item_name)
249
+ end
250
+
251
+ def load_environment(environment_name)
252
+ Chef::Environment.load(environment_name)
253
+ end
254
+
255
+ def load_environment_from_file(environment_name)
256
+ begin
257
+ environment_loader.object_from_file("#{environment_path}/#{environment_name}.json")
258
+ rescue FFI_Yajl::ParseError => e
259
+ raise "#{environment_name} environment file has syntactically incorrect json.\n #{e.to_s}"
260
+ end
261
+ end
262
+
263
+ def load_remote_environment(environment_name)
264
+ begin
265
+ Chef::Environment.load(environment_name)
266
+ rescue Net::HTTPServerException => e
267
+ ui.error "Could not load #{environment_name} from Chef Server. You must upload the environment manually the first time."
268
+ exit(1)
269
+ end
270
+ end
271
+
272
+ def environment_diff(local_environment, remote_environment)
273
+ local_environment_versions = local_environment.to_hash['cookbook_versions']
274
+ remote_environment_versions = remote_environment.to_hash['cookbook_versions']
275
+ hash_diff remote_environment_versions, local_environment_versions
276
+ end
277
+
278
+ def json_diff(a, b)
279
+ pre_json = JSON.parse(a.respond_to?(:to_json) ? a.to_json : a)
280
+ post_json = JSON.parse(b.respond_to?(:to_json) ? b.to_json : b)
281
+ diff = Diffy::Diff.new(JSON.pretty_generate(pre_json), JSON.pretty_generate(post_json), :diff=>"-U 3")
282
+ if spork_config.stdout_diffs
283
+ ui.info "Diff:"
284
+ ui.info diff.to_s(:color)
285
+ end
286
+ return diff.to_s.gsub(/[()]/, '\\\\\0')
287
+ end
288
+
289
+ def hash_diff(hash, other)
290
+ hash.keys.inject({}) do |memo, key|
291
+ unless hash[key] == other[key]
292
+ memo[key] = "#{hash[key]} changed to #{other[key]}"
293
+ end
294
+ memo
295
+ end
296
+ end
297
+
298
+ def constraints_diff (environment_diff)
299
+ Hash[Hash[environment_diff.map{|k,v| [k, v.split(" changed to ").map{|x|x.gsub("= ","")}]}].map{|k,v|[k,calc_diff(k,v)]}]
300
+ end
301
+
302
+ def calc_diff(cookbook, version)
303
+ components = version.map{|v|v.split(".")}
304
+
305
+ if components.length < 2
306
+ ui.warn "#{cookbook} has no remote version to diff against!"
307
+ return 0
308
+ end
309
+
310
+ if components[1][0].to_i != components[0][0].to_i
311
+ return (components[1][0].to_i - components[0][0].to_i)*100
312
+ elsif components[1][1].to_i != components[0][1].to_i
313
+ return (components[1][1].to_i - components[0][1].to_i)*10
314
+ else
315
+ return (components[1][2].to_i - components[0][2].to_i)
316
+ end
317
+ end
318
+
319
+ def ensure_cookbook_path!
320
+ if config[:cookbook_path].nil?
321
+ ui.fatal "No default cookbook_path; Specify with -o or fix your knife.rb."
322
+ show_usage
323
+ exit(1)
324
+ end
325
+ end
326
+
327
+ def unload_berkshelf_if_specified
328
+ # Temporary fix for #138 to allow Berkshelf functionality
329
+ # to be bypassed until #85 has been completed and Berkshelf 3 support added
330
+ if spork_config.skip_berkshelf
331
+ ui.warn "Unloading Berkshelf as skip_berkshelf option found in config"
332
+ Object.send(:remove_const, :Berkshelf) if defined?(::Berkshelf)
333
+ end
334
+ end
335
+ end
336
+
337
+ def self.included(receiver)
338
+ receiver.extend(ClassMethods)
339
+ receiver.send(:include, InstanceMethods)
340
+ end
341
+ end
342
+ end