berkshelf-vagrant 1.0.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.
- data/.gitignore +17 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +44 -0
- data/Gemfile +40 -0
- data/Guardfile +16 -0
- data/LICENSE.txt +13 -0
- data/README.md +28 -0
- data/Thorfile +58 -0
- data/berkshelf-vagrant.gemspec +34 -0
- data/lib/berkshelf-vagrant.rb +1 -0
- data/lib/berkshelf/vagrant.rb +40 -0
- data/lib/berkshelf/vagrant/action.rb +61 -0
- data/lib/berkshelf/vagrant/action/clean.rb +26 -0
- data/lib/berkshelf/vagrant/action/configure_chef.rb +22 -0
- data/lib/berkshelf/vagrant/action/install.rb +34 -0
- data/lib/berkshelf/vagrant/action/load_shelf.rb +44 -0
- data/lib/berkshelf/vagrant/action/set_ui.rb +15 -0
- data/lib/berkshelf/vagrant/action/upload.rb +38 -0
- data/lib/berkshelf/vagrant/config.rb +66 -0
- data/lib/berkshelf/vagrant/env.rb +20 -0
- data/lib/berkshelf/vagrant/env_helpers.rb +46 -0
- data/lib/berkshelf/vagrant/errors.rb +33 -0
- data/lib/berkshelf/vagrant/plugin.rb +32 -0
- data/lib/berkshelf/vagrant/version.rb +5 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/unit/berkshelf/vagrant/errors_spec.rb +12 -0
- data/spec/unit/berkshelf/vagrant_spec.rb +25 -0
- metadata +228 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
## Developing
|
4
|
+
|
5
|
+
If you'd like to submit a patch:
|
6
|
+
|
7
|
+
1. Fork the project.
|
8
|
+
2. Make your feature addition or bug fix.
|
9
|
+
3. Add [tests](#testing) for it. This is important so that it isn't broken in a
|
10
|
+
future version unintentionally.
|
11
|
+
4. Commit. **Do not touch any unrelated code, such as the gemspec or version.**
|
12
|
+
If you must change unrelated code, do it in a commit by itself, so that it
|
13
|
+
can be ignored.
|
14
|
+
5. Send a pull request.
|
15
|
+
|
16
|
+
## Testing
|
17
|
+
|
18
|
+
### Install prerequisites
|
19
|
+
|
20
|
+
Install the latest version of [Bundler](http://gembundler.com)
|
21
|
+
|
22
|
+
$ gem install bundler
|
23
|
+
|
24
|
+
Clone the project
|
25
|
+
|
26
|
+
$ git clone git://github.com/RiotGames/berkshelf-vagrant.git
|
27
|
+
|
28
|
+
and run:
|
29
|
+
|
30
|
+
$ cd berkshelf-vagrant
|
31
|
+
$ bundle-vagrant install
|
32
|
+
|
33
|
+
Bundler will install all gems and their dependencies required for testing and developing.
|
34
|
+
|
35
|
+
### Running unit (RSpec) tests
|
36
|
+
|
37
|
+
One-time run with Thor
|
38
|
+
|
39
|
+
$ bundle exec thor spec
|
40
|
+
|
41
|
+
Or you can setup a quick feedback loop with Guard
|
42
|
+
|
43
|
+
$ bundle exec guard start
|
44
|
+
guard> rspec
|
data/Gemfile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in berkshelf-vagrant.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem 'vagrant', github: "mitchellh/vagrant", tag: "v1.1.2"
|
8
|
+
end
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem 'coolline'
|
12
|
+
gem 'guard', '>= 1.5.0'
|
13
|
+
gem 'guard-rspec'
|
14
|
+
gem 'guard-spork'
|
15
|
+
gem 'guard-yard'
|
16
|
+
gem 'redcarpet'
|
17
|
+
gem 'yard'
|
18
|
+
gem 'fuubar'
|
19
|
+
gem 'rspec'
|
20
|
+
|
21
|
+
require 'rbconfig'
|
22
|
+
|
23
|
+
if RbConfig::CONFIG['target_os'] =~ /darwin/i
|
24
|
+
gem 'growl', require: false
|
25
|
+
gem 'rb-fsevent', require: false
|
26
|
+
|
27
|
+
if `uname`.strip == 'Darwin' && `sw_vers -productVersion`.strip >= '10.8'
|
28
|
+
gem 'terminal-notifier-guard', '~> 1.5.3', require: false
|
29
|
+
end rescue Errno::ENOENT
|
30
|
+
|
31
|
+
elsif RbConfig::CONFIG['target_os'] =~ /linux/i
|
32
|
+
gem 'libnotify', '~> 0.8.0', require: false
|
33
|
+
gem 'rb-inotify', require: false
|
34
|
+
|
35
|
+
elsif RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
|
36
|
+
gem 'rb-notifu', '>= 0.0.4', require: false
|
37
|
+
gem 'wdm', require: false
|
38
|
+
gem 'win32console', require: false
|
39
|
+
end
|
40
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
guard 'spork' do
|
2
|
+
watch('Gemfile')
|
3
|
+
watch('spec/spec_helper.rb') { :rspec }
|
4
|
+
end
|
5
|
+
|
6
|
+
guard 'yard', stdout: '/dev/null', stderr: '/dev/null' do
|
7
|
+
watch(%r{app/.+\.rb})
|
8
|
+
watch(%r{lib/.+\.rb})
|
9
|
+
watch(%r{ext/.+\.c})
|
10
|
+
end
|
11
|
+
|
12
|
+
guard 'rspec', cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false do
|
13
|
+
watch(%r{^spec/unit/.+_spec\.rb$})
|
14
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
|
15
|
+
watch('spec/spec_helper.rb') { "spec" }
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2012-2013 Riot Games
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Berkshelf::Vagrant
|
2
|
+
[](http://badge.fury.io/rb/berkshelf-vagrant)
|
3
|
+
[](https://travis-ci.org/RiotGames/berkshelf-vagrant)
|
4
|
+
[](https://gemnasium.com/RiotGames/berkshelf-vagrant)
|
5
|
+
[](https://codeclimate.com/github/RiotGames/berkshelf-vagrant)
|
6
|
+
|
7
|
+
A Vagrant plugin to add Berkshelf integration to the Chef provisioners
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Install Vagrant 1.1.x from the [Vagrant downloads page](http://downloads.vagrantup.com/)
|
12
|
+
|
13
|
+
Install the Berkshelf Vagrant plugin
|
14
|
+
|
15
|
+
$ vagrant plugin install berkshelf-vagrant
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
The Berkshelf Vagrant plugin automatically hooks into the Vagrant provisioning middleware; theres no need to perform any additional steps after installation.
|
20
|
+
|
21
|
+
Just ensure that you have a Berksfile in the directory with your Vagrantfile and when you run `vagrant up`, `vagrant provision`, or `vagrant destroy` the Berkshelf integration will automatically kick in!
|
22
|
+
|
23
|
+
# Authors
|
24
|
+
- Jamie Winsor (<reset@riotgames.com>)
|
25
|
+
|
26
|
+
Thank you to all of our [Contributors](https://github.com/RiotGames/berkshelf-vagrant/graphs/contributors), testers, and users.
|
27
|
+
|
28
|
+
If you'd like to contribute, please see our [contribution guidelines](https://github.com/RiotGames/berkshelf-vagrant/blob/master/CONTRIBUTING.md) first.
|
data/Thorfile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require 'bundler'
|
5
|
+
require 'bundler/setup'
|
6
|
+
require 'thor/rake_compat'
|
7
|
+
|
8
|
+
require 'berkshelf/vagrant'
|
9
|
+
|
10
|
+
class Default < Thor
|
11
|
+
class Gem < Thor
|
12
|
+
include Thor::RakeCompat
|
13
|
+
Bundler::GemHelper.install_tasks
|
14
|
+
|
15
|
+
namespace :gem
|
16
|
+
|
17
|
+
desc "build", "Build berkshelf-vagrant-#{Berkshelf::Vagrant::VERSION}.gem into the pkg directory"
|
18
|
+
def build
|
19
|
+
Rake::Task["build"].execute
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "release", "Create tag v#{Berkshelf::Vagrant::VERSION} and build and push berkshelf-vagrant-#{Berkshelf::Vagrant::VERSION}.gem to Rubygems"
|
23
|
+
def release
|
24
|
+
Rake::Task["release"].execute
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "install", "Build and install berkshelf-vagrant-#{Berkshelf::Vagrant::VERSION}.gem into system gems"
|
28
|
+
def install
|
29
|
+
Rake::Task["install"].execute
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Spec < Thor
|
34
|
+
include Thor::Actions
|
35
|
+
|
36
|
+
namespace :spec
|
37
|
+
default_task :unit
|
38
|
+
|
39
|
+
desc "ci", "Run all possible tests on Travis-CI"
|
40
|
+
def ci
|
41
|
+
ENV['CI'] = 'true' # Travis-CI also sets this, but set it here for local testing
|
42
|
+
invoke(:unit)
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "unit", "Run unit tests"
|
46
|
+
def unit
|
47
|
+
unless run_unit
|
48
|
+
exit 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
no_tasks do
|
53
|
+
def run_unit(*flags)
|
54
|
+
run "rspec --color --format=documentation #{flags.join(' ')} spec"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'berkshelf/vagrant/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "berkshelf-vagrant"
|
8
|
+
spec.version = Berkshelf::Vagrant::VERSION
|
9
|
+
spec.authors = [ "Jamie Winsor" ]
|
10
|
+
spec.email = [ "reset@riotgames.com" ]
|
11
|
+
spec.description = %q{A Vagrant plugin to add Berkshelf integration to the Chef provisioners}
|
12
|
+
spec.summary = spec.description
|
13
|
+
spec.homepage = "http://berkshelf.com"
|
14
|
+
spec.license = "Apache 2.0"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
spec.required_ruby_version = ">= 1.9.1"
|
21
|
+
|
22
|
+
spec.add_dependency 'berkshelf', '>= 1.3.0.rc1'
|
23
|
+
|
24
|
+
# Explicit locks to ensure we activate the proper gem versions for Vagrant
|
25
|
+
spec.add_dependency "i18n", "~> 0.6.0"
|
26
|
+
spec.add_dependency "json", ">= 1.5.1", "< 1.8.0"
|
27
|
+
spec.add_dependency "net-ssh", "~> 2.6.6"
|
28
|
+
spec.add_dependency "net-scp", "~> 1.1.0"
|
29
|
+
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
31
|
+
spec.add_development_dependency 'spork'
|
32
|
+
spec.add_development_dependency 'rspec'
|
33
|
+
spec.add_development_dependency 'thor'
|
34
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'berkshelf/vagrant'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
require 'berkshelf'
|
3
|
+
require 'berkshelf/vagrant/version'
|
4
|
+
require 'berkshelf/vagrant/errors'
|
5
|
+
require 'tmpdir'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module Berkshelf
|
9
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
10
|
+
module Vagrant
|
11
|
+
autoload :Action, 'berkshelf/vagrant/action'
|
12
|
+
autoload :Config, 'berkshelf/vagrant/config'
|
13
|
+
autoload :Env, 'berkshelf/vagrant/env'
|
14
|
+
autoload :EnvHelpers, 'berkshelf/vagrant/env_helpers'
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# The path to where shelfs are created on the host machine to be mounted in
|
18
|
+
# Vagrant guests
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
def shelf_path
|
22
|
+
File.join(Berkshelf.berkshelf_path, 'vagrant')
|
23
|
+
end
|
24
|
+
|
25
|
+
# Generate a new shelf to be mounted in a Vagrant guest
|
26
|
+
#
|
27
|
+
# @return [String]
|
28
|
+
# path to the generated shelf
|
29
|
+
def mkshelf
|
30
|
+
unless File.exist?(shelf_path)
|
31
|
+
FileUtils.mkdir_p(shelf_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
Dir.mktmpdir('berkshelf-', shelf_path)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
require 'berkshelf/vagrant/plugin'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
module Action
|
3
|
+
autoload :Clean, 'berkshelf/vagrant/action/clean'
|
4
|
+
autoload :ConfigureChef, 'berkshelf/vagrant/action/configure_chef'
|
5
|
+
autoload :Install, 'berkshelf/vagrant/action/install'
|
6
|
+
autoload :LoadShelf, 'berkshelf/vagrant/action/load_shelf'
|
7
|
+
autoload :SetUI, 'berkshelf/vagrant/action/set_ui'
|
8
|
+
autoload :Upload, 'berkshelf/vagrant/action/upload'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# Return the Berkshelf install middleware stack. When placed in the action chain
|
12
|
+
# this stack will find retrieve and resolve the cookbook dependencies describe
|
13
|
+
# in your configured Berksfile.
|
14
|
+
#
|
15
|
+
# Cookbooks will installed into a temporary directory, called a Shelf, and mounted
|
16
|
+
# into the VM. This mounted path will be appended to the chef_solo.cookbooks_path value.
|
17
|
+
#
|
18
|
+
# @return [::Vagrant::Action::Builder]
|
19
|
+
def install
|
20
|
+
@install ||= ::Vagrant::Action::Builder.new.tap do |b|
|
21
|
+
b.use Berkshelf::Vagrant::Action::Install
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return the Berkshelf upload middleware stack. When placed in the action chain
|
26
|
+
# this stack will upload cookbooks to a Chef Server if the Chef-Client provisioner
|
27
|
+
# is used. The Chef Server where the cookbooks will be uploaded to is the same Chef
|
28
|
+
# Server used in the Chef-Client provisioner.
|
29
|
+
#
|
30
|
+
# Nothing will be done if the Chef-Solo provisioner is used.
|
31
|
+
#
|
32
|
+
# @return [::Vagrant::Action::Builder]
|
33
|
+
def upload
|
34
|
+
@upload ||= ::Vagrant::Action::Builder.new.tap do |b|
|
35
|
+
b.use Berkshelf::Vagrant::Action::Upload
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the Berkshelf clean middleware stack. When placed in the action chain
|
40
|
+
# this stack will clean up any temporary directories or files created by the other
|
41
|
+
# middleware stacks.
|
42
|
+
#
|
43
|
+
# @return [::Vagrant::Action::Builder]
|
44
|
+
def clean
|
45
|
+
@clean ||= ::Vagrant::Action::Builder.new.tap do |b|
|
46
|
+
b.use setup
|
47
|
+
b.use Berkshelf::Vagrant::Action::Clean
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def setup
|
52
|
+
@setup ||= ::Vagrant::Action::Builder.new.tap do |b|
|
53
|
+
b.use ::Vagrant::Action::Builtin::EnvSet, berkshelf: Berkshelf::Vagrant::Env.new
|
54
|
+
b.use Berkshelf::Vagrant::Action::SetUI
|
55
|
+
b.use Berkshelf::Vagrant::Action::LoadShelf
|
56
|
+
b.use Berkshelf::Vagrant::Action::ConfigureChef
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
module Action
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
class Clean
|
5
|
+
include Berkshelf::Vagrant::EnvHelpers
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
if env[:berkshelf].shelf && File.exist?(env[:berkshelf].shelf)
|
13
|
+
env[:berkshelf].ui.info "Cleaning Vagrant's berkshelf"
|
14
|
+
|
15
|
+
FileUtils.remove_dir(env[:berkshelf].shelf, force: true)
|
16
|
+
FileUtils.rm_f(cache_file)
|
17
|
+
env[:berkshelf].shelf = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
@app.call(env)
|
21
|
+
rescue Berkshelf::BerkshelfError => e
|
22
|
+
raise VagrantWrapperError.new(e)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
module Action
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
class ConfigureChef
|
5
|
+
include Berkshelf::Vagrant::EnvHelpers
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
if chef_solo?(env) && env[:berkshelf].shelf
|
13
|
+
provisioners(:chef_solo, env).each do |provisioner|
|
14
|
+
provisioner.config.cookbooks_path = provisioner.config.send(:prepare_folders_config, env[:berkshelf].shelf)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
module Action
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
class Install
|
5
|
+
include Berkshelf::Vagrant::EnvHelpers
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:berkshelf].berksfile = Berkshelf::Berksfile.from_file(env[:global_config].berkshelf.berksfile_path)
|
13
|
+
|
14
|
+
if chef_solo?(env)
|
15
|
+
install(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
@app.call(env)
|
19
|
+
rescue Berkshelf::BerkshelfError => e
|
20
|
+
raise VagrantWrapperError.new(e)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def install(env)
|
26
|
+
env[:berkshelf].ui.info "Updating Vagrant's berkshelf: '#{env[:berkshelf].shelf}'"
|
27
|
+
opts = {
|
28
|
+
path: env[:berkshelf].shelf
|
29
|
+
}.merge(env[:global_config].berkshelf.to_hash).symbolize_keys!
|
30
|
+
env[:berkshelf].berksfile.install(opts)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
module Action
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
class LoadShelf
|
5
|
+
include Berkshelf::Vagrant::EnvHelpers
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
shelf = load_shelf
|
13
|
+
|
14
|
+
if shelf.nil?
|
15
|
+
shelf = cache_shelf(Berkshelf::Vagrant.mkshelf)
|
16
|
+
end
|
17
|
+
|
18
|
+
env[:berkshelf].shelf = shelf
|
19
|
+
|
20
|
+
@app.call(env)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param [String] path
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
def cache_shelf(path)
|
27
|
+
FileUtils.mkdir_p(File.dirname(path))
|
28
|
+
|
29
|
+
File.open(cache_file, 'w+') do |f|
|
30
|
+
f.write(path)
|
31
|
+
end
|
32
|
+
|
33
|
+
path
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String, nil]
|
37
|
+
def load_shelf
|
38
|
+
return nil unless File.exist?(cache_file)
|
39
|
+
|
40
|
+
File.read(cache_file).chomp
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
module Action
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
class Upload
|
5
|
+
include Berkshelf::Vagrant::EnvHelpers
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
if chef_client?(env)
|
13
|
+
upload(env)
|
14
|
+
end
|
15
|
+
|
16
|
+
@app.call(env)
|
17
|
+
rescue Berkshelf::BerkshelfError => e
|
18
|
+
raise VagrantWrapperError.new(e)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def upload(env)
|
24
|
+
provisioners(:chef_client, env).each do |provisioner|
|
25
|
+
env[:berkshelf].ui.info "Uploading cookbooks to '#{provisioner.config.chef_server_url}'"
|
26
|
+
env[:berkshelf].berksfile.upload(
|
27
|
+
server_url: provisioner.config.chef_server_url,
|
28
|
+
client_name: env[:berkshelf].config.chef.node_name,
|
29
|
+
client_key: env[:berkshelf].config.chef.client_key,
|
30
|
+
ssl: {
|
31
|
+
verify: env[:berkshelf].config.ssl.verify
|
32
|
+
}
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
class Config < ::Vagrant.plugin("2", :config)
|
5
|
+
include Berkshelf::Vagrant::EnvHelpers
|
6
|
+
|
7
|
+
# @return [String]
|
8
|
+
# path to the Berksfile to use with Vagrant
|
9
|
+
attr_reader :berksfile_path
|
10
|
+
|
11
|
+
# @return [Array<Symbol>]
|
12
|
+
# only cookbooks in these groups will be installed and copied to
|
13
|
+
# Vagrant's shelf
|
14
|
+
attr_accessor :only
|
15
|
+
|
16
|
+
# @return [Array<Symbol>]
|
17
|
+
# cookbooks in all other groups except for these will be installed
|
18
|
+
# and copied to Vagrant's shelf
|
19
|
+
attr_accessor :except
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@berksfile_path = UNSET_VALUE
|
23
|
+
@except = UNSET_VALUE
|
24
|
+
@only = UNSET_VALUE
|
25
|
+
end
|
26
|
+
|
27
|
+
def finalize!
|
28
|
+
@berksfile_path = File.join(Dir.pwd, Berkshelf::DEFAULT_FILENAME) if @berksfile_path == UNSET_VALUE
|
29
|
+
@except = Array.new if @except == UNSET_VALUE
|
30
|
+
@only = Array.new if @only == UNSET_VALUE
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [String] value
|
34
|
+
def berksfile_path=(value)
|
35
|
+
@berksfile_path = File.expand_path(value)
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param [String] value
|
39
|
+
def client_key=(value)
|
40
|
+
@client_key = File.expand_path(value)
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :to_hash, :instance_variables_hash
|
44
|
+
|
45
|
+
def validate(machine)
|
46
|
+
errors = Array.new
|
47
|
+
|
48
|
+
if !except.empty? && !only.empty?
|
49
|
+
errors.add("A value for berkshelf.empty and berkshelf.only cannot both be defined.")
|
50
|
+
end
|
51
|
+
|
52
|
+
if chef_client?(machine.env)
|
53
|
+
if Berkshelf::Config.instance.chef.node_name.nil?
|
54
|
+
errors.add("A configuration must be set for chef.node_name when using the chef_client provisioner. Run 'berks configure' or edit your configuration.")
|
55
|
+
end
|
56
|
+
|
57
|
+
if Berkshelf::Config.instance.chef.client_key.nil?
|
58
|
+
errors.add("A configuration must be set for chef.client_key when using the chef_client provisioner. Run 'berks configure' or edit your configuration.")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
{ "berkshelf configuration" => errors }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
3
|
+
#
|
4
|
+
# Environment data to build up and persist through the middleware chain
|
5
|
+
class Env
|
6
|
+
# @return [Vagrant::UI::Colored]
|
7
|
+
attr_accessor :ui
|
8
|
+
# @return [Berkshelf::Berksfile]
|
9
|
+
attr_accessor :berksfile
|
10
|
+
# @return [String]
|
11
|
+
attr_accessor :shelf
|
12
|
+
# @return [Berkshelf::Config]
|
13
|
+
attr_accessor :config
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@ui = ::Vagrant::UI::Colored.new('Berkshelf')
|
17
|
+
@config = Berkshelf::Config.instance
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
3
|
+
#
|
4
|
+
# A module of common helper functions that can be mixed into Berkshelf::Vagrant actions
|
5
|
+
module EnvHelpers
|
6
|
+
# A file to persist berkshelf-vagrant specific information in between
|
7
|
+
# Vagrant runs.
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
def cache_file
|
11
|
+
File.join('.vagrant', 'berkshelf')
|
12
|
+
end
|
13
|
+
|
14
|
+
# Filter all of the provisioners of the given vagrant environment with the given name
|
15
|
+
#
|
16
|
+
# @param [Symbol] name
|
17
|
+
# name of provisioner to filter
|
18
|
+
# @param [Vagrant::Environment, Hash] env
|
19
|
+
# environment to inspect
|
20
|
+
#
|
21
|
+
# @return [Array]
|
22
|
+
def provisioners(name, env)
|
23
|
+
config_global = env.respond_to?(:config_global) ? env.config_global : env[:global_config]
|
24
|
+
|
25
|
+
config_global.vm.provisioners.select { |prov| prov.name == name }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Determine if the given vagrant environment contains a chef_solo provisioner
|
29
|
+
#
|
30
|
+
# @param [Vagrant::Environment] env
|
31
|
+
#
|
32
|
+
# @return [Boolean]
|
33
|
+
def chef_solo?(env)
|
34
|
+
provisioners(:chef_solo, env).any?
|
35
|
+
end
|
36
|
+
|
37
|
+
# Determine if the given vagrant environment contains a chef_client provisioner
|
38
|
+
#
|
39
|
+
# @param [Vagrant::Environment] env
|
40
|
+
#
|
41
|
+
# @return [Boolean]
|
42
|
+
def chef_client?(env)
|
43
|
+
provisioners(:chef_client, env).any?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'vagrant/errors'
|
2
|
+
|
3
|
+
module Berkshelf
|
4
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
5
|
+
#
|
6
|
+
# A wrapper for a BerkshelfError for Vagrant. All Berkshelf exceptions should be
|
7
|
+
# wrapped in this proxy object so they are properly handled when Vagrant encounters
|
8
|
+
# an exception.
|
9
|
+
#
|
10
|
+
# @example wrapping an error encountered within the Vagrant plugin
|
11
|
+
# rescue BerkshelfError => e
|
12
|
+
# VagrantWrapperError.new(e)
|
13
|
+
# end
|
14
|
+
class VagrantWrapperError < ::Vagrant::Errors::VagrantError
|
15
|
+
# @param [BerkshelfError]
|
16
|
+
attr_reader :original
|
17
|
+
|
18
|
+
# @param [BerkshelfError] original
|
19
|
+
def initialize(original)
|
20
|
+
@original = original
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"#{original.class}: #{original.to_s}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def method_missing(fun, *args, &block)
|
30
|
+
original.send(fun, *args, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Berkshelf::Vagrant
|
2
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
3
|
+
class Plugin < ::Vagrant.plugin("2")
|
4
|
+
class << self
|
5
|
+
def provision(hook)
|
6
|
+
hook.after(Vagrant::Action::Builtin::Provision, Berkshelf::Vagrant::Action.upload)
|
7
|
+
hook.after(Vagrant::Action::Builtin::Provision, Berkshelf::Vagrant::Action.install)
|
8
|
+
hook.before(Vagrant::Action::Builtin::ConfigValidate, Berkshelf::Vagrant::Action.setup)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
name "berkshelf"
|
13
|
+
description <<-DESC
|
14
|
+
Automatically make available cookbooks to virtual machines provisioned by Chef Solo
|
15
|
+
or Chef Client using Berkshelf.
|
16
|
+
DESC
|
17
|
+
|
18
|
+
action_hook(:berkshelf_provision, :machine_action_up, &method(:provision))
|
19
|
+
action_hook(:berkshelf_provision, :machine_action_provision, &method(:provision))
|
20
|
+
|
21
|
+
action_hook(:berkshelf_cleanup, :machine_action_destroy) do |hook|
|
22
|
+
# @todo this should be appended to the middleware stack instead of hooked in after the
|
23
|
+
# Virtualbox specific destroy step but there is a bug in Vagrant (1.1.0) which
|
24
|
+
# causes appended middleware to run multiple times.
|
25
|
+
hook.after(VagrantPlugins::ProviderVirtualBox::Action::DestroyUnusedNetworkInterfaces, Berkshelf::Vagrant::Action.clean)
|
26
|
+
end
|
27
|
+
|
28
|
+
config(:berkshelf) do
|
29
|
+
Berkshelf::Vagrant::Config
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'spork'
|
4
|
+
|
5
|
+
Spork.prefork do
|
6
|
+
APP_ROOT = File.expand_path('../../', __FILE__)
|
7
|
+
ENV["BERKSHELF_PATH"] = File.join(APP_ROOT, 'spec', 'tmp', 'berkshelf')
|
8
|
+
|
9
|
+
require 'rspec'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.mock_with :rspec
|
13
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
|
+
config.filter_run focus: true
|
15
|
+
config.run_all_when_everything_filtered = true
|
16
|
+
|
17
|
+
config.around(:each) do
|
18
|
+
clean_tmp_path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def clean_tmp_path
|
23
|
+
FileUtils.rm_rf(tmp_path)
|
24
|
+
FileUtils.mkdir_p(tmp_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def tmp_path
|
28
|
+
File.join(APP_ROOT, 'spec', 'tmp')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Spork.each_run do
|
33
|
+
require 'berkshelf/vagrant'
|
34
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Berkshelf::VagrantWrapperError do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
it "proxies messages to the original exception" do
|
7
|
+
original = double('original_error')
|
8
|
+
original.should_receive(:a_message)
|
9
|
+
|
10
|
+
subject.new(original).a_message
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Berkshelf::Vagrant do
|
4
|
+
describe "ClassMethods" do
|
5
|
+
describe "::shelf_path" do
|
6
|
+
it "returns a String" do
|
7
|
+
subject.shelf_path.should be_a(String)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "is a pathname including the berkshelf_path" do
|
11
|
+
subject.shelf_path.should include(Berkshelf.berkshelf_path)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "::mkshelf" do
|
16
|
+
it "returns a String" do
|
17
|
+
subject.mkshelf.should be_a(String)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "is a pathname including the shelf_path" do
|
21
|
+
subject.mkshelf.should include(subject.shelf_path)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: berkshelf-vagrant
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.rc1
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jamie Winsor
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: berkshelf
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.3.0.rc1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.3.0.rc1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: i18n
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.6.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.6.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: json
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.5.1
|
54
|
+
- - <
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.8.0
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.5.1
|
65
|
+
- - <
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.8.0
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: net-ssh
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.6.6
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ~>
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 2.6.6
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: net-scp
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ~>
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 1.1.0
|
92
|
+
type: :runtime
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ~>
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 1.1.0
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: bundler
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ~>
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '1.3'
|
108
|
+
type: :development
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ~>
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '1.3'
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: spork
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: rspec
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
type: :development
|
141
|
+
prerelease: false
|
142
|
+
version_requirements: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ! '>='
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
- !ruby/object:Gem::Dependency
|
149
|
+
name: thor
|
150
|
+
requirement: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ! '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
type: :development
|
157
|
+
prerelease: false
|
158
|
+
version_requirements: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
description: A Vagrant plugin to add Berkshelf integration to the Chef provisioners
|
165
|
+
email:
|
166
|
+
- reset@riotgames.com
|
167
|
+
executables: []
|
168
|
+
extensions: []
|
169
|
+
extra_rdoc_files: []
|
170
|
+
files:
|
171
|
+
- .gitignore
|
172
|
+
- .travis.yml
|
173
|
+
- CHANGELOG.md
|
174
|
+
- CONTRIBUTING.md
|
175
|
+
- Gemfile
|
176
|
+
- Guardfile
|
177
|
+
- LICENSE.txt
|
178
|
+
- README.md
|
179
|
+
- Thorfile
|
180
|
+
- berkshelf-vagrant.gemspec
|
181
|
+
- lib/berkshelf-vagrant.rb
|
182
|
+
- lib/berkshelf/vagrant.rb
|
183
|
+
- lib/berkshelf/vagrant/action.rb
|
184
|
+
- lib/berkshelf/vagrant/action/clean.rb
|
185
|
+
- lib/berkshelf/vagrant/action/configure_chef.rb
|
186
|
+
- lib/berkshelf/vagrant/action/install.rb
|
187
|
+
- lib/berkshelf/vagrant/action/load_shelf.rb
|
188
|
+
- lib/berkshelf/vagrant/action/set_ui.rb
|
189
|
+
- lib/berkshelf/vagrant/action/upload.rb
|
190
|
+
- lib/berkshelf/vagrant/config.rb
|
191
|
+
- lib/berkshelf/vagrant/env.rb
|
192
|
+
- lib/berkshelf/vagrant/env_helpers.rb
|
193
|
+
- lib/berkshelf/vagrant/errors.rb
|
194
|
+
- lib/berkshelf/vagrant/plugin.rb
|
195
|
+
- lib/berkshelf/vagrant/version.rb
|
196
|
+
- spec/spec_helper.rb
|
197
|
+
- spec/unit/berkshelf/vagrant/errors_spec.rb
|
198
|
+
- spec/unit/berkshelf/vagrant_spec.rb
|
199
|
+
homepage: http://berkshelf.com
|
200
|
+
licenses:
|
201
|
+
- Apache 2.0
|
202
|
+
post_install_message:
|
203
|
+
rdoc_options: []
|
204
|
+
require_paths:
|
205
|
+
- lib
|
206
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
207
|
+
none: false
|
208
|
+
requirements:
|
209
|
+
- - ! '>='
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: 1.9.1
|
212
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
|
+
none: false
|
214
|
+
requirements:
|
215
|
+
- - ! '>'
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: 1.3.1
|
218
|
+
requirements: []
|
219
|
+
rubyforge_project:
|
220
|
+
rubygems_version: 1.8.24
|
221
|
+
signing_key:
|
222
|
+
specification_version: 3
|
223
|
+
summary: A Vagrant plugin to add Berkshelf integration to the Chef provisioners
|
224
|
+
test_files:
|
225
|
+
- spec/spec_helper.rb
|
226
|
+
- spec/unit/berkshelf/vagrant/errors_spec.rb
|
227
|
+
- spec/unit/berkshelf/vagrant_spec.rb
|
228
|
+
has_rdoc:
|