berkshelf 0.4.0 → 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/berkshelf.gemspec +8 -3
  2. data/bin/berks +1 -1
  3. data/features/groups_install.feature +67 -0
  4. data/features/install.feature +1 -71
  5. data/features/json_formatter.feature +0 -17
  6. data/features/step_definitions/filesystem_steps.rb +1 -3
  7. data/features/update.feature +3 -6
  8. data/features/vendor_install.feature +20 -0
  9. data/generator_files/Vagrantfile.erb +25 -3
  10. data/lib/berkshelf.rb +27 -17
  11. data/lib/berkshelf/base_generator.rb +5 -0
  12. data/lib/berkshelf/berksfile.rb +82 -77
  13. data/lib/berkshelf/cli.rb +37 -26
  14. data/lib/berkshelf/cookbook_source.rb +14 -4
  15. data/lib/berkshelf/errors.rb +4 -1
  16. data/lib/berkshelf/formatters.rb +69 -5
  17. data/lib/berkshelf/formatters/human_readable.rb +26 -8
  18. data/lib/berkshelf/formatters/json.rb +51 -23
  19. data/lib/berkshelf/init_generator.rb +4 -4
  20. data/lib/berkshelf/location.rb +29 -6
  21. data/lib/berkshelf/locations/chef_api_location.rb +23 -5
  22. data/lib/berkshelf/locations/git_location.rb +13 -6
  23. data/lib/berkshelf/locations/path_location.rb +8 -4
  24. data/lib/berkshelf/locations/site_location.rb +9 -3
  25. data/lib/berkshelf/ui.rb +34 -0
  26. data/lib/berkshelf/uploader.rb +37 -103
  27. data/lib/berkshelf/vagrant.rb +65 -0
  28. data/lib/berkshelf/vagrant/action/clean.rb +24 -0
  29. data/lib/berkshelf/vagrant/action/install.rb +47 -0
  30. data/lib/berkshelf/vagrant/action/set_ui.rb +17 -0
  31. data/lib/berkshelf/vagrant/action/upload.rb +40 -0
  32. data/lib/berkshelf/vagrant/config.rb +70 -0
  33. data/lib/berkshelf/vagrant/middleware.rb +52 -0
  34. data/lib/berkshelf/version.rb +1 -1
  35. data/lib/thor/monkies.rb +3 -0
  36. data/lib/thor/monkies/hash_with_indifferent_access.rb +13 -0
  37. data/lib/vagrant_init.rb +2 -0
  38. data/spec/spec_helper.rb +5 -0
  39. data/spec/support/chef_api.rb +6 -1
  40. data/spec/unit/berkshelf/berksfile_spec.rb +93 -55
  41. data/spec/unit/berkshelf/formatters_spec.rb +99 -1
  42. data/spec/unit/berkshelf/init_generator_spec.rb +1 -1
  43. data/spec/unit/berkshelf/location_spec.rb +44 -7
  44. data/spec/unit/berkshelf/lockfile_spec.rb +2 -2
  45. data/spec/unit/berkshelf/uploader_spec.rb +2 -20
  46. data/spec/unit/berkshelf_spec.rb +2 -2
  47. metadata +100 -14
  48. data/features/without.feature +0 -26
  49. data/lib/berkshelf/core_ext/fileutils.rb +0 -90
  50. data/lib/berkshelf/core_ext/kernel.rb +0 -33
  51. data/spec/unit/berkshelf/core_ext/fileutils_spec.rb +0 -20
@@ -16,10 +16,14 @@ Gem::Specification.new do |s|
16
16
  s.version = Berkshelf::VERSION
17
17
  s.required_ruby_version = ">= 1.9.1"
18
18
 
19
- s.add_runtime_dependency 'solve', '~> 0.2.1'
20
- s.add_runtime_dependency 'chef', '~> 10.12.0'
19
+ s.add_runtime_dependency 'ridley', '>= 0.0.3'
20
+ s.add_runtime_dependency 'solve', '~> 0.2.1'
21
+ s.add_runtime_dependency 'chef', '~> 10.12.0'
21
22
  s.add_runtime_dependency 'minitar'
22
- s.add_runtime_dependency 'thor', '~> 0.16.0'
23
+ s.add_runtime_dependency 'thor', '~> 0.16.0'
24
+ s.add_runtime_dependency 'vagrant', '~> 1.0.3'
25
+ s.add_runtime_dependency 'activesupport'
26
+ s.add_runtime_dependency 'multi_json'
23
27
 
24
28
  s.add_development_dependency 'redcarpet'
25
29
  s.add_development_dependency 'cucumber'
@@ -38,4 +42,5 @@ Gem::Specification.new do |s|
38
42
  s.add_development_dependency 'guard-spork'
39
43
  s.add_development_dependency 'guard-yard'
40
44
  s.add_development_dependency 'coolline'
45
+ s.add_development_dependency 'rb-fsevent', '~> 0.9.1'
41
46
  end
data/bin/berks CHANGED
@@ -5,6 +5,6 @@ require 'berkshelf'
5
5
  begin
6
6
  Berkshelf::Cli.start
7
7
  rescue Berkshelf::BerkshelfError => e
8
- Berkshelf.ui.fatal e
8
+ Berkshelf.ui.error e
9
9
  exit e.status_code
10
10
  end
@@ -0,0 +1,67 @@
1
+ Feature: installing groups
2
+ As a user
3
+ I want to be able specify groups of cookbooks to include or exclude
4
+ So I don't install cookbooks that are part of a group that I do not want to install
5
+
6
+ Scenario: except groups
7
+ Given I write to "Berksfile" with:
8
+ """
9
+ group :notme do
10
+ cookbook "nginx", "= 0.101.2"
11
+ end
12
+
13
+ cookbook "artifact", "= 0.10.0"
14
+
15
+ group :takeme do
16
+ cookbook "ntp", "= 1.1.8"
17
+ end
18
+ """
19
+ When I run the install command with flags:
20
+ | --except notme |
21
+ Then the cookbook store should have the cookbooks:
22
+ | artifact | 0.10.0 |
23
+ | ntp | 1.1.8 |
24
+ And the cookbook store should not have the cookbooks:
25
+ | nginx | 0.101.2 |
26
+
27
+ Scenario: only groups
28
+ Given I write to "Berksfile" with:
29
+ """
30
+ group :notme do
31
+ cookbook "nginx", "= 0.101.2"
32
+ end
33
+
34
+ cookbook "artifact", "= 0.10.0"
35
+
36
+ group :takeme do
37
+ cookbook "ntp", "= 1.1.8"
38
+ end
39
+ """
40
+ When I run the install command with flags:
41
+ | --only takeme |
42
+ Then the cookbook store should have the cookbooks:
43
+ | ntp | 1.1.8 |
44
+ And the cookbook store should not have the cookbooks:
45
+ | nginx | 0.101.2 |
46
+ | artifact | 0.10.0 |
47
+
48
+ Scenario: attempting to provide an only and except option
49
+ Given I write to "Berksfile" with:
50
+ """
51
+ group :notme do
52
+ cookbook "nginx", "= 0.101.2"
53
+ end
54
+
55
+ cookbook "artifact", "= 0.10.0"
56
+
57
+ group :takeme do
58
+ cookbook "ntp", "= 1.1.8"
59
+ end
60
+ """
61
+ When I run the install command with flags:
62
+ | --only takeme --except notme |
63
+ Then the output should contain:
64
+ """
65
+ Cannot specify both :except and :only
66
+ """
67
+ And the CLI should exit with the status code for error "ArgumentError"
@@ -65,21 +65,6 @@ Feature: install cookbooks from a Berksfile
65
65
  """
66
66
  And the exit status should be 0
67
67
 
68
- @no_run
69
- Scenario: installing a Berksfile that contains a path location which contains a broken symlink
70
- Given a Berksfile with path location sources to fixtures:
71
- | example_cookbook_broken_link | example_cookbook_broken_link |
72
- When I run the install command with flags:
73
- | --shims |
74
- Then the following directories should exist:
75
- | cookbooks |
76
- | cookbooks/example_cookbook |
77
- And the output should contain:
78
- """
79
- Shims written to:
80
- """
81
- And the exit status should be 0
82
-
83
68
  Scenario: installing a Berksfile that contains a Git location
84
69
  Given I write to "Berksfile" with:
85
70
  """
@@ -146,61 +131,6 @@ Feature: install cookbooks from a Berksfile
146
131
  """
147
132
  And the CLI should exit with the status code for error "CookbookNotFound"
148
133
 
149
- Scenario: running install command with the --shims flag to create a directory of shims
150
- Given I write to "Berksfile" with:
151
- """
152
- cookbook "mysql", "1.2.4"
153
- """
154
- When I run the install command with flags:
155
- | --shims |
156
- Then the following directories should exist:
157
- | cookbooks |
158
- | cookbooks/mysql |
159
- And the output should contain:
160
- """
161
- Shims written to:
162
- """
163
- And the exit status should be 0
164
-
165
- Scenario: running install command with the --shims flag and a relative path
166
- Given I write to "Berksfile" with:
167
- """
168
- cookbook "mysql", "1.2.4"
169
- """
170
- When I run the install command with flags:
171
- | --shims relativepath |
172
- Then the following directories should exist:
173
- | relativepath |
174
- | relativepath/mysql |
175
- And the output should contain:
176
- """
177
- Shims written to:
178
- """
179
- And the exit status should be 0
180
-
181
- Scenario: running install with --shims when current project is a cookbook and the 'metadata' is specified
182
- Given a cookbook named "sparkle_motion"
183
- And the cookbook "sparkle_motion" has the file "Berksfile" with:
184
- """
185
- metadata
186
- """
187
- When I cd to "sparkle_motion"
188
- And I run the install command with flags:
189
- | --shims |
190
- Then the following directories should exist:
191
- | cookbooks |
192
- | cookbooks/sparkle_motion |
193
- And the output should contain:
194
- """
195
- Shims written to:
196
- """
197
- And the output should contain:
198
- """
199
- Using sparkle_motion (0.0.0) at path:
200
- """
201
- And the exit status should be 0
202
-
203
-
204
134
  Scenario: installing a Berksfile that has a Git location source with an invalid Git URI
205
135
  Given I write to "Berksfile" with:
206
136
  """
@@ -267,7 +197,7 @@ Feature: install cookbooks from a Berksfile
267
197
  Scenario: with a cookbook definition containing a chef_api source location
268
198
  Given I write to "Berksfile" with:
269
199
  """
270
- cookbook "artifact", chef_api: :knife
200
+ cookbook "artifact", "= 0.10.2", chef_api: :knife
271
201
  """
272
202
  And the Chef server has cookbooks:
273
203
  | artifact | 0.10.2 |
@@ -43,20 +43,3 @@ Feature: --format json
43
43
  And the JSON should have "cookbooks/0/uploaded_to"
44
44
  And the Chef server should have the cookbooks:
45
45
  | example_cookbook | 0.5.0 |
46
-
47
- Scenario: JSON output when running install command with the --shims flag
48
- Given I write to "Berksfile" with:
49
- """
50
- cookbook "mysql", "1.2.4"
51
- """
52
- When I run the install command with flags:
53
- | --shims |
54
- | --format json|
55
- Then the following directories should exist:
56
- | cookbooks |
57
- | cookbooks/mysql |
58
- And the output should be JSON
59
- And the JSON should have "shims_dir"
60
-
61
-
62
-
@@ -107,11 +107,9 @@ Then /^I should have a new cookbook skeleton "(.*?)" with Vagrant support$/ do |
107
107
  contains "gem 'vagrant'"
108
108
  end
109
109
  file "Vagrantfile" do
110
+ contains "require 'berkshelf/vagrant'"
110
111
  contains "recipe[#{name}::default]"
111
112
  end
112
- directory "cookbooks" do
113
- directory name
114
- end
115
113
  }
116
114
  end
117
115
 
@@ -6,17 +6,14 @@ Feature: update
6
6
  Scenario: knife berkshelf update
7
7
  Given I write to "Berksfile" with:
8
8
  """
9
- cookbook "mysql", "1.3.0"
9
+ cookbook "artifact", "0.10.0"
10
10
  """
11
11
  Given I write to "Berksfile.lock" with:
12
12
  """
13
- cookbook 'mysql', :locked_version => '0.0.1'
14
- cookbook 'openssl', :locked_version => '0.0.1'
13
+ cookbook 'artifact', :locked_version => '0.0.1'
15
14
  """
16
15
  When I run the update command
17
16
  Then the file "Berksfile.lock" should contain exactly:
18
17
  """
19
- cookbook 'mysql', :locked_version => '1.3.0'
20
- cookbook 'openssl', :locked_version => '1.0.0'
21
- cookbook 'build-essential', :locked_version => '1.1.0'
18
+ cookbook 'artifact', :locked_version => '0.10.0'
22
19
  """
@@ -0,0 +1,20 @@
1
+ Feature: install cookbooks to a given vendor path
2
+ As a user of Berkshelf
3
+ I want to be able to install cookbooks to a specific directory
4
+ So I vendor my cookbooks and package them with my application
5
+
6
+ Scenario: default
7
+ Given I write to "Berksfile" with:
8
+ """
9
+ site :opscode
10
+
11
+ cookbook "artifact", "0.10.0"
12
+ """
13
+ When I run the install command with flags:
14
+ | --path vendor/cookbooks |
15
+ Then the cookbook store should have the cookbooks:
16
+ | artifact | 0.10.0 |
17
+ Then the following directories should exist:
18
+ | vendor/cookbooks |
19
+ | vendor/cookbooks/artifact |
20
+ And the exit status should be 0
@@ -1,8 +1,32 @@
1
+ require 'berkshelf/vagrant'
2
+
1
3
  Vagrant::Config.run do |config|
2
4
  # All Vagrant configuration is done here. The most common configuration
3
5
  # options are documented and commented below. For a complete reference,
4
6
  # please see the online documentation at vagrantup.com.
5
7
 
8
+ # The path to the Berksfile to use with Vagrant Berkshelf
9
+ # config.berkshelf.berksfile_path = "./Berksfile"
10
+
11
+ # The path to the Knife config to use with Vagrant Berkshelf
12
+ # config.berkshelf.config_path = "~/.chef/knife.rb"
13
+
14
+ # A client name (node_name) to use with the Chef Client provisioner to upload
15
+ # cookbooks installed by Berkshelf.
16
+ # config.berkshelf.node_name = "reset"
17
+
18
+ # A path to a client key on disk to use with the Chef Client provisioner to
19
+ # upload cookbooks installed by Berkshelf.
20
+ # config.berkshelf.client_key = "~/.chef/reset.pem"
21
+
22
+ # An array of symbols representing groups of cookbook described in the Vagrantfile
23
+ # to skip installing and copying to Vagrant's shelf.
24
+ # config.berkshelf.only = []
25
+
26
+ # An array of symbols representing groups of cookbook described in the Vagrantfile
27
+ # to skip installing and copying to Vagrant's shelf.
28
+ # config.berkshelf.except = []
29
+
6
30
  config.vm.host_name = "<%= cookbook_name %>-berkshelf"
7
31
 
8
32
  # CentOS 6.3
@@ -35,9 +59,7 @@ Vagrant::Config.run do |config|
35
59
  config.ssh.max_tries = 40
36
60
  config.ssh.timeout = 120
37
61
 
38
- config.vm.provision :chef_solo do |chef|
39
- chef.cookbooks_path = ["cookbooks"]
40
-
62
+ config.vm.provision :chef_solo do |chef|
41
63
  chef.json = {
42
64
  :mysql => {
43
65
  :server_root_password => 'rootpass',
@@ -1,14 +1,16 @@
1
1
  require 'forwardable'
2
2
  require 'uri'
3
3
  require 'pathname'
4
+ require 'tmpdir'
4
5
  require 'zlib'
5
6
  require 'archive/tar/minitar'
6
7
  require 'solve'
8
+ require 'ridley'
7
9
  require 'chef/knife'
8
- require 'chef/rest'
9
10
  require 'chef/platform'
10
11
  require 'chef/cookbook/metadata'
11
12
  require 'chef/cookbook_version'
13
+ require 'active_support/core_ext'
12
14
 
13
15
  require 'berkshelf/version'
14
16
  require 'berkshelf/core_ext'
@@ -21,6 +23,7 @@ module Berkshelf
21
23
  DEFAULT_STORE_PATH = File.expand_path("~/.berkshelf").freeze
22
24
  DEFAULT_FILENAME = 'Berksfile'.freeze
23
25
 
26
+ autoload :UI, 'berkshelf/ui'
24
27
  autoload :Cli, 'berkshelf/cli'
25
28
  autoload :Git, 'berkshelf/git'
26
29
  autoload :Berksfile, 'berkshelf/berksfile'
@@ -43,12 +46,14 @@ module Berkshelf
43
46
  attr_writer :config_path
44
47
  attr_writer :cookbook_store
45
48
 
49
+ # @return [Pathname]
46
50
  def root
47
51
  @root ||= Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
48
52
  end
49
53
 
54
+ # @return [Berkshelf::UI]
50
55
  def ui
51
- @ui ||= Chef::Knife::UI.new(null_stream, null_stream, STDIN, {})
56
+ @ui ||= Berkshelf::UI.new
52
57
  end
53
58
 
54
59
  # Returns the filepath to the location Berskhelf will use for
@@ -62,18 +67,30 @@ module Berkshelf
62
67
  ENV["BERKSHELF_PATH"] || DEFAULT_STORE_PATH
63
68
  end
64
69
 
70
+ # @return [String]
65
71
  def tmp_dir
66
72
  File.join(berkshelf_path, "tmp")
67
73
  end
68
74
 
75
+ # Creates a temporary directory within the Berkshelf path
76
+ #
77
+ # @return [String]
78
+ # path to the created temporary directory
79
+ def mktmpdir
80
+ FileUtils.mkdir_p(File.join(berkshelf_path, "tmp"))
81
+ Dir.mktmpdir(nil, File.join(berkshelf_path, "tmp"))
82
+ end
83
+
69
84
  def cookbooks_dir
70
85
  File.join(berkshelf_path, "cookbooks")
71
86
  end
72
87
 
88
+ # @return [Berkshelf::CookbookStore]
73
89
  def cookbook_store
74
90
  @cookbook_store ||= CookbookStore.new(cookbooks_dir)
75
91
  end
76
92
 
93
+ # @return [String]
77
94
  def config_path
78
95
  @config_path ||= DEFAULT_CONFIG
79
96
  end
@@ -108,26 +125,19 @@ module Berkshelf
108
125
  #
109
126
  # @return [~Formatter]
110
127
  def formatter
111
- @formatter ||= (formatters.has_key?(@_format) ? formatters[@_format] : Formatters::HumanReadable).new
128
+ @formatter ||= Formatters::HumanReadable.new
112
129
  end
113
130
 
114
- # Specify a formatter identifier
131
+ # Specify the format for output
115
132
  #
116
- # @param [String] format
117
- # which formatter to use
133
+ # @param [#to_sym] format_id
134
+ # the ID of the registered formatter to use
118
135
  #
119
- # @example Berkshelf.set_format "json"
120
- def set_format(format)
121
- @_format = format
122
- @formatter = nil
123
- end
124
-
125
- # Access the formatters map that links string symbols to Formatter
126
- # implementations
136
+ # @example Berkshelf.set_format :json
127
137
  #
128
- # @return [Hash]
129
- def formatters
130
- @formatters ||= {}
138
+ # @return [~Formatter]
139
+ def set_format(format_id)
140
+ @formatter = Formatters[format_id].new
131
141
  end
132
142
 
133
143
  private
@@ -11,6 +11,11 @@ module Berkshelf
11
11
 
12
12
  include Thor::Actions
13
13
 
14
+ def initialize(*args)
15
+ super(*args)
16
+ self.shell = Berkshelf.ui
17
+ end
18
+
14
19
  private
15
20
 
16
21
  def target
@@ -16,19 +16,29 @@ module Berkshelf
16
16
  raise BerksfileNotFound, "No Berksfile or Berksfile.lock found at: #{file}"
17
17
  end
18
18
 
19
- # @param [Array] sources
20
- # an array of sources to filter
21
- # @param [Array, Symbol] excluded
22
- # an array of symbols or a symbol representing the group or group(s)
23
- # to exclude
19
+ # Copy all cached_cookbooks to the given directory. Each cookbook will be contained in
20
+ # a directory named after the name of the cookbook.
24
21
  #
25
- # @return [Array<Berkshelf::CookbookSource>]
26
- # an array of sources that are not members of the excluded group(s)
27
- def filter_sources(sources, excluded)
28
- excluded = Array(excluded)
29
- excluded.collect!(&:to_sym)
22
+ # @param [Array<CachedCookbook>] cookbooks
23
+ # an array of CachedCookbooks to be copied to a vendor directory
24
+ # @param [String] path
25
+ # filepath to vendor cookbooks to
26
+ #
27
+ # @return [String]
28
+ # expanded filepath to the vendor directory
29
+ def vendor(cookbooks, path)
30
+ path = File.expand_path(path)
31
+ FileUtils.mkdir_p(path)
32
+
33
+ scratch = Berkshelf.mktmpdir
34
+ cookbooks.each do |cb|
35
+ FileUtils.cp_r(cb.path, File.join(scratch, cb.cookbook_name))
36
+ end
30
37
 
31
- sources.select { |source| (excluded & source.groups).empty? }
38
+ FileUtils.remove_dir(path, force: true)
39
+ File.rename(scratch, path)
40
+
41
+ path
32
42
  end
33
43
  end
34
44
 
@@ -41,6 +51,9 @@ module Berkshelf
41
51
  # @return [Berkshelf::Downloader]
42
52
  attr_reader :downloader
43
53
 
54
+ # @return [Array<Berkshelf::CachedCookbook>]
55
+ attr_reader :cached_cookbooks
56
+
44
57
  def_delegator :downloader, :add_location
45
58
  def_delegator :downloader, :locations
46
59
 
@@ -48,6 +61,7 @@ module Berkshelf
48
61
  @filepath = path
49
62
  @sources = Hash.new
50
63
  @downloader = Downloader.new(Berkshelf.cookbook_store)
64
+ @cached_cookbooks = nil
51
65
  end
52
66
 
53
67
  # Add a cookbook source to the Berksfile to be retrieved and have it's dependencies recurisvely retrieved
@@ -130,7 +144,6 @@ module Berkshelf
130
144
  add_source(name, constraint, options)
131
145
  end
132
146
 
133
-
134
147
  def group(*args)
135
148
  @@active_group = args
136
149
  yield
@@ -245,16 +258,29 @@ module Berkshelf
245
258
  @sources.has_key?(source.to_s)
246
259
  end
247
260
 
248
- # @option options [Symbol, Array] :exclude
261
+ # @option options [Symbol, Array] :except
249
262
  # Group(s) to exclude to exclude from the returned Array of sources
250
263
  # group to not be installed
264
+ # @option options [Symbol, Array] :only
265
+ # Group(s) to include which will cause any sources marked as a member of the
266
+ # group to be installed and all others to be ignored
267
+ #
268
+ # @raise [Berkshelf::ArgumentError] if a value for both :except and :only is provided
251
269
  #
252
270
  # @return [Array<Berkshelf::CookbookSource>]
253
271
  def sources(options = {})
254
272
  l_sources = @sources.collect { |name, source| source }.flatten
255
273
 
256
- if options[:exclude]
257
- self.class.filter_sources(l_sources, options[:exclude])
274
+ except = Array(options.fetch(:except, nil)).collect(&:to_sym)
275
+ only = Array(options.fetch(:only, nil)).collect(&:to_sym)
276
+
277
+ case
278
+ when !except.empty? && !only.empty?
279
+ raise Berkshelf::ArgumentError, "Cannot specify both :except and :only"
280
+ when !except.empty?
281
+ l_sources.select { |source| (except & source.groups).empty? }
282
+ when !only.empty?
283
+ l_sources.select { |source| !(only & source.groups).empty? }
258
284
  else
259
285
  l_sources
260
286
  end
@@ -294,101 +320,80 @@ module Berkshelf
294
320
  end
295
321
  alias_method :get_source, :[]
296
322
 
297
- # @option options [Symbol, Array] :without
323
+ # @option options [Symbol, Array] :except
298
324
  # Group(s) to exclude which will cause any sources marked as a member of the
299
325
  # group to not be installed
300
- # @option options [String, Pathname] :shims
301
- # Path to a directory of shims each pointing to a Cookbook Version that is
302
- # part of the dependency solution. Each shim is a hard link on disk.
326
+ # @option options [Symbol, Array] :only
327
+ # Group(s) to include which will cause any sources marked as a member of the
328
+ # group to be installed and all others to be ignored
329
+ # @option options [String] :path
330
+ # a path to "vendor" the cached_cookbooks resolved by the resolver. Vendoring
331
+ # is a technique for packaging all cookbooks resolved by a Berksfile.
332
+ #
333
+ # @return [Array<Berkshelf::CachedCookbook>]
303
334
  def install(options = {})
304
335
  resolver = Resolver.new(
305
336
  self.downloader,
306
- sources: sources(exclude: options[:without])
337
+ sources: sources(options)
307
338
  )
308
339
 
309
- solution = resolver.resolve
310
- if options[:shims]
311
- write_shims(options[:shims], solution)
312
- Berkshelf.formatter.shims_written options[:shims]
313
- end
340
+ @cached_cookbooks = resolver.resolve
314
341
  write_lockfile(resolver.sources) unless lockfile_present?
342
+
343
+ if options[:path]
344
+ self.class.vendor(@cached_cookbooks, options[:path])
345
+ end
346
+
347
+ self.cached_cookbooks
315
348
  end
316
349
 
317
- # @param [String] chef_server_url
318
- # the full URL to the Chef Server to upload to
319
- #
320
- # "https://api.opscode.com/organizations/vialstudios"
321
- #
322
- # @option options [Symbol, Array] :without
323
- # Group(s) to exclude which will cause any sources marked as a member of the
324
- # group to not be installed
325
- # @option options [String] :node_name
326
- # the name of the client used to sign REST requests to the Chef Server
350
+ # @option options [String] :server_url
351
+ # URL to the Chef API
352
+ # @option options [String] :client_name
353
+ # name of the client used to authenticate with the Chef API
327
354
  # @option options [String] :client_key
328
- # the filepath location for the client's key used to sign REST requests
329
- # to the Chef Server
355
+ # filepath to the client's private key used to authenticate with
356
+ # the Chef API
357
+ # @option options [String] :organization
358
+ # the Organization to connect to. This is only used if you are connecting to
359
+ # private Chef or hosted Chef
330
360
  # @option options [Boolean] :force Upload the Cookbook even if the version
331
361
  # already exists and is frozen on the target Chef Server
332
362
  # @option options [Boolean] :freeze Freeze the uploaded Cookbook on the Chef
333
363
  # Server so that it cannot be overwritten
334
- def upload(chef_server_url, options = {})
335
- uploader = Uploader.new(chef_server_url, options)
364
+ # @option options [Symbol, Array] :except
365
+ # Group(s) to exclude which will cause any sources marked as a member of the
366
+ # group to not be installed
367
+ # @option options [Symbol, Array] :only
368
+ # Group(s) to include which will cause any sources marked as a member of the
369
+ # group to be installed and all others to be ignored
370
+ def upload(options = {})
371
+ uploader = Uploader.new(options)
336
372
  solution = resolve(options)
337
373
 
338
374
  solution.each do |cb|
339
- Berkshelf.formatter.upload cb.cookbook_name, cb.version, chef_server_url
375
+ Berkshelf.formatter.upload cb.cookbook_name, cb.version, options[:server_url]
340
376
  uploader.upload(cb, options)
341
377
  end
342
378
  end
343
379
 
344
380
  # Finds a solution for the Berksfile and returns an array of CachedCookbooks.
345
381
  #
346
- # @option options [Symbol, Array] :without
382
+ # @option options [Symbol, Array] :except
347
383
  # Group(s) to exclude which will cause any sources marked as a member of the
348
- # group to not be resolved
384
+ # group to not be installed
385
+ # @option options [Symbol, Array] :only
386
+ # Group(s) to include which will cause any sources marked as a member of the
387
+ # group to be installed and all others to be ignored
349
388
  #
350
389
  # @return [Array<Berkshelf::CachedCookbooks]
351
390
  def resolve(options = {})
352
391
  Resolver.new(
353
392
  self.downloader,
354
- sources: sources(exclude: options[:without])
393
+ sources: sources(options)
355
394
  ).resolve
356
395
  end
357
396
 
358
- # Write a collection of hard links to the given path representing the given
359
- # CachedCookbooks. Useful for getting Cookbooks in a single location for
360
- # consumption by Vagrant, or another tool that expect this structure.
361
- #
362
- # @example
363
- # Given the path: '/Users/reset/code/pvpnet/cookbooks'
364
- # And a CachedCookbook: 'nginx' verison '0.100.5' at '/Users/reset/.berkshelf/nginx-0.100.5'
365
- #
366
- # A hardlink will be created at: '/Users/reset/code/pvpnet/cookbooks/nginx'
367
- #
368
- # @param [Pathname, String] path
369
- # @param [Array<Berkshelf::CachedCookbook>] cached_cookbooks
370
- def write_shims(path, cached_cookbooks)
371
- path = File.expand_path(path)
372
- actual_path = nil
373
-
374
- if descendant_directory?(path, Dir.pwd)
375
- actual_path = path
376
- FileUtils.rm_rf(actual_path)
377
- path = File.join(Berkshelf.tmp_dir, "shims")
378
- end
379
-
380
- FileUtils.mkdir_p(path)
381
- cached_cookbooks.each do |cached_cookbook|
382
- destination = File.expand_path(File.join(path, cached_cookbook.cookbook_name))
383
- FileUtils.rm_rf(destination)
384
- FileUtils.ln_r(cached_cookbook.path, destination, force: true)
385
- end
386
-
387
- if actual_path
388
- FileUtils.mv(path, actual_path)
389
- end
390
- end
391
-
392
397
  # Reload this instance of Berksfile with the given content. The content
393
398
  # is a string that may contain terms from the included DSL.
394
399
  #