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.
@@ -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