knife-spork 1.3.2 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NzAyZmY2MjljNzA5ZDRkOWQ4MTE4MWNiZGNmZjE1NjQ5MzA4MDg4Zg==
4
+ MDgxNDk5MzE2Mjc3NDc4NjVlOWNhYmExOTQyZDlmNjhkZTc1NDcyZg==
5
5
  data.tar.gz: !binary |-
6
- ZGU1NWM1NDgxMjFiODRjYTM4NmY0ZjkwZDUyZGI3Mzk4M2NkMDdjMg==
6
+ YzE1ZWVmZGQwMTJiYTA2ZjIyNTU4YjU4OTQ5N2Y5YTM2MGJmZTMxZg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzY1ZDU4NDRmMzgzNmY2NzEzOTI0YjIzYTNkYmUxNTY1MDYyY2Y0Mjc5ZTY1
10
- ZmJiYjcyZTU2NDJkMTk0YTdkOWIxZTdlNmVjNWU3Yjg3ZWRlMzU1ZWZkYzk1
11
- NTI4MTdiYTZiZmY1OTg4M2QzMTMxOTQ0YTY4NjU2Y2VhMjg4NTg=
9
+ MjVmNjkxMDQ1OTJlZTZhOTg4OWNhNmY1MjFkNDM5MGZhOWNhN2U4ZTAxZGFi
10
+ ZGI4YWEzZWQ1NDU4ZjBkNmMwYmIyYmJhNzg0MWU3MjFlNDVhMTcwNjVkZDA2
11
+ NDVjYWJkYmJlNjJkNTYzYTdhYTczMDBmMjUyMzdlYjEyNzNkOTc=
12
12
  data.tar.gz: !binary |-
13
- YTIyMDQwODRmN2QzMGQ1ODFiYWIzNTZhMWRkZjU5MGVmNGQ1MGYwZDhkZWI4
14
- ZmRmZDc5OGI0ZGE1YmI2YTM3ZjRkYjVjNjJiNjA3ODY3OTRkMDVjMjM3OGEw
15
- ZGQ0ZTg2NDViZTA4MTQ1ZGM0ZmY1Nzg0Y2EzZDY2MGZiZTM2YTk=
13
+ Yjg3MTg2YWM4YjBlNzA4NDA5YjkyYThlMmQ3YjdiZTU5ZTA3MWFiZGJlMDAx
14
+ NWQ5NjZiODVhMGIwMTA2MjkzMGU0NmQ2ODNiYTIyYjc4YWU5ZWVkOWQ3ZjIw
15
+ N2M4MjVmZmEzNzQwOGVhZTc4YjQ5ZmUzZmVkYTEzYThlOTZmOGM=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 1.3.3 (nth May, 2014)
2
+
3
+ Features:
4
+ - Added new preserve_constraint_operators config flag to make spork promote preserve existing version constraint operators (https://github.com/jonlives/knife-spork/issues/101)
5
+ - Have runner check Chef::Config for environment_path (Thanks to @cstewart87 https://github.com/jonlives/knife-spork/pull/114)
6
+ - Have spork check autobump when -y option given (Thanks to @slingcode https://github.com/jonlives/knife-spork/pull/108)
7
+ - Add ability to pass options to JSON.pretty_generate (Thanks to @halcyonCorsair https://github.com/jonlives/knife-spork/pull/105)
8
+ - Spork check environment command to validate constraints specified in environments (Thanks to @jperry https://github.com/jonlives/knife-spork/pull/115)
9
+
10
+ Bugfixes:
11
+ - Fix exception when trying to load non existent role or env from file (Thanks to @jperry https://github.com/jonlives/knife-spork/pull/116)
12
+ - Fix incorrect error message when uploading frozen cookbook (https://github.com/jonlives/knife-spork/issues/117)
13
+ - Fix invalid API endpoint in cookbook upload check when environment specified in knife.rb (https://github.com/jonlives/knife-spork/issues/106)
14
+
1
15
  ## 1.3.2 (5th Feb, 2014)
2
16
 
3
17
  Features:
data/README.md CHANGED
@@ -47,10 +47,13 @@ environment_groups:
47
47
  - user_testing
48
48
  - acceptance_testing
49
49
  version_change_threshold: 2
50
+ preserve_constraint_operators: true
50
51
  environment_path: "/home/me/environments"
51
52
  role_path: "/home/me/roles"
52
53
  custom_plugin_path: "/home/me/spork-plugins"
53
54
  always_promote_remote: true
55
+ json_options:
56
+ indent: " "
54
57
  plugins:
55
58
  campfire:
56
59
  account: myaccount
@@ -96,9 +99,14 @@ The `environment_groups` directive allows you to specify a list of environments
96
99
  #### Version Change Threshold
97
100
  The `version_change_threshold` directive allows you to customise the threshold used by a safety check in spork promote which will prompt for confirmation if you're promoting a cookbook by more than version_change_threshold versions. This defaults to 2 if not set, ie promoting a cookbook from v1.0.1 to v 1.0.2 will not trip this check, wheras promoting from v1.0.1 to v1.0.3 will.
98
101
 
102
+ #### Preserve Constraint Operators
103
+ The `preserve_constraint_operators` directive causes spork promote to preserve existing version constraint operators in your environment files, only updating the version number. This directive is disabled by default, which causes spork to always use the `=` constraint.
104
+
99
105
  #### Always Promote Remote
100
106
  The `always_promote_remote` directive allows you to tell spork promote to always act as if the --remote option had been specified. This will also have the same effect on spork omni. This option should only be used if you're sure you want all changes to be uploaded to the server as soon as you run promote.
101
107
 
108
+ #### JSON Options
109
+ The `json_options` directive allows you to tell spork to pass options to [pretty_generate](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#method-i-pretty_generate) to control the format of the resulting json
102
110
 
103
111
  #### Environment Path
104
112
  The `environment_path` allows you to specify the path to where you store your chef environment json files. If this parameter is not specified, spork will default to using the first element of your cookbook_path, replacing the word "cookbooks" with "environments"
@@ -365,6 +373,59 @@ Saving changes to development.json
365
373
  Promotion complete. Don't forget to upload your changed development.json to Chef Server
366
374
  ```
367
375
 
376
+ Spork Environnent Check
377
+ -------------
378
+ Environment check provides the ability to validate a local chef environment file is locked to versions that actually exist on the chef server. Running this check prior to uploading your environment files is recommended as it can prevent your chef server from becoming unresponsive due to a version constraint that will never be valid.
379
+
380
+ If you run environment check with no options it will collect all invalid cookbook versions before reporting a failure.
381
+
382
+ Alternatively, you can specify any of the following options:
383
+
384
+ ```-f, --fatal```: Quit on first invalid constraint located
385
+
386
+ #### Usage
387
+
388
+ ```bash
389
+ knife spork environment check ENVIRONMENT (options)
390
+ ```
391
+
392
+ #### Example of a passing chef environment check with no options
393
+
394
+ ```text
395
+ $ knife spork environment check production
396
+
397
+ Checking constraints for environment: production
398
+ Environment production looks good
399
+ ```
400
+
401
+ #### Example of multiple invalid cookbooks with no options
402
+
403
+ ```text
404
+ $ knife spork environment check production
405
+
406
+ Checking constraints for environment: production
407
+ ERROR: mysql@10.2.0 does not exist on Chef Server! Upload the cookbook first by running:
408
+
409
+ knife spork upload mysql
410
+
411
+ ERROR: rbenv@10.7.1 does not exist on Chef Server! Upload the cookbook first by running:
412
+
413
+ knife spork upload rbenv
414
+
415
+ FATAL: Environment production has constraints that point to non existent cookbook versions.
416
+ ```
417
+
418
+ #### Example of running with the --fatal flag with the same invalid cookbooks from previous example
419
+
420
+ ```text
421
+ $ knife spork environment check production
422
+
423
+ Checking constraints for environment: production
424
+ FATAL: mysql@10.2.0 does not exist on Chef Server! Upload the cookbook first by running:
425
+
426
+ knife spork upload mysql
427
+ ```
428
+
368
429
  Spork Node / Role / Databag Commands
369
430
  -------------
370
431
 
data/knife-spork.gemspec CHANGED
@@ -2,12 +2,13 @@ $:.push File.expand_path('../lib', __FILE__)
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'knife-spork'
5
- gem.version = '1.3.2'
5
+ gem.version = '1.3.3'
6
6
  gem.authors = ["Jon Cowie"]
7
7
  gem.email = 'jonlives@gmail.com'
8
8
  gem.homepage = 'https://github.com/jonlives/knife-spork'
9
+ gem.licenses = ['GPL']
9
10
  gem.summary = "A workflow plugin to help many devs work with the same chef repo/server"
10
- gem.description = "A workflow plugin to help many devs work with the same chef repo/server"
11
+ gem.description = "KnifeSpork is a workflow plugin for Chef::Knife which helps multiple developers work on the same Chef Server and repository without treading on each other's toes. This plugin was designed around the workflow we have here at Etsy, where several people are working on the Chef repository and Chef Server simultaneously."
11
12
 
12
13
  gem.files = `git ls-files`.split($\)
13
14
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -1,9 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkBump < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  TYPE_INDEX = { :major => 0, :minor => 1, :patch => 2, :manual => 3 }.freeze
9
11
 
@@ -30,6 +32,7 @@ module KnifeSpork
30
32
  banner 'knife spork bump COOKBOOK [major|minor|patch|manual]'
31
33
 
32
34
  def run
35
+ self.class.send(:include, KnifeSpork::Runner)
33
36
  self.config = Chef::Config.merge!(config)
34
37
  config[:cookbook_path] ||= Chef::Config[:cookbook_path]
35
38
 
@@ -51,6 +54,7 @@ module KnifeSpork
51
54
  end
52
55
 
53
56
  private
57
+
54
58
  def bump
55
59
  old_version = @cookbook.version
56
60
 
@@ -1,9 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkCheck < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork check COOKBOOK (options)'
9
11
 
@@ -11,10 +13,10 @@ module KnifeSpork
11
13
  :short => '--a',
12
14
  :long => '--all',
13
15
  :description => 'Show all uploaded versions of the cookbook'
14
-
15
- option :fail,
16
- :long => "--fail",
17
- :description => "If the check fails exit with non-zero exit code"
16
+
17
+ option :fail,
18
+ :long => "--fail",
19
+ :description => "If the check fails exit with non-zero exit code"
18
20
 
19
21
  option :cookbook_path,
20
22
  :short => '-o PATH:PATH',
@@ -37,6 +39,7 @@ module KnifeSpork
37
39
  end
38
40
 
39
41
  def run
42
+ self.class.send(:include, KnifeSpork::Runner)
40
43
  self.config = Chef::Config.merge!(config)
41
44
 
42
45
  if name_args.empty?
@@ -78,14 +81,20 @@ module KnifeSpork
78
81
  if remote_version == local_version
79
82
  if frozen?(remote_version)
80
83
  message = "Your local version (#{local_version}) is frozen on the remote server. You'll need to bump before you can upload."
84
+ message_autobump = "Your local version (#{local_version}) is frozen on the remote server. Autobumping so you can upload."
81
85
  if config[:fail]
82
86
  fail_and_exit("#{message}")
83
87
  else
84
- ui.warn("#{message}")
85
- answer = ui.ask("Would you like to perform a patch-level bump on the #{@cookbook.name} cookbook now? (Y/N)")
86
- if answer == "Y" or answer == "y"
88
+ answer = nil
89
+ unless config[:yes]
90
+ ui.warn("#{message}")
91
+ answer = ui.ask("Would you like to perform a patch-level bump on the #{@cookbook.name} cookbook now? (Y/N)")
92
+ else
93
+ ui.warn message_autobump
94
+ end
95
+ if config[:yes] or answer == "Y" or answer == "y"
87
96
  bump = SporkBump.new
88
- bump.name_args = [@cookbook.name]
97
+ bump.name_args = [@cookbook.name,"patch"]
89
98
  bump.run
90
99
  else
91
100
  ui.info "Skipping bump..."
@@ -1,12 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
- require 'json'
4
2
 
5
3
  module KnifeSpork
6
4
  class SporkDataBagCreate < Chef::Knife
7
- include KnifeSpork::Runner
8
5
 
9
6
  deps do
7
+ require 'knife-spork/runner'
8
+ require 'json'
10
9
  require 'chef/knife/data_bag_create'
11
10
  end
12
11
 
@@ -22,6 +21,7 @@ module KnifeSpork
22
21
  :description => "A file containing the secret key to use to encrypt data bag item values"
23
22
 
24
23
  def run
24
+ self.class.send(:include, KnifeSpork::Runner)
25
25
  self.config = Chef::Config.merge!(config)
26
26
 
27
27
  if @name_args.nil?
@@ -1,12 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
- require 'json'
4
2
 
5
3
  module KnifeSpork
6
4
  class SporkDataBagDelete < Chef::Knife
7
- include KnifeSpork::Runner
8
5
 
9
6
  deps do
7
+ require 'knife-spork/runner'
8
+ require 'json'
10
9
  require 'chef/knife/data_bag_delete'
11
10
  end
12
11
 
@@ -14,6 +13,7 @@ module KnifeSpork
14
13
 
15
14
 
16
15
  def run
16
+ self.class.send(:include, KnifeSpork::Runner)
17
17
  self.config = Chef::Config.merge!(config)
18
18
 
19
19
  if @name_args.length == 2
@@ -1,12 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
- require 'json'
4
2
 
5
3
  module KnifeSpork
6
4
  class SporkDataBagEdit < Chef::Knife
7
- include KnifeSpork::Runner
8
5
 
9
6
  deps do
7
+ require 'knife-spork/runner'
8
+ require 'json'
10
9
  require 'chef/knife/data_bag_edit'
11
10
  end
12
11
 
@@ -22,6 +21,7 @@ module KnifeSpork
22
21
  :description => "A file containing the secret key to use to encrypt data bag item values"
23
22
 
24
23
  def run
24
+ self.class.send(:include, KnifeSpork::Runner)
25
25
  self.config = Chef::Config.merge!(config)
26
26
 
27
27
  if @name_args.length != 2
@@ -1,12 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
- require 'json'
4
2
 
5
3
  module KnifeSpork
6
4
  class SporkDataBagFromFile < Chef::Knife
7
- include KnifeSpork::Runner
8
5
 
9
6
  deps do
7
+ require 'knife-spork/runner'
8
+ require 'json'
10
9
  require 'chef/knife/data_bag_from_file'
11
10
  end
12
11
 
@@ -27,6 +26,7 @@ module KnifeSpork
27
26
  :description => "Upload all data bags"
28
27
 
29
28
  def run
29
+ self.class.send(:include, KnifeSpork::Runner)
30
30
  self.config = Chef::Config.merge!(config)
31
31
 
32
32
  @object_name = @name_args.first
@@ -0,0 +1,90 @@
1
+ require 'chef/knife'
2
+
3
+ module KnifeSpork
4
+ class SporkEnvironmentCheck < Chef::Knife
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ require 'chef/exceptions'
9
+ end
10
+
11
+ banner 'knife spork environment check ENVIRONMENT (options)'
12
+
13
+ option :fatal,
14
+ :short => '-f',
15
+ :long => '--fatal',
16
+ :description => 'Quit on first invalid constraint located'
17
+
18
+ def run
19
+ self.class.send(:include, KnifeSpork::Runner)
20
+ self.config = Chef::Config.merge!(config)
21
+
22
+ #First load so plugins etc know what to work with
23
+ @environments = verify_and_load_environments
24
+
25
+ run_plugins(:before_environmentcheck)
26
+
27
+ #Reload cookbook and env in case a VCS plugin found updates
28
+ @environments = verify_and_load_environments
29
+
30
+ check_environments
31
+ run_plugins(:after_environmentcheck)
32
+ end
33
+
34
+ private
35
+
36
+ def check_environments
37
+ @environments.each do |e|
38
+ env_status = true
39
+ ui.info "\nChecking constraints for environment: #{e}\n"
40
+ environment = load_environment_from_file(e)
41
+ cookbook_versions = environment.cookbook_versions
42
+
43
+ cookbook_versions.each do |cookbook, version_constraint|
44
+ vc = Chef::VersionConstraint.new(version_constraint)
45
+ status = check_cookbook_uploaded(environment, cookbook, vc.version)
46
+ if !status
47
+ fail_and_exit(cookbook, vc.version)
48
+ env_status = status
49
+ end
50
+ end
51
+
52
+ if env_status
53
+ ui.msg "Environment #{e} looks good"
54
+ else
55
+ ui.fatal "Environment #{e} has constraints that point to non existent cookbook versions."
56
+ exit 1
57
+ end
58
+ end
59
+ end
60
+
61
+ def check_cookbook_uploaded(environment, cookbook_name, version)
62
+ api_endpoint = environment ? "environments/#{environment}/cookbooks/#{cookbook_name}" : "cookbooks/#{cookbook_name}"
63
+
64
+ begin
65
+ cookbook = rest.get_rest(api_endpoint)
66
+ results = cookbook[cookbook_name]['versions'].any? do |cv|
67
+ cv['version'] == version.to_s
68
+ end
69
+
70
+ if results
71
+ return true
72
+ else
73
+ return false
74
+ end
75
+ rescue Net::HTTPServerException
76
+ false
77
+ end
78
+ end
79
+
80
+ def fail_and_exit(cookbook_name, version)
81
+ message = "#{cookbook_name}@#{version} does not exist on Chef Server! Upload the cookbook first by running:\n\n\tknife spork upload #{cookbook_name}\n\n"
82
+ if config[:fatal]
83
+ ui.fatal message
84
+ exit 1
85
+ else
86
+ ui.error message
87
+ end
88
+ end
89
+ end
90
+ end
@@ -1,9 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkEnvironmentCreate < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork environment create ENVIRONMENT (options)'
9
11
 
@@ -13,6 +15,7 @@ module KnifeSpork
13
15
  :description => "The environment description"
14
16
 
15
17
  def run
18
+ self.class.send(:include, KnifeSpork::Runner)
16
19
  self.config = Chef::Config.merge!(config)
17
20
 
18
21
  if @name_args.empty?
@@ -1,13 +1,15 @@
1
- require 'chef/knife'
2
- require 'knife-spork/runner'
3
-
4
1
  module KnifeSpork
5
2
  class SporkEnvironmentDelete < Chef::Knife
6
- include KnifeSpork::Runner
3
+
4
+ deps do
5
+ require 'chef/knife'
6
+ require 'knife-spork/runner'
7
+ end
7
8
 
8
9
  banner 'knife spork environment delete ENVIRONMENT (options)'
9
10
 
10
11
  def run
12
+ self.class.send(:include, KnifeSpork::Runner)
11
13
  self.config = Chef::Config.merge!(config)
12
14
 
13
15
  if @name_args.empty?
@@ -1,13 +1,16 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkEnvironmentEdit < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork environment edit ENVIRONMENT (options)'
9
11
 
10
12
  def run
13
+ self.class.send(:include, KnifeSpork::Runner)
11
14
  self.config = Chef::Config.merge!(config)
12
15
 
13
16
  if @name_args.empty?
@@ -1,18 +1,18 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
- require 'json'
4
2
 
5
3
  module KnifeSpork
6
4
  class SporkEnvironmentFromFile < Chef::Knife
7
- include KnifeSpork::Runner
8
5
 
9
6
  deps do
7
+ require 'knife-spork/runner'
8
+ require 'json'
10
9
  require 'chef/knife/environment_from_file'
11
10
  end
12
11
 
13
12
  banner 'knife spork environment from file FILENAME (options)'
14
13
 
15
14
  def run
15
+ self.class.send(:include, KnifeSpork::Runner)
16
16
  self.config = Chef::Config.merge!(config)
17
17
 
18
18
  if @name_args.empty?
@@ -22,13 +22,17 @@ module KnifeSpork
22
22
  end
23
23
 
24
24
  @name_args.each do |arg|
25
- @object_name = arg.split("/").last
26
- run_plugins(:before_environmentfromfile)
25
+ @object_name = arg.split("/").last
26
+ run_plugins(:before_environmentfromfile)
27
+ begin
27
28
  pre_environment = load_environment(@object_name.gsub(".json","").gsub(".rb",""))
28
- environment_from_file
29
- post_environment = load_environment(@object_name.gsub(".json","").gsub(".rb",""))
30
- @object_difference = json_diff(pre_environment,post_environment).to_s
31
- run_plugins(:after_environmentfromfile)
29
+ rescue Net::HTTPServerException => e
30
+ pre_environment = {}
31
+ end
32
+ environment_from_file
33
+ post_environment = load_environment(@object_name.gsub(".json","").gsub(".rb",""))
34
+ @object_difference = json_diff(pre_environment,post_environment).to_s
35
+ run_plugins(:after_environmentfromfile)
32
36
  end
33
37
  end
34
38
 
@@ -1,13 +1,16 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkInfo < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork info'
9
11
 
10
12
  def run
13
+ self.class.send(:include, KnifeSpork::Runner)
11
14
  self.config = Chef::Config.merge!(config)
12
15
 
13
16
  run_plugins(:before_info)
@@ -1,14 +1,17 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkNodeCreate < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork node create NODE (options)'
9
11
 
10
12
 
11
13
  def run
14
+ self.class.send(:include, KnifeSpork::Runner)
12
15
  self.config = Chef::Config.merge!(config)
13
16
 
14
17
  if @name_args.empty?
@@ -1,14 +1,17 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkNodeDelete < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork node delete NODE (options)'
9
11
 
10
12
 
11
13
  def run
14
+ self.class.send(:include, KnifeSpork::Runner)
12
15
  self.config = Chef::Config.merge!(config)
13
16
 
14
17
  if @name_args.empty?
@@ -1,10 +1,12 @@
1
1
  require 'chef/knife'
2
- require 'chef/knife/core/node_editor'
3
- require 'knife-spork/runner'
4
2
 
5
3
  module KnifeSpork
6
4
  class SporkNodeEdit < Chef::Knife
7
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'chef/knife/core/node_editor'
8
+ require 'knife-spork/runner'
9
+ end
8
10
 
9
11
  banner 'knife spork node edit NODE (options)'
10
12
 
@@ -15,6 +17,7 @@ module KnifeSpork
15
17
  :description => "Display all attributes when editing"
16
18
 
17
19
  def run
20
+ self.class.send(:include, KnifeSpork::Runner)
18
21
  self.config = Chef::Config.merge!(config)
19
22
 
20
23
  if @name_args.empty?
@@ -1,14 +1,17 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkNodeFromFile < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork node from file FILE (options)'
9
11
 
10
12
 
11
13
  def run
14
+ self.class.send(:include, KnifeSpork::Runner)
12
15
  self.config = Chef::Config.merge!(config)
13
16
 
14
17
  if @name_args.empty?
@@ -1,9 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkNodeRunListAdd < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork node run_list add [NODE] [ENTRY[,ENTRY]] (options)'
9
11
 
@@ -14,6 +16,7 @@ module KnifeSpork
14
16
  :description => "Place the ENTRY in the run list after ITEM"
15
17
 
16
18
  def run
19
+ self.class.send(:include, KnifeSpork::Runner)
17
20
  self.config = Chef::Config.merge!(config)
18
21
 
19
22
  if @name_args.empty?
@@ -1,14 +1,16 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkNodeRunListRemove < Chef::Knife
6
- include KnifeSpork::Runner
7
5
 
8
- banner 'knife spork node run_list add [NODE] [ENTRY[,ENTRY]] (options)'
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
9
9
 
10
+ banner 'knife spork node run_list add [NODE] [ENTRY[,ENTRY]] (options)'
10
11
 
11
12
  def run
13
+ self.class.send(:include, KnifeSpork::Runner)
12
14
  self.config = Chef::Config.merge!(config)
13
15
 
14
16
  if @name_args.empty?
@@ -1,14 +1,16 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkNodeRunListSet < Chef::Knife
6
- include KnifeSpork::Runner
7
5
 
8
- banner 'knife spork node run_list set NODE ENTRIES (options)'
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
9
9
 
10
+ banner 'knife spork node run_list set NODE ENTRIES (options)'
10
11
 
11
12
  def run
13
+ self.class.send(:include, KnifeSpork::Runner)
12
14
  self.config = Chef::Config.merge!(config)
13
15
 
14
16
  if @name_args.size < 2
@@ -1,13 +1,14 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
-
4
- begin
5
- require 'berkshelf'
6
- rescue LoadError; end
7
2
 
8
3
  module KnifeSpork
9
4
  class SporkOmni < Chef::Knife
10
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ begin
9
+ require 'berkshelf'
10
+ rescue LoadError; end
11
+ end
11
12
 
12
13
  banner 'knife spork omni COOKBOOK (options)'
13
14
 
@@ -48,6 +49,7 @@ module KnifeSpork
48
49
  end
49
50
 
50
51
  def run
52
+ self.class.send(:include, KnifeSpork::Runner)
51
53
  self.config = Chef::Config.merge!(config)
52
54
 
53
55
  if name_args.empty?
@@ -1,14 +1,15 @@
1
1
  require 'chef/knife'
2
- require 'chef/exceptions'
3
- require 'knife-spork/runner'
4
-
5
- begin
6
- require 'berkshelf'
7
- rescue LoadError; end
8
2
 
9
3
  module KnifeSpork
10
4
  class SporkPromote < Chef::Knife
11
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'chef/exceptions'
8
+ require 'knife-spork/runner'
9
+ begin
10
+ require 'berkshelf'
11
+ rescue LoadError; end
12
+ end
12
13
 
13
14
  banner 'knife spork promote ENVIRONMENT COOKBOOK (options)'
14
15
 
@@ -32,6 +33,7 @@ module KnifeSpork
32
33
  end
33
34
 
34
35
  def run
36
+ self.class.send(:include, KnifeSpork::Runner)
35
37
  self.config = Chef::Config.merge!(config)
36
38
 
37
39
  if @name_args.empty?
@@ -77,7 +79,13 @@ module KnifeSpork
77
79
 
78
80
  def update_version_constraints(environment, cookbook, new_version)
79
81
  validate_version!(new_version)
80
- environment.cookbook_versions[cookbook] = "= #{new_version}"
82
+ if spork_config.preserve_constraint_operators
83
+ constraint_operator = environment.cookbook_versions[cookbook].split.first
84
+ ui.msg "Preserving existing version constraint operator: #{constraint_operator}"
85
+ else
86
+ constraint_operator = "="
87
+ end
88
+ environment.cookbook_versions[cookbook] = "#{constraint_operator} #{new_version}"
81
89
  end
82
90
 
83
91
  def save_environment_changes_remote(environment)
@@ -152,8 +160,7 @@ module KnifeSpork
152
160
  validate_version!(config[:version])
153
161
  version = config[:version] || load_cookbook(cookbook_name).version
154
162
 
155
- environment = config[:environment]
156
- api_endpoint = environment ? "environments/#{environment}/cookbooks/#{cookbook_name}/#{version}" : "cookbooks/#{cookbook_name}/#{version}"
163
+ api_endpoint = "cookbooks/#{cookbook_name}/#{version}"
157
164
 
158
165
  begin
159
166
  cookbooks = rest.get_rest(api_endpoint)
@@ -1,9 +1,11 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkRoleCreate < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork role create ROLE (options)'
9
11
 
@@ -13,6 +15,7 @@ module KnifeSpork
13
15
  :description => "The role description"
14
16
 
15
17
  def run
18
+ self.class.send(:include, KnifeSpork::Runner)
16
19
  self.config = Chef::Config.merge!(config)
17
20
 
18
21
  if @name_args.empty?
@@ -1,13 +1,16 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkRoleDelete < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork role delete ROLENAME (options)'
9
11
 
10
12
  def run
13
+ self.class.send(:include, KnifeSpork::Runner)
11
14
  self.config = Chef::Config.merge!(config)
12
15
 
13
16
  if @name_args.empty?
@@ -1,13 +1,16 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
2
 
4
3
  module KnifeSpork
5
4
  class SporkRoleEdit < Chef::Knife
6
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'knife-spork/runner'
8
+ end
7
9
 
8
10
  banner 'knife spork role edit ROLENAME (options)'
9
11
 
10
12
  def run
13
+ self.class.send(:include, KnifeSpork::Runner)
11
14
  self.config = Chef::Config.merge!(config)
12
15
 
13
16
  if @name_args.empty?
@@ -1,18 +1,18 @@
1
1
  require 'chef/knife'
2
- require 'knife-spork/runner'
3
- require 'json'
4
2
 
5
3
  module KnifeSpork
6
4
  class SporkRoleFromFile < Chef::Knife
7
- include KnifeSpork::Runner
8
5
 
9
6
  deps do
7
+ require 'knife-spork/runner'
8
+ require 'json'
10
9
  require 'chef/knife/role_from_file'
11
10
  end
12
11
 
13
12
  banner 'knife spork role from file FILENAME (options)'
14
13
 
15
14
  def run
15
+ self.class.send(:include, KnifeSpork::Runner)
16
16
  self.config = Chef::Config.merge!(config)
17
17
 
18
18
  if @name_args.empty?
@@ -24,7 +24,11 @@ module KnifeSpork
24
24
  @name_args.each do |arg|
25
25
  @object_name = arg.split("/").last
26
26
  run_plugins(:before_rolefromfile)
27
- pre_role = load_role(@object_name.gsub(".json","").gsub(".rb",""))
27
+ begin
28
+ pre_role = load_role(@object_name.gsub(".json","").gsub(".rb",""))
29
+ rescue Net::HTTPServerException => e
30
+ pre_role = {}
31
+ end
28
32
  role_from_file
29
33
  post_role = load_role(@object_name.gsub(".json","").gsub(".rb",""))
30
34
  @object_difference = json_diff(pre_role,post_role).to_s
@@ -1,13 +1,15 @@
1
1
  require 'chef/knife'
2
- require 'chef/exceptions'
3
- require 'chef/cookbook_loader'
4
- require 'chef/cookbook_uploader'
5
- require 'knife-spork/runner'
6
- require 'socket'
7
2
 
8
3
  module KnifeSpork
9
4
  class SporkUpload < Chef::Knife
10
- include KnifeSpork::Runner
5
+
6
+ deps do
7
+ require 'chef/exceptions'
8
+ require 'chef/cookbook_loader'
9
+ require 'chef/cookbook_uploader'
10
+ require 'knife-spork/runner'
11
+ require 'socket'
12
+ end
11
13
 
12
14
  CHECKSUM = 'checksum'
13
15
  MATCH_CHECKSUM = /[0-9a-f]{32,}/
@@ -39,6 +41,7 @@ module KnifeSpork
39
41
  end
40
42
 
41
43
  def run
44
+ self.class.send(:include, KnifeSpork::Runner)
42
45
  self.config = Chef::Config.merge!(config)
43
46
  config[:cookbook_path] ||= Chef::Config[:cookbook_path]
44
47
 
@@ -78,18 +81,23 @@ module KnifeSpork
78
81
  check_dependencies(cookbook)
79
82
  if name_args.include?(cookbook.name.to_s)
80
83
  uploader = Chef::CookbookUploader.new(cookbook, ::Chef::Config.cookbook_path)
81
- if uploader.respond_to?(:upload_cookbooks)
82
- # Chef >= 10.14.0
83
- uploader.upload_cookbooks
84
- ui.info "Freezing #{cookbook.name} at #{cookbook.version}..."
85
- cookbook.freeze_version
86
- uploader.upload_cookbooks
87
- else
88
- uploader.upload_cookbook
89
- ui.info "Freezing #{cookbook.name} at #{cookbook.version}..."
90
- cookbook.freeze_version
91
- uploader.upload_cookbook
92
-
84
+ begin
85
+ if uploader.respond_to?(:upload_cookbooks)
86
+ # Chef >= 10.14.0
87
+ uploader.upload_cookbooks
88
+ ui.info "Freezing #{cookbook.name} at #{cookbook.version}..."
89
+ cookbook.freeze_version
90
+ uploader.upload_cookbooks
91
+ else
92
+ uploader.upload_cookbook
93
+ ui.info "Freezing #{cookbook.name} at #{cookbook.version}..."
94
+ cookbook.freeze_version
95
+ uploader.upload_cookbook
96
+
97
+ end
98
+ rescue Chef::Exceptions::CookbookFrozen => msg
99
+ ui.error "#{cookbook.name}@#{cookbook.version} is frozen. Please bump your version number before continuing!"
100
+ exit(1)
93
101
  end
94
102
  end
95
103
  rescue Net::HTTPServerException => e
@@ -53,7 +53,7 @@ module KnifeSpork
53
53
  end
54
54
 
55
55
  def load_environments_and_cookbook
56
- ensure_environment_provided!
56
+ ensure_environment_and_cookbook_provided!
57
57
 
58
58
  if @name_args.size == 2
59
59
  environments = load_specified_environment_group(@name_args[0])
@@ -63,6 +63,16 @@ module KnifeSpork
63
63
  end
64
64
  end
65
65
 
66
+ def verify_and_load_environments
67
+ ensure_environment_provided!
68
+
69
+ if @name_args.size == 0
70
+ default_environments
71
+ elsif @name_args.size == 1
72
+ [@name_args[0]]
73
+ end
74
+ end
75
+
66
76
  def load_specified_environment_group(name)
67
77
  if !spork_config.environment_groups.nil? && spork_config.environment_groups.keys.include?(name)
68
78
  spork_config.environment_groups[name]
@@ -71,19 +81,29 @@ module KnifeSpork
71
81
  end
72
82
  end
73
83
 
74
- def ensure_environment_provided!
84
+ def ensure_environment_and_cookbook_provided!
75
85
  if default_environments.empty? && @name_args.size < 2
76
86
  ui.error('You must specify an environment or environment group and a cookbook name')
77
87
  exit(1)
78
88
  end
79
89
  end
80
90
 
91
+ def ensure_environment_provided!
92
+ if default_environments.empty? && @name_args.size < 1
93
+ ui.error('You must specify an environment or configure default environments.')
94
+ exit(1)
95
+ end
96
+ end
97
+
81
98
  def default_environments
82
99
  [ spork_config.default_environment || spork_config.default_environments ].flatten.compact
83
100
  end
84
101
 
85
102
  def pretty_print_json(json)
86
- JSON.pretty_generate(json)
103
+ options = spork_config[:json_options] || {}
104
+ # generate requires a hash where the keys are symbols
105
+ options = Hash[ options.to_hash.map {|(k,v)| [k.to_sym,v] }] unless options == {}
106
+ JSON.pretty_generate(json, options.to_hash)
87
107
  end
88
108
 
89
109
  def valid_version?(version)
@@ -115,7 +135,7 @@ module KnifeSpork
115
135
  end
116
136
 
117
137
  def environment_path
118
- spork_config[:environment_path] || cookbook_path.gsub("/cookbooks","/environments")
138
+ spork_config[:environment_path] || Chef::Config.environment_path.first || cookbook_path.gsub("/cookbooks","/environments")
119
139
  end
120
140
 
121
141
  def role_path
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-spork
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Cowie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-05 00:00:00.000000000 Z
11
+ date: 2014-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -66,7 +66,10 @@ dependencies:
66
66
  - - ! '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: 3.0.1
69
- description: A workflow plugin to help many devs work with the same chef repo/server
69
+ description: KnifeSpork is a workflow plugin for Chef::Knife which helps multiple
70
+ developers work on the same Chef Server and repository without treading on each
71
+ other's toes. This plugin was designed around the workflow we have here at Etsy,
72
+ where several people are working on the Chef repository and Chef Server simultaneously.
70
73
  email: jonlives@gmail.com
71
74
  executables: []
72
75
  extensions: []
@@ -87,6 +90,7 @@ files:
87
90
  - lib/chef/knife/spork-databag-delete.rb
88
91
  - lib/chef/knife/spork-databag-edit.rb
89
92
  - lib/chef/knife/spork-databag-fromfile.rb
93
+ - lib/chef/knife/spork-environment-check.rb
90
94
  - lib/chef/knife/spork-environment-create.rb
91
95
  - lib/chef/knife/spork-environment-delete.rb
92
96
  - lib/chef/knife/spork-environment-edit.rb
@@ -133,7 +137,8 @@ files:
133
137
  - plugins/StatusNet.md
134
138
  - plugins/Template.md
135
139
  homepage: https://github.com/jonlives/knife-spork
136
- licenses: []
140
+ licenses:
141
+ - GPL
137
142
  metadata: {}
138
143
  post_install_message:
139
144
  rdoc_options: []