berkshelf 1.1.6 → 1.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.cane +4 -0
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +25 -0
  4. data/CONTRIBUTING.md +9 -0
  5. data/Gemfile +1 -7
  6. data/Guardfile +4 -2
  7. data/LICENSE +4 -4
  8. data/README.md +34 -11
  9. data/Thorfile +12 -11
  10. data/berkshelf-complete.sh +68 -0
  11. data/berkshelf.gemspec +23 -10
  12. data/bin/berks +2 -0
  13. data/features/config.feature +5 -4
  14. data/features/configure_command.feature +1 -0
  15. data/features/install_command.feature +7 -43
  16. data/features/step_definitions/configure_cli_steps.rb +6 -0
  17. data/features/step_definitions/filesystem_steps.rb +3 -1
  18. data/features/step_definitions/json_steps.rb +7 -0
  19. data/features/support/env.rb +3 -8
  20. data/features/upload_command.feature +49 -101
  21. data/generator_files/Vagrantfile.erb +1 -1
  22. data/generator_files/gitignore.erb +6 -1
  23. data/lib/berkshelf.rb +17 -26
  24. data/lib/berkshelf/base_generator.rb +8 -7
  25. data/lib/berkshelf/berksfile.rb +33 -13
  26. data/lib/berkshelf/cached_cookbook.rb +16 -37
  27. data/lib/berkshelf/chef.rb +11 -0
  28. data/lib/berkshelf/chef/config.rb +93 -0
  29. data/lib/berkshelf/chef/cookbook.rb +8 -0
  30. data/lib/berkshelf/chef/cookbook/chefignore.rb +60 -0
  31. data/lib/berkshelf/chef/cookbook/metadata.rb +556 -0
  32. data/lib/berkshelf/chef/cookbook/syntax_check.rb +158 -0
  33. data/lib/berkshelf/chef/digester.rb +67 -0
  34. data/lib/berkshelf/cli.rb +18 -4
  35. data/lib/berkshelf/command.rb +117 -0
  36. data/lib/berkshelf/community_rest.rb +135 -0
  37. data/lib/berkshelf/config.rb +16 -50
  38. data/lib/berkshelf/cookbook_generator.rb +5 -9
  39. data/lib/berkshelf/cookbook_source.rb +1 -1
  40. data/lib/berkshelf/cookbook_store.rb +5 -1
  41. data/lib/berkshelf/downloader.rb +4 -4
  42. data/lib/berkshelf/errors.rb +6 -0
  43. data/lib/berkshelf/formatters.rb +3 -3
  44. data/lib/berkshelf/formatters/human_readable.rb +1 -1
  45. data/lib/berkshelf/formatters/json.rb +1 -1
  46. data/lib/berkshelf/git.rb +2 -2
  47. data/lib/berkshelf/init_generator.rb +5 -11
  48. data/lib/berkshelf/location.rb +7 -6
  49. data/lib/berkshelf/locations/chef_api_location.rb +54 -108
  50. data/lib/berkshelf/locations/git_location.rb +1 -1
  51. data/lib/berkshelf/locations/github_location.rb +1 -1
  52. data/lib/berkshelf/locations/path_location.rb +22 -3
  53. data/lib/berkshelf/locations/site_location.rb +31 -99
  54. data/lib/berkshelf/mixin.rb +10 -0
  55. data/lib/berkshelf/mixin/checksum.rb +16 -0
  56. data/lib/berkshelf/mixin/params_validate.rb +218 -0
  57. data/lib/berkshelf/mixin/path_helpers.rb +30 -0
  58. data/lib/berkshelf/mixin/shell_out.rb +23 -0
  59. data/lib/berkshelf/resolver.rb +5 -3
  60. data/lib/berkshelf/ui.rb +5 -1
  61. data/lib/berkshelf/uploader.rb +11 -5
  62. data/lib/berkshelf/vagrant.rb +1 -1
  63. data/lib/berkshelf/vagrant/action/clean.rb +1 -1
  64. data/lib/berkshelf/vagrant/action/install.rb +1 -1
  65. data/lib/berkshelf/vagrant/action/set_ui.rb +2 -2
  66. data/lib/berkshelf/vagrant/action/upload.rb +1 -1
  67. data/lib/berkshelf/vagrant/action/validate.rb +1 -1
  68. data/lib/berkshelf/vagrant/config.rb +1 -1
  69. data/lib/berkshelf/vagrant/middleware.rb +1 -1
  70. data/lib/berkshelf/version.rb +1 -1
  71. data/lib/thor/monkies/shell.rb +8 -0
  72. data/spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb +1 -1
  73. data/spec/fixtures/cookbooks/example_cookbook/metadata.rb +1 -1
  74. data/spec/fixtures/cookbooks/nginx-0.100.5/templates/default/plugins/nginx.rb.erb +1 -1
  75. data/spec/spec_helper.rb +81 -21
  76. data/spec/support/chef_api.rb +29 -28
  77. data/spec/support/knife.rb +2 -2
  78. data/spec/support/test_generators.rb +27 -0
  79. data/spec/unit/berkshelf/berksfile_spec.rb +2 -2
  80. data/spec/unit/berkshelf/cached_cookbook_spec.rb +10 -2
  81. data/spec/unit/berkshelf/community_rest_spec.rb +120 -0
  82. data/spec/unit/berkshelf/config_spec.rb +0 -12
  83. data/spec/unit/berkshelf/cookbook_generator_spec.rb +65 -67
  84. data/spec/unit/berkshelf/cookbook_source_spec.rb +1 -1
  85. data/spec/unit/berkshelf/git_spec.rb +17 -12
  86. data/spec/unit/berkshelf/init_generator_spec.rb +126 -120
  87. data/spec/unit/berkshelf/location_spec.rb +2 -2
  88. data/spec/unit/berkshelf/locations/chef_api_location_spec.rb +90 -186
  89. data/spec/unit/berkshelf/locations/git_location_spec.rb +87 -82
  90. data/spec/unit/berkshelf/locations/path_location_spec.rb +34 -35
  91. data/spec/unit/berkshelf/locations/site_location_spec.rb +12 -115
  92. data/spec/unit/berkshelf/resolver_spec.rb +96 -87
  93. data/spec/unit/berkshelf/ui_spec.rb +132 -0
  94. data/spec/unit/berkshelf/uploader_spec.rb +18 -12
  95. data/spec/unit/chef/config_spec.rb +9 -0
  96. data/spec/unit/chef/cookbook/metadata_spec.rb +5 -0
  97. data/spec/unit/chef/digester_spec.rb +41 -0
  98. metadata +263 -28
@@ -1,3 +1,9 @@
1
+ Given /^I have a default Chef config$/ do
2
+ path = tmp_path.join('chef_config').to_s
3
+ generate_chef_config(path)
4
+ ENV['BERKSHELF_CHEF_CONFIG'] = path
5
+ end
6
+
1
7
  Then /^a Berkshelf config file should exist and contain:$/ do |table|
2
8
  config = Berkshelf::Config.from_file(Berkshelf::Config.path)
3
9
  table.raw.each do |key, value|
@@ -23,7 +23,9 @@ Given /^I have a default Berkshelf config file$/ do
23
23
  end
24
24
 
25
25
  Given /^I have a Berkshelf config file containing:$/ do |contents|
26
- Berkshelf::Config.new.from_json(contents).save
26
+ File.open(Berkshelf::Config.path, 'w+') do |f|
27
+ f.write(contents)
28
+ end
27
29
  end
28
30
 
29
31
  Given /^I do not have a Berkshelf config file$/ do
@@ -1,3 +1,10 @@
1
1
  Then /^the output should be JSON$/ do
2
2
  lambda { parse_json(all_output) }.should_not raise_error
3
3
  end
4
+
5
+ Then /^the file "(.*?)" should contain JSON:$/ do |file, data|
6
+ target = MultiJson.decode(data)
7
+ actual = MultiJson.decode(File.read(File.join(current_dir, file)))
8
+
9
+ target.should eql(actual)
10
+ end
@@ -7,7 +7,6 @@ Spork.prefork do
7
7
  require 'rspec'
8
8
  require 'pp'
9
9
  require 'aruba/cucumber'
10
- require 'vcr'
11
10
 
12
11
  APP_ROOT = File.expand_path('../../../', __FILE__)
13
12
 
@@ -26,17 +25,13 @@ Spork.prefork do
26
25
 
27
26
  ENV["GIT_SSH"] = git_ssh_path
28
27
 
29
-
30
28
  Dir[File.join(APP_ROOT, "spec/support/**/*.rb")].each {|f| require f}
31
29
 
32
- Around do |scenario, block|
33
- VCR.use_cassette(scenario.name) do
34
- block.call
35
- end
36
- end
30
+ World(Berkshelf::TestGenerators)
37
31
 
38
32
  Before do
39
33
  clean_cookbook_store
34
+ generate_berks_config(File.join(ENV["BERKSHELF_PATH"], 'config.json'))
40
35
  @aruba_io_wait_seconds = 5
41
36
  @aruba_timeout_seconds = 16
42
37
  end
@@ -47,7 +42,7 @@ Spork.prefork do
47
42
  end
48
43
 
49
44
  def cookbook_store
50
- Pathname.new(File.join(ENV["BERKSHELF_PATH"],"cookbooks"))
45
+ Pathname.new(File.join(ENV["BERKSHELF_PATH"], "cookbooks"))
51
46
  end
52
47
 
53
48
  def clean_cookbook_store
@@ -94,175 +94,123 @@ Feature: upload command
94
94
  And the exit status should be 0
95
95
 
96
96
  @chef_server @slow_process
97
- Scenario: Running the upload command with multiple cookbooks
97
+ Scenario: explicitly specifying multiple cookbooks to upload
98
98
  Given I write to "Berksfile" with:
99
99
  """
100
- cookbook "build-essential"
101
- cookbook "chef-client"
102
- cookbook "database"
103
- cookbook "editor"
104
- cookbook "git"
105
- cookbook "known_host"
106
- cookbook "networking_basic"
100
+ cookbook "ntp"
107
101
  cookbook "vim"
102
+ cookbook "apt"
108
103
  """
109
104
  And I successfully run `berks install`
110
105
  And the Chef server does not have the cookbooks:
111
- | build-essential |
112
- | chef-client |
113
- | database |
114
- | editor |
115
- | git |
116
- | known_host |
117
- | networking_basic |
118
- | vim |
119
- When I run `berks upload build-essential chef-client database`
120
- Then the output should contain "Uploading build-essential"
121
- And the output should contain "Uploading chef-client"
122
- And the output should contain "Uploading database"
123
- And the output should not contain "Uploading editor"
124
- And the output should not contain "Uploading git"
125
- And the output should not contain "Uploading known_host"
126
- And the output should not contain "Uploading networking_basic"
127
- And the output should not contain "Uploading vim"
106
+ | ntp |
107
+ | vim |
108
+ | apt |
109
+ When I run `berks upload ntp vim`
110
+ Then the output should contain "Uploading ntp"
111
+ And the output should contain "Uploading vim"
112
+ And the output should not contain "Uploading apt"
128
113
  And the Chef server should have the cookbooks:
129
- | build_essential |
130
- | chef-client |
131
- | database |
114
+ | ntp |
115
+ | vim |
132
116
  And the Chef server should not have the cookbooks:
133
- | editor |
134
- | git |
135
- | known_host |
136
- | networking_basic |
137
- | vim |
117
+ | apt |
138
118
  And the exit status should be 0
139
119
 
140
120
  @chef_server @slow_process
141
- Scenario: Running the upload command with the :only option
121
+ Scenario: uploading a single group of cookbooks with the --only flag
142
122
  Given I write to "Berksfile" with:
143
123
  """
144
124
  group :core do
145
- cookbook "build-essential"
146
- cookbook "chef-client"
125
+ cookbook "ntp"
147
126
  end
148
127
 
149
128
  group :system do
150
- cookbook "database"
151
- cookbook "editor"
129
+ cookbook "vim"
152
130
  end
153
131
  """
154
132
  And I successfully run `berks install`
155
133
  And the Chef server does not have the cookbooks:
156
- | build-essential |
157
- | chef-client |
158
- | database |
159
- | editor |
134
+ | ntp |
135
+ | vim |
160
136
  When I run `berks upload --only core`
161
- Then the output should contain "Uploading build-essential"
162
- And the output should contain "Uploading chef-client"
163
- And the output should not contain "Uploading database"
164
- And the output should not contain "Uploading editor"
137
+ Then the output should contain "Uploading ntp"
138
+ And the output should not contain "Uploading vim"
165
139
  And the Chef server should have the cookbooks:
166
- | build_essential |
167
- | chef-client |
140
+ | ntp |
168
141
  And the Chef server should not have the cookbooks:
169
- | database |
170
- | editor |
142
+ | vim |
171
143
  And the exit status should be 0
172
144
 
173
145
  @chef_server @slow_process
174
- Scenario: Running the upload command with the :only option multiple
146
+ Scenario: uploading multiple groups of cookbooks with the --only flag
175
147
  Given I write to "Berksfile" with:
176
148
  """
177
149
  group :core do
178
- cookbook "build-essential"
179
- cookbook "chef-client"
150
+ cookbook "ntp"
180
151
  end
181
152
 
182
153
  group :system do
183
- cookbook "database"
184
- cookbook "editor"
154
+ cookbook "vim"
185
155
  end
186
156
  """
187
157
  And I successfully run `berks install`
188
158
  And the Chef server does not have the cookbooks:
189
- | build-essential |
190
- | chef-client |
191
- | database |
192
- | editor |
159
+ | ntp |
160
+ | vim |
193
161
  When I run `berks upload --only core system`
194
- Then the output should contain "Uploading build-essential"
195
- And the output should contain "Uploading chef-client"
196
- And the output should contain "Uploading database"
197
- And the output should contain "Uploading editor"
162
+ Then the output should contain "Uploading ntp"
163
+ And the output should contain "Uploading vim"
198
164
  And the Chef server should have the cookbooks:
199
- | build_essential |
200
- | chef-client |
201
- | database |
202
- | editor |
165
+ | ntp |
166
+ | vim |
203
167
  And the exit status should be 0
204
168
 
205
169
  @chef_server @slow_process
206
- Scenario: Running the upload command with the :except option
170
+ Scenario: skip uploading one group of cookbooks with the --except flag
207
171
  Given I write to "Berksfile" with:
208
172
  """
209
173
  group :core do
210
- cookbook "build-essential"
211
- cookbook "chef-client"
174
+ cookbook "ntp"
212
175
  end
213
176
 
214
177
  group :system do
215
- cookbook "database"
216
- cookbook "editor"
178
+ cookbook "vim"
217
179
  end
218
180
  """
219
181
  And I successfully run `berks install`
220
182
  And the Chef server does not have the cookbooks:
221
- | build-essential |
222
- | chef-client |
223
- | database |
224
- | editor |
183
+ | ntp |
184
+ | vim |
225
185
  When I run `berks upload --except core`
226
- Then the output should not contain "Uploading build-essential"
227
- And the output should not contain "Uploading chef-client"
228
- And the output should contain "Uploading database"
229
- And the output should contain "Uploading editor"
186
+ Then the output should not contain "Uploading ntp"
187
+ And the output should contain "Uploading vim"
230
188
  And the Chef server should not have the cookbooks:
231
- | build_essential |
232
- | chef-client |
189
+ | ntp |
233
190
  And the Chef server should have the cookbooks:
234
- | database |
235
- | editor |
191
+ | vim |
236
192
  And the exit status should be 0
237
193
 
238
194
  @chef_server @slow_process
239
- Scenario: Running the upload command with the :except option multiple
195
+ Scenario: skip uploading multiple groups of cookbooks with the --except flag
240
196
  Given I write to "Berksfile" with:
241
197
  """
242
198
  group :core do
243
- cookbook "build-essential"
244
- cookbook "chef-client"
199
+ cookbook "ntp"
245
200
  end
246
201
 
247
202
  group :system do
248
- cookbook "database"
249
- cookbook "editor"
203
+ cookbook "vim"
250
204
  end
251
205
  """
252
206
  And I successfully run `berks install`
253
207
  And the Chef server does not have the cookbooks:
254
- | build-essential |
255
- | chef-client |
256
- | database |
257
- | editor |
208
+ | ntp |
209
+ | vim |
258
210
  When I run `berks upload --except core system`
259
- Then the output should not contain "Uploading build-essential"
260
- And the output should not contain "Uploading chef-client"
261
- And the output should not contain "Uploading database"
262
- And the output should not contain "Uploading editor"
211
+ Then the output should not contain "Uploading ntp"
212
+ And the output should not contain "Uploading vim"
263
213
  And the Chef server should not have the cookbooks:
264
- | build_essential |
265
- | chef-client |
266
- | database |
267
- | editor |
214
+ | ntp |
215
+ | vim |
268
216
  And the exit status should be 0
@@ -9,7 +9,7 @@ Vagrant::Config.run do |config|
9
9
  # config.berkshelf.berksfile_path = "./Berksfile"
10
10
 
11
11
  # An array of symbols representing groups of cookbook described in the Vagrantfile
12
- # to skip installing and copying to Vagrant's shelf.
12
+ # to exclusively install and copy to Vagrant's shelf.
13
13
  # config.berkshelf.only = []
14
14
 
15
15
  # An array of symbols representing groups of cookbook described in the Vagrantfile
@@ -1,6 +1,5 @@
1
1
  .vagrant
2
2
  Berksfile.lock
3
- Gemfile.lock
4
3
  *~
5
4
  *#
6
5
  .#*
@@ -8,6 +7,12 @@ Gemfile.lock
8
7
  .*.sw[a-z]
9
8
  *.un~
10
9
  /cookbooks
10
+
11
+ # Bundler
12
+ Gemfile.lock
13
+ bin/*
14
+ .bundle/*
15
+
11
16
  <% if options[:scmversion] -%>
12
17
  VERSION
13
18
  <% end -%>
@@ -1,17 +1,20 @@
1
- require 'yajl'
2
- require 'chef/platform'
3
- require 'chef/cookbook/metadata'
4
- require 'chef/cookbook_version'
5
- require 'chef/knife'
1
+ require 'multi_json'
2
+
3
+ # Fix for Facter < 1.7.0 changing LANG to C
4
+ # https://github.com/puppetlabs/facter/commit/f77584f4
5
+ begin
6
+ old_lang = ENV['LANG']
7
+ require 'ridley'
8
+ ensure
9
+ ENV['LANG'] = old_lang
10
+ end
6
11
 
7
12
  require 'chozo/core_ext'
8
-
9
13
  require 'active_support/core_ext'
10
14
  require 'archive/tar/minitar'
11
15
  require 'forwardable'
12
16
  require 'hashie'
13
17
  require 'pathname'
14
- require 'ridley'
15
18
  require 'solve'
16
19
  require 'thor'
17
20
  require 'tmpdir'
@@ -23,16 +26,17 @@ require 'berkshelf/core_ext'
23
26
  require 'berkshelf/errors'
24
27
  require 'thor/monkies'
25
28
 
26
- Chef::Config[:cache_options][:path] = Dir.mktmpdir
29
+ JSON.create_id = nil
27
30
 
28
31
  module Berkshelf
29
- DEFAULT_STORE_PATH = File.expand_path("~/.berkshelf").freeze
30
32
  DEFAULT_FILENAME = 'Berksfile'.freeze
31
33
 
32
34
  autoload :BaseGenerator, 'berkshelf/base_generator'
33
35
  autoload :Berksfile, 'berkshelf/berksfile'
34
36
  autoload :CachedCookbook, 'berkshelf/cached_cookbook'
37
+ autoload :Chef, 'berkshelf/chef'
35
38
  autoload :Cli, 'berkshelf/cli'
39
+ autoload :CommunityREST, 'berkshelf/community_rest'
36
40
  autoload :Config, 'berkshelf/config'
37
41
  autoload :CookbookGenerator, 'berkshelf/cookbook_generator'
38
42
  autoload :CookbookSource, 'berkshelf/cookbook_source'
@@ -41,6 +45,7 @@ module Berkshelf
41
45
  autoload :Git, 'berkshelf/git'
42
46
  autoload :InitGenerator, 'berkshelf/init_generator'
43
47
  autoload :Lockfile, 'berkshelf/lockfile'
48
+ autoload :Mixin, 'berkshelf/mixin'
44
49
  autoload :Resolver, 'berkshelf/resolver'
45
50
  autoload :UI, 'berkshelf/ui'
46
51
  autoload :Uploader, 'berkshelf/uploader'
@@ -57,9 +62,9 @@ module Berkshelf
57
62
  @root ||= Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
58
63
  end
59
64
 
60
- # @return [Berkshelf::UI]
65
+ # @return [::Thor::Shell::Color]
61
66
  def ui
62
- @ui ||= Berkshelf::UI.new
67
+ @ui ||= ::Thor::Shell::Color.new
63
68
  end
64
69
 
65
70
  # Returns the filepath to the location Berskhelf will use for
@@ -70,21 +75,7 @@ module Berkshelf
70
75
  #
71
76
  # @return [String]
72
77
  def berkshelf_path
73
- ENV["BERKSHELF_PATH"] || DEFAULT_STORE_PATH
74
- end
75
-
76
- # Check if we're running a version of Chef that is in the 11.x line
77
- #
78
- # @return [Boolean]
79
- def chef_11?
80
- chef_version >= Solve::Version.new("11.0.0") && chef_version <= Solve::Version.new("12.0.0")
81
- end
82
-
83
- # Return the loaded version of Chef
84
- #
85
- # @return [Solve::Version]
86
- def chef_version
87
- @chef_version ||= Solve::Version.new(::Chef::VERSION)
78
+ ENV["BERKSHELF_PATH"] || File.expand_path("~/.berkshelf")
88
79
  end
89
80
 
90
81
  # @return [String]
@@ -1,7 +1,7 @@
1
1
  require 'thor/group'
2
2
 
3
3
  module Berkshelf
4
- # @author Jamie Winsor <jamie@vialstudios.com>
4
+ # @author Jamie Winsor <reset@riotgames.com>
5
5
  class BaseGenerator < Thor::Group
6
6
  class << self
7
7
  def source_root
@@ -9,15 +9,16 @@ module Berkshelf
9
9
  end
10
10
  end
11
11
 
12
- include Thor::Actions
12
+ shell = Berkshelf.ui
13
13
 
14
- def initialize(*args)
15
- super(*args)
16
- self.shell = Berkshelf.ui
17
- end
14
+ argument :path,
15
+ type: :string,
16
+ required: true
18
17
 
19
- private
18
+ include Thor::Actions
20
19
 
20
+ private
21
+
21
22
  def target
22
23
  @target ||= Pathname.new(File.expand_path(path))
23
24
  end
@@ -1,7 +1,5 @@
1
- require 'chef/cookbook/chefignore'
2
-
3
1
  module Berkshelf
4
- # @author Jamie Winsor <jamie@vialstudios.com>
2
+ # @author Jamie Winsor <reset@riotgames.com>
5
3
  class Berksfile
6
4
  extend Forwardable
7
5
 
@@ -30,11 +28,11 @@ module Berkshelf
30
28
  # expanded filepath to the vendor directory
31
29
  def vendor(cookbooks, path)
32
30
  chefignore_file = [
33
- File.join(Dir.pwd, 'chefignore'),
34
- File.join(Dir.pwd, 'cookbooks', 'chefignore')
31
+ File.join(Dir.pwd, Berkshelf::Chef::Cookbook::Chefignore::FILENAME),
32
+ File.join(Dir.pwd, 'cookbooks', Berkshelf::Chef::Cookbook::Chefignore::FILENAME)
35
33
  ].find { |f| File.exists?(f) }
36
34
 
37
- chefignore = chefignore_file && ::Chef::Cookbook::Chefignore.new(chefignore_file)
35
+ chefignore = chefignore_file && Berkshelf::Chef::Cookbook::Chefignore.new(chefignore_file)
38
36
  path = File.expand_path(path)
39
37
  FileUtils.mkdir_p(path)
40
38
 
@@ -185,8 +183,7 @@ module Berkshelf
185
183
  raise CookbookNotFound, "No 'metadata.rb' found at #{path}"
186
184
  end
187
185
 
188
- metadata = Chef::Cookbook::Metadata.new
189
- metadata.from_file(metadata_file.to_s)
186
+ metadata = Berkshelf::Chef::Cookbook::Metadata.from_file(metadata_file.to_s)
190
187
 
191
188
  name = if metadata.name.empty? || metadata.name.nil?
192
189
  File.basename(File.dirname(metadata_file))
@@ -435,7 +432,7 @@ module Berkshelf
435
432
  location = cookbook.location || Location.init(cookbook.name, cookbook.version_constraint)
436
433
 
437
434
  if location.is_a?(SiteLocation)
438
- latest_version = SiteLocation.new(cookbook.name, cookbook.version_constraint).latest_version[0]
435
+ latest_version = location.latest_version
439
436
 
440
437
  unless cookbook.version_constraint.satisfies?(latest_version)
441
438
  outdated[cookbook] = latest_version
@@ -483,12 +480,18 @@ module Berkshelf
483
480
  def upload(options = {})
484
481
  uploader = Uploader.new(options)
485
482
  solution = resolve(options)
486
-
487
483
  solution.each do |cb|
488
484
  Berkshelf.formatter.upload cb.cookbook_name, cb.version, options[:server_url]
489
485
  uploader.upload(cb, options)
490
486
  end
491
-
487
+ if options[:skip_dependencies]
488
+ missing_cookbooks = options.fetch(:cookbooks, nil) - solution.map(&:cookbook_name)
489
+ unless missing_cookbooks.empty?
490
+ msg = "Unable to upload cookbooks: #{missing_cookbooks.sort.join(', ')}\n"
491
+ msg << "Specified cookbooks must be defined within the Berkshelf file when using the `--skip-dependencies` option"
492
+ raise ExplicitCookbookNotFound.new(msg)
493
+ end
494
+ end
492
495
  rescue Ridley::Errors::ClientKeyFileNotFound => e
493
496
  msg = "Could not upload cookbooks: Missing Chef client key: '#{Berkshelf::Config.instance.chef.client_key}'."
494
497
  msg << " Generate or update your Berkshelf configuration that contains a valid path to a Chef client key."
@@ -508,10 +511,27 @@ module Berkshelf
508
511
  #
509
512
  # @return [Array<Berkshelf::CachedCookbooks]
510
513
  def resolve(options = {})
514
+ resolver(options).resolve
515
+ end
516
+
517
+ # Builds a Resolver instance
518
+ #
519
+ # @option options [Symbol, Array] :except
520
+ # Group(s) to exclude which will cause any sources marked as a member of the
521
+ # group to not be installed
522
+ # @option options [Symbol, Array] :only
523
+ # Group(s) to include which will cause any sources marked as a member of the
524
+ # group to be installed and all others to be ignored
525
+ # @option cookbooks [String, Array] :cookbooks
526
+ # Names of the cookbooks to retrieve sources for
527
+ #
528
+ # @return <Berkshelf::Resolver>
529
+ def resolver(options={})
511
530
  Resolver.new(
512
531
  self.downloader,
513
- sources: sources(options)
514
- ).resolve
532
+ sources: sources(options),
533
+ skip_dependencies: options[:skip_dependencies]
534
+ )
515
535
  end
516
536
 
517
537
  # Reload this instance of Berksfile with the given content. The content