Merge pull request #4700 from mitchellh/f-provisioner-names

Named Provisioners
This commit is contained in:
Mitchell Hashimoto 2014-10-23 19:03:38 -07:00
commit 7108462817
6 changed files with 85 additions and 40 deletions

View File

@ -15,7 +15,7 @@ module Vagrant
# Get all the configured provisioners # Get all the configured provisioners
@_provisioner_instances = env[:machine].config.vm.provisioners.map do |provisioner| @_provisioner_instances = env[:machine].config.vm.provisioners.map do |provisioner|
# Instantiate the provisioner # Instantiate the provisioner
klass = Vagrant.plugin("2").manager.provisioners[provisioner.name] klass = Vagrant.plugin("2").manager.provisioners[provisioner.type]
# This can happen in the case the configuration isn't validated. # This can happen in the case the configuration isn't validated.
next nil if !klass next nil if !klass
@ -23,11 +23,12 @@ module Vagrant
result = klass.new(env[:machine], provisioner.config) result = klass.new(env[:machine], provisioner.config)
# Store in the type map so that --provision-with works properly # Store in the type map so that --provision-with works properly
@_provisioner_types[result] = provisioner.name @_provisioner_types[result] = provisioner.type
# Build up the options # Build up the options
options = { options = {
run: provisioner.run, name: provisioner.name,
run: provisioner.run,
} }
# Return the result # Return the result

View File

@ -103,14 +103,20 @@ module Vagrant
provisioner_instances(env).each do |p, options| provisioner_instances(env).each do |p, options|
type_name = type_map[p] type_name = type_map[p]
next if env[:provision_types] && \ next if env[:provision_types] && \
!env[:provision_types].include?(type_name) !env[:provision_types].include?(type_name) && \
!env[:provision_types].include?(options[:name])
# Don't run if sentinel is around and we're not always running # Don't run if sentinel is around and we're not always running
next if !provision_enabled && options[:run] != :always next if !provision_enabled && options[:run] != :always
name = type_name
if options[:name]
name = "#{options[:name]} (#{type_name})"
end
env[:ui].info(I18n.t( env[:ui].info(I18n.t(
"vagrant.actions.vm.provision.beginning", "vagrant.actions.vm.provision.beginning",
provisioner: type_name)) provisioner: name))
env[:hook].call(:provisioner_run, env.merge( env[:hook].call(:provisioner_run, env.merge(
callable: method(:run_provisioner), callable: method(:run_provisioner),

View File

@ -132,8 +132,8 @@ module VagrantPlugins
new_provs = [] new_provs = []
other_provs = other.provisioners.dup other_provs = other.provisioners.dup
@provisioners.each do |p| @provisioners.each do |p|
if p.id if p.name
other_p = other_provs.find { |o| p.id == o.id } other_p = other_provs.find { |o| p.name == o.name }
if other_p if other_p
# There is an override. Take it. # There is an override. Take it.
other_p.config = p.config.merge(other_p.config) other_p.config = p.config.merge(other_p.config)
@ -278,15 +278,30 @@ module VagrantPlugins
end end
def provision(name, **options, &block) def provision(name, **options, &block)
id = options.delete(:id).to_s if options.has_key?(:id) type = name
if options.has_key?(:type)
type = options.delete(:type)
else
name = nil
end
if options.has_key?(:id)
puts "Setting `id` on a provisioner is deprecated. Please use the"
puts "new syntax of `config.vm.provision \"name\", type: \"type\""
puts "where \"name\" is the replacement for `id`. This will be"
puts "fully removed in Vagrant 1.8."
name = id
end
prov = nil prov = nil
if id if name
prov = @provisioners.find { |p| p.id == id } name = name.to_sym
prov = @provisioners.find { |p| p.name == name }
end end
if !prov if !prov
prov = VagrantConfigProvisioner.new(id, name.to_sym) prov = VagrantConfigProvisioner.new(name, type.to_sym)
@provisioners << prov @provisioners << prov
end end

View File

@ -4,16 +4,16 @@ module VagrantPlugins
module Kernel_V2 module Kernel_V2
# Represents a single configured provisioner for a VM. # Represents a single configured provisioner for a VM.
class VagrantConfigProvisioner class VagrantConfigProvisioner
# Unique ID name for this provisioner # Unique name for this provisioner
# #
# @return [String] # @return [String]
attr_reader :id attr_reader :name
# The name of the provisioner that should be registered # The type of the provisioner that should be registered
# as a plugin. # as a plugin.
# #
# @return [Symbol] # @return [Symbol]
attr_reader :name attr_reader :type
# The configuration associated with the provisioner, if there is any. # The configuration associated with the provisioner, if there is any.
# #
@ -31,30 +31,30 @@ module VagrantPlugins
# @return [Boolean] # @return [Boolean]
attr_accessor :preserve_order attr_accessor :preserve_order
def initialize(id, name) def initialize(name, type)
@logger = Log4r::Logger.new("vagrant::config::vm::provisioner") @logger = Log4r::Logger.new("vagrant::config::vm::provisioner")
@logger.debug("Provisioner defined: #{name}") @logger.debug("Provisioner defined: #{name}")
@config = nil @config = nil
@id = id
@invalid = false @invalid = false
@name = name @name = name
@preserve_order = false @preserve_order = false
@run = nil @run = nil
@type = type
# Attempt to find the provisioner... # Attempt to find the provisioner...
if !Vagrant.plugin("2").manager.provisioners[name] if !Vagrant.plugin("2").manager.provisioners[type]
@logger.warn("Provisioner '#{name}' not found.") @logger.warn("Provisioner '#{type}' not found.")
@invalid = true @invalid = true
end end
# Attempt to find the configuration class for this provider # Attempt to find the configuration class for this provider
# if it exists and load the configuration. # if it exists and load the configuration.
@config_class = Vagrant.plugin("2").manager. @config_class = Vagrant.plugin("2").manager.
provisioner_configs[@name] provisioner_configs[@type]
if !@config_class if !@config_class
@logger.info( @logger.info(
"Provisioner config for '#{@name}' not found. Ignoring config.") "Provisioner config for '#{@type}' not found. Ignoring config.")
@config_class = Vagrant::Config::V2::DummyConfig @config_class = Vagrant::Config::V2::DummyConfig
end end
end end

View File

@ -341,8 +341,8 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
end end
it "allows provisioner settings to be overriden" do it "allows provisioner settings to be overriden" do
subject.provision("shell", path: "foo", id: "s") { |s| s.inline = "foo" } subject.provision("s", path: "foo", type: "shell") { |s| s.inline = "foo" }
subject.provision("shell", inline: "bar", id: "s") { |s| s.args = "bar" } subject.provision("s", inline: "bar", type: "shell") { |s| s.args = "bar" }
subject.finalize! subject.finalize!
r = subject.provisioners r = subject.provisioners
@ -412,12 +412,12 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
end end
it "uses the proper order when merging overrides" do it "uses the proper order when merging overrides" do
subject.provision("shell", inline: "foo", id: "original") subject.provision("original", inline: "foo", type: "shell")
subject.provision("shell", inline: "other", id: "other") subject.provision("other", inline: "other", type: "shell")
other = described_class.new other = described_class.new
other.provision("shell", inline: "bar") other.provision("shell", inline: "bar")
other.provision("shell", inline: "foo-overload", id: "original") other.provision("original", inline: "foo-overload", type: "shell")
merged = subject.merge(other) merged = subject.merge(other)
merged_provs = merged.provisioners merged_provs = merged.provisioners
@ -432,13 +432,13 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
end end
it "can preserve order for overrides" do it "can preserve order for overrides" do
subject.provision("shell", inline: "foo", id: "original") subject.provision("original", inline: "foo", type: "shell")
subject.provision("shell", inline: "other", id: "other") subject.provision("other", inline: "other", type: "shell")
other = described_class.new other = described_class.new
other.provision("shell", inline: "bar") other.provision("shell", inline: "bar")
other.provision( other.provision(
"shell", inline: "foo-overload", id: "original", "original", inline: "foo-overload", type: "shell",
preserve_order: true) preserve_order: true)
merged = subject.merge(other) merged = subject.merge(other)

View File

@ -11,7 +11,8 @@ points common to all provisioners that are important to know.
## Configuration ## Configuration
First, every provisioner is configured within your [Vagrantfile](/v2/vagrantfile/index.html) First, every provisioner is configured within your
[Vagrantfile](/v2/vagrantfile/index.html)
using the `config.vm.provision` method call. For example, the Vagrantfile using the `config.vm.provision` method call. For example, the Vagrantfile
below enables shell provisioning: below enables shell provisioning:
@ -44,6 +45,24 @@ it can greatly improve readability. Additionally, some provisioners, like
the Chef provisioner, have special methods that can be called within that the Chef provisioner, have special methods that can be called within that
block to ease configuration that can't be done with the key/value approach. block to ease configuration that can't be done with the key/value approach.
Provisioners can also be named. These names are used cosmetically for output
as well as overriding provisioner settings (covered further below). An example
of naming provisioners is shown below:
```ruby
Vagrant.configure("2") do |config|
# ... other configuration
config.vm.provision "bootstrap", type: "shell" do |s|
s.inline = "echo hello"
end
end
```
Naming provisioners is simple. The first argument to `config.vm.provision`
becomes the name, and then a `type` option is used to specify the provisioner
type, such as `type: "shell"` above.
## Running Provisioners ## Running Provisioners
Provisioners are run in three cases: the initial `vagrant up`, `vagrant Provisioners are run in three cases: the initial `vagrant up`, `vagrant
@ -57,6 +76,8 @@ The `--provision-with` flag can be used if you only want to run a
specific provisioner if you have multiple provisioners specified. For specific provisioner if you have multiple provisioners specified. For
example, if you have a shell and Puppet provisioner and only want to example, if you have a shell and Puppet provisioner and only want to
run the shell one, you can do `vagrant provision --provision-with shell`. run the shell one, you can do `vagrant provision --provision-with shell`.
The arguments to `--provision-with` can be the provisioner type (such as
"shell") or the provisioner name (such as "bootstrap" from above).
## Run Once or Always ## Run Once or Always
@ -118,6 +139,9 @@ The ordering of the provisioners will be to echo "foo", "baz", then
"bar" (note the second one might not be what you expect!). Remember: "bar" (note the second one might not be what you expect!). Remember:
ordering is _outside in_. ordering is _outside in_.
With multiple provisioners, use the `--provision-with` setting along
with names to get more fine grainted control over what is run and when.
## Overriding Provisioner Settings ## Overriding Provisioner Settings
<div class="alert alert-block alert-warn"> <div class="alert alert-block alert-warn">
@ -135,17 +159,16 @@ you may want to define common provisioners in the global configuration
scope of a Vagrantfile, but override certain aspects of them internally. scope of a Vagrantfile, but override certain aspects of them internally.
Vagrant allows you to do this, but has some details to consider. Vagrant allows you to do this, but has some details to consider.
To override settings, you must assign an ID to your provisioner. Then To override settings, you must assign a name to your provisioner.
it is only a matter of specifying the same ID to override:
```ruby ```ruby
Vagrant.configure("2") do |config| Vagrant.configure("2") do |config|
config.vm.provision "shell", config.vm.provision "foo", type: "shell",
inline: "echo foo", id: "foo" inline: "echo foo"
config.vm.define "web" do |web| config.vm.define "web" do |web|
web.vm.provision "shell", web.vm.provision "foo", type: "shell",
inline: "echo bar", id: "foo" inline: "echo bar"
end end
end end
``` ```
@ -162,14 +185,14 @@ below, the output would be "foo" then "bar":
```ruby ```ruby
Vagrant.configure("2") do |config| Vagrant.configure("2") do |config|
config.vm.provision "shell", config.vm.provision "foo", type: "shell",
inline: "echo ORIGINAL!", id: "foo" inline: "echo ORIGINAL!"
config.vm.define "web" do |web| config.vm.define "web" do |web|
web.vm.provision "shell", web.vm.provision "shell",
inline: "echo foo" inline: "echo foo"
web.vm.provision "shell", web.vm.provision "foo", type: "shell",
inline: "echo bar", id: "foo" inline: "echo bar"
end end
end end
``` ```