vagrant-berkshelf 1.2.0
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.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +18 -0
- data/CONTRIBUTING.md +44 -0
- data/Gemfile +35 -0
- data/Guardfile +16 -0
- data/LICENSE.txt +13 -0
- data/README.md +35 -0
- data/Thorfile +58 -0
- data/lib/berkshelf/vagrant.rb +45 -0
- data/lib/berkshelf/vagrant/action.rb +63 -0
- data/lib/berkshelf/vagrant/action/clean.rb +28 -0
- data/lib/berkshelf/vagrant/action/configure_chef.rb +28 -0
- data/lib/berkshelf/vagrant/action/install.rb +71 -0
- data/lib/berkshelf/vagrant/action/load_shelf.rb +50 -0
- data/lib/berkshelf/vagrant/action/set_ui.rb +17 -0
- data/lib/berkshelf/vagrant/action/upload.rb +50 -0
- data/lib/berkshelf/vagrant/config.rb +91 -0
- data/lib/berkshelf/vagrant/env.rb +26 -0
- data/lib/berkshelf/vagrant/env_helpers.rb +64 -0
- data/lib/berkshelf/vagrant/errors.rb +33 -0
- data/lib/berkshelf/vagrant/plugin.rb +42 -0
- data/lib/berkshelf/vagrant/version.rb +5 -0
- data/lib/vagrant-berkshelf.rb +1 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/unit/berkshelf/vagrant/config_spec.rb +97 -0
- data/spec/unit/berkshelf/vagrant/errors_spec.rb +12 -0
- data/spec/unit/berkshelf/vagrant_spec.rb +25 -0
- data/vagrant-berkshelf.gemspec +36 -0
- metadata +230 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
module Action
|
4
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
5
|
+
class Install
|
6
|
+
include Berkshelf::Vagrant::EnvHelpers
|
7
|
+
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
if provision_disabled?(env)
|
14
|
+
env[:berkshelf].ui.info "Skipping Berkshelf with --no-provision"
|
15
|
+
|
16
|
+
return @app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
unless berkshelf_enabled?(env)
|
20
|
+
if File.exist?(env[:global_config].berkshelf.berksfile_path)
|
21
|
+
warn_disabled_but_berksfile_exists(env)
|
22
|
+
end
|
23
|
+
|
24
|
+
return @app.call(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
env[:berkshelf].berksfile = Berkshelf::Berksfile.from_file(env[:global_config].berkshelf.berksfile_path)
|
28
|
+
|
29
|
+
if chef_solo?(env)
|
30
|
+
install(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
@app.call(env)
|
34
|
+
rescue Berkshelf::BerkshelfError => e
|
35
|
+
raise Berkshelf::VagrantWrapperError.new(e)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def install(env)
|
41
|
+
check_vagrant_version(env)
|
42
|
+
env[:berkshelf].ui.info "Updating Vagrant's berkshelf: '#{env[:berkshelf].shelf}'"
|
43
|
+
opts = {
|
44
|
+
path: env[:berkshelf].shelf
|
45
|
+
}.merge(env[:global_config].berkshelf.to_hash).symbolize_keys!
|
46
|
+
env[:berkshelf].berksfile.install(opts)
|
47
|
+
end
|
48
|
+
|
49
|
+
def warn_disabled_but_berksfile_exists(env)
|
50
|
+
env[:berkshelf].ui.warn "Berkshelf plugin is disabled but a Berksfile was found at" +
|
51
|
+
" your configured path: #{env[:global_config].berkshelf.berksfile_path}"
|
52
|
+
env[:berkshelf].ui.warn "Enable the Berkshelf plugin by setting 'config.berkshelf.enabled = true'" +
|
53
|
+
" in your vagrant config"
|
54
|
+
end
|
55
|
+
|
56
|
+
def check_vagrant_version(env)
|
57
|
+
unless Solve::Constraint.new(">= 1.1").satisfies?(::Vagrant::VERSION)
|
58
|
+
raise Berkshelf::VagrantWrapperError.new(RuntimeError.new("vagrant-berkshelf requires Vagrant 1.1 or later."))
|
59
|
+
end
|
60
|
+
|
61
|
+
unless Solve::Constraint.new(::Berkshelf::Vagrant::TESTED_CONSTRAINT).satisfies?(::Vagrant::VERSION)
|
62
|
+
env[:berkshelf].ui.warn "This version of the Berkshelf plugin has not been fully tested on this version of Vagrant."
|
63
|
+
env[:berkshelf].ui.warn "You should check for a newer version of vagrant-berkshelf."
|
64
|
+
env[:berkshelf].ui.warn "If you encounter any errors with this version, please report them at https://github.com/RiotGames/vagrant-berkshelf/issues"
|
65
|
+
env[:berkshelf].ui.warn "You can also join the discussion in #berkshelf on Freenode."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
module Action
|
4
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
5
|
+
class LoadShelf
|
6
|
+
include Berkshelf::Vagrant::EnvHelpers
|
7
|
+
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
unless berkshelf_enabled?(env)
|
14
|
+
return @app.call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
shelf = load_shelf
|
18
|
+
|
19
|
+
if shelf.nil?
|
20
|
+
shelf = cache_shelf(Berkshelf::Vagrant.mkshelf)
|
21
|
+
end
|
22
|
+
|
23
|
+
env[:berkshelf].shelf = shelf
|
24
|
+
|
25
|
+
@app.call(env)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [String] path
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
def cache_shelf(path)
|
32
|
+
FileUtils.mkdir_p(File.dirname(path))
|
33
|
+
|
34
|
+
File.open(cache_file, 'w+') do |f|
|
35
|
+
f.write(path)
|
36
|
+
end
|
37
|
+
|
38
|
+
path
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [String, nil]
|
42
|
+
def load_shelf
|
43
|
+
return nil unless File.exist?(cache_file)
|
44
|
+
|
45
|
+
File.read(cache_file).chomp
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
module Action
|
4
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
5
|
+
class SetUI
|
6
|
+
def initialize(app, env)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
Berkshelf.ui = env[:berkshelf].ui
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
module Action
|
4
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
5
|
+
class Upload
|
6
|
+
include Berkshelf::Vagrant::EnvHelpers
|
7
|
+
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
if provision_disabled?(env)
|
14
|
+
return @app.call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
unless berkshelf_enabled?(env)
|
18
|
+
return @app.call(env)
|
19
|
+
end
|
20
|
+
|
21
|
+
if chef_client?(env)
|
22
|
+
upload(env)
|
23
|
+
end
|
24
|
+
|
25
|
+
@app.call(env)
|
26
|
+
rescue Berkshelf::BerkshelfError => e
|
27
|
+
raise Berkshelf::VagrantWrapperError.new(e)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def upload(env)
|
33
|
+
provisioners(:chef_client, env).each do |provisioner|
|
34
|
+
env[:berkshelf].ui.info "Uploading cookbooks to '#{provisioner.config.chef_server_url}'"
|
35
|
+
env[:berkshelf].berksfile.upload(
|
36
|
+
server_url: provisioner.config.chef_server_url,
|
37
|
+
client_name: env[:berkshelf].config.chef.node_name,
|
38
|
+
client_key: env[:berkshelf].config.chef.client_key,
|
39
|
+
ssl: {
|
40
|
+
verify: env[:berkshelf].config.ssl.verify
|
41
|
+
},
|
42
|
+
force: true,
|
43
|
+
freeze: false
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
class Config < ::Vagrant.plugin("2", :config)
|
5
|
+
# @return [String]
|
6
|
+
# path to the Berksfile to use with Vagrant
|
7
|
+
attr_reader :berksfile_path
|
8
|
+
|
9
|
+
# @return [Boolean]
|
10
|
+
# disable of use Berks in Vagrant
|
11
|
+
attr_accessor :enabled
|
12
|
+
|
13
|
+
# @return [Array<Symbol>]
|
14
|
+
# only cookbooks in these groups will be installed and copied to
|
15
|
+
# Vagrant's shelf
|
16
|
+
attr_accessor :only
|
17
|
+
|
18
|
+
# @return [Array<Symbol>]
|
19
|
+
# cookbooks in all other groups except for these will be installed
|
20
|
+
# and copied to Vagrant's shelf
|
21
|
+
attr_accessor :except
|
22
|
+
|
23
|
+
# @return [String]
|
24
|
+
# the Chef node name (client name) to use to authenticate with the remote
|
25
|
+
# chef server to upload cookbooks when using the chef client provisioner
|
26
|
+
attr_accessor :node_name
|
27
|
+
|
28
|
+
# @return [String]
|
29
|
+
# a filepath to a chef client key to use to authenticate with the remote
|
30
|
+
# chef server to upload cookbooks when using the chef client provisioner
|
31
|
+
attr_accessor :client_key
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
super
|
35
|
+
|
36
|
+
@berksfile_path = File.join(Dir.pwd, Berkshelf::DEFAULT_FILENAME)
|
37
|
+
@except = Array.new
|
38
|
+
@only = Array.new
|
39
|
+
@node_name = Berkshelf::Config.instance.chef.node_name
|
40
|
+
@client_key = Berkshelf::Config.instance.chef.client_key
|
41
|
+
@enabled = File.exist?(@berksfile_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [String] value
|
45
|
+
def berksfile_path=(value)
|
46
|
+
@berksfile_path = File.expand_path(value)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param [String] value
|
50
|
+
def client_key=(value)
|
51
|
+
@client_key = File.expand_path(value)
|
52
|
+
end
|
53
|
+
|
54
|
+
alias_method :to_hash, :instance_variables_hash
|
55
|
+
|
56
|
+
def validate(machine)
|
57
|
+
errors = Array.new
|
58
|
+
|
59
|
+
unless [TrueClass, FalseClass].include?(enabled.class)
|
60
|
+
errors << "A value for berkshelf.enabled can be true or false."
|
61
|
+
end
|
62
|
+
|
63
|
+
if enabled
|
64
|
+
if machine.config.berkshelf.berksfile_path.nil?
|
65
|
+
errors << "berkshelf.berksfile_path cannot be nil."
|
66
|
+
end
|
67
|
+
|
68
|
+
unless File.exist?(machine.config.berkshelf.berksfile_path)
|
69
|
+
errors << "No Berskfile was found at #{machine.config.berkshelf.berksfile_path}."
|
70
|
+
end
|
71
|
+
|
72
|
+
if !except.empty? && !only.empty?
|
73
|
+
errors << "A value for berkshelf.empty and berkshelf.only cannot both be defined."
|
74
|
+
end
|
75
|
+
|
76
|
+
if machine.env.config_global.vm.provisioners.any? { |prov| prov.name == :chef_client }
|
77
|
+
if machine.config.berkshelf.node_name.nil?
|
78
|
+
errors << "A configuration must be set for chef.node_name when using the chef_client provisioner. Run 'berks configure' or edit your configuration."
|
79
|
+
end
|
80
|
+
|
81
|
+
if machine.config.berkshelf.client_key.nil?
|
82
|
+
errors << "A configuration must be set for chef.client_key when using the chef_client provisioner. Run 'berks configure' or edit your configuration."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
{ "berkshelf configuration" => errors }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
#
|
5
|
+
# Environment data to build up and persist through the middleware chain
|
6
|
+
class Env
|
7
|
+
# @return [Vagrant::UI::Colored]
|
8
|
+
attr_accessor :ui
|
9
|
+
# @return [Berkshelf::Berksfile]
|
10
|
+
attr_accessor :berksfile
|
11
|
+
# @return [String]
|
12
|
+
attr_accessor :shelf
|
13
|
+
# @return [Berkshelf::Config]
|
14
|
+
attr_accessor :config
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
if Gem::Version.new(::Vagrant::VERSION) >= Gem::Version.new("1.2")
|
18
|
+
@ui = ::Vagrant::UI::Colored.new.scope('Berkshelf')
|
19
|
+
else
|
20
|
+
@ui = ::Vagrant::UI::Colored.new('Berkshelf')
|
21
|
+
end
|
22
|
+
@config = Berkshelf::Config.instance
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
#
|
5
|
+
# A module of common helper functions that can be mixed into Berkshelf::Vagrant actions
|
6
|
+
module EnvHelpers
|
7
|
+
# A file to persist vagrant-berkshelf specific information in between
|
8
|
+
# Vagrant runs.
|
9
|
+
#
|
10
|
+
# @return [String]
|
11
|
+
def cache_file
|
12
|
+
File.join('.vagrant', 'berkshelf')
|
13
|
+
end
|
14
|
+
|
15
|
+
# Filter all of the provisioners of the given vagrant environment with the given name
|
16
|
+
#
|
17
|
+
# @param [Symbol] name
|
18
|
+
# name of provisioner to filter
|
19
|
+
# @param [Vagrant::Environment, Hash] env
|
20
|
+
# environment to inspect
|
21
|
+
#
|
22
|
+
# @return [Array]
|
23
|
+
def provisioners(name, env)
|
24
|
+
env[:machine].config.vm.provisioners.select { |prov| prov.name == name }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Determine if the given vagrant environment contains a chef_solo provisioner
|
28
|
+
#
|
29
|
+
# @param [Vagrant::Environment] env
|
30
|
+
#
|
31
|
+
# @return [Boolean]
|
32
|
+
def chef_solo?(env)
|
33
|
+
provisioners(:chef_solo, env).any?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Determine if the given vagrant environment contains a chef_client provisioner
|
37
|
+
#
|
38
|
+
# @param [Vagrant::Environment] env
|
39
|
+
#
|
40
|
+
# @return [Boolean]
|
41
|
+
def chef_client?(env)
|
42
|
+
provisioners(:chef_client, env).any?
|
43
|
+
end
|
44
|
+
|
45
|
+
# Determine if the Berkshelf plugin should be run for the given environment
|
46
|
+
#
|
47
|
+
# @param [Vagrant::Environment] env
|
48
|
+
#
|
49
|
+
# @return [Boolean]
|
50
|
+
def berkshelf_enabled?(env)
|
51
|
+
env[:global_config].berkshelf.enabled
|
52
|
+
end
|
53
|
+
|
54
|
+
# Determine if --no-provision was specified
|
55
|
+
#
|
56
|
+
# @param [Vagrant::Environment] env
|
57
|
+
#
|
58
|
+
# @return [Boolean]
|
59
|
+
def provision_disabled?(env)
|
60
|
+
env.has_key?(:provision_enabled) && !env[:provision_enabled]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
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,42 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Vagrant
|
3
|
+
# @author Jamie Winsor <reset@riotgames.com>
|
4
|
+
TESTED_CONSTRAINT="<= 1.2.1"
|
5
|
+
class Plugin < ::Vagrant.plugin("2")
|
6
|
+
class << self
|
7
|
+
def provision(hook)
|
8
|
+
hook.after(::Vagrant::Action::Builtin::Provision, Berkshelf::Vagrant::Action.upload)
|
9
|
+
hook.after(::Vagrant::Action::Builtin::Provision, Berkshelf::Vagrant::Action.install)
|
10
|
+
|
11
|
+
if ::VagrantPlugins.const_defined?(:AWS)
|
12
|
+
hook.after(::VagrantPlugins::AWS::Action::TimedProvision, Berkshelf::Vagrant::Action.upload)
|
13
|
+
hook.after(::VagrantPlugins::AWS::Action::TimedProvision, Berkshelf::Vagrant::Action.install)
|
14
|
+
end
|
15
|
+
|
16
|
+
hook.before(::Vagrant::Action::Builtin::ConfigValidate, Berkshelf::Vagrant::Action.setup)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
name "berkshelf"
|
21
|
+
description <<-DESC
|
22
|
+
Automatically make available cookbooks to virtual machines provisioned by Chef Solo
|
23
|
+
or Chef Client using Berkshelf.
|
24
|
+
DESC
|
25
|
+
|
26
|
+
action_hook(:berkshelf_provision, :machine_action_up, &method(:provision))
|
27
|
+
action_hook(:berkshelf_provision, :machine_action_reload, &method(:provision))
|
28
|
+
action_hook(:berkshelf_provision, :machine_action_provision, &method(:provision))
|
29
|
+
|
30
|
+
action_hook(:berkshelf_cleanup, :machine_action_destroy) do |hook|
|
31
|
+
# @todo this should be appended to the middleware stack instead of hooked in after the
|
32
|
+
# Virtualbox specific destroy step but there is a bug in Vagrant (1.1.0) which
|
33
|
+
# causes appended middleware to run multiple times.
|
34
|
+
hook.after(VagrantPlugins::ProviderVirtualBox::Action::DestroyUnusedNetworkInterfaces, Berkshelf::Vagrant::Action.clean)
|
35
|
+
end
|
36
|
+
|
37
|
+
config(:berkshelf) do
|
38
|
+
Berkshelf::Vagrant::Config
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|