berkshelf 0.4.0 → 0.5.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  #