Merge pull request #11043 from briancain/provisioner-enhancements
Introduce new Provisioner options: before and after
This commit is contained in:
commit
f74239bed9
|
@ -29,15 +29,92 @@ module Vagrant
|
|||
options = {
|
||||
name: provisioner.name,
|
||||
run: provisioner.run,
|
||||
before: provisioner.before,
|
||||
after: provisioner.after,
|
||||
}
|
||||
|
||||
# Return the result
|
||||
[result, options]
|
||||
end
|
||||
|
||||
@_provisioner_instances = sort_provisioner_instances(@_provisioner_instances)
|
||||
return @_provisioner_instances.compact
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Sorts provisioners based on order specified with before/after options
|
||||
#
|
||||
# @return [Array<Provisioner, Hash>]
|
||||
def sort_provisioner_instances(pvs)
|
||||
final_provs = []
|
||||
root_provs = []
|
||||
# extract root provisioners
|
||||
root_provs = pvs.find_all { |_, o| o[:before].nil? && o[:after].nil? }
|
||||
|
||||
if root_provs.size == pvs.size
|
||||
# no dependencies found
|
||||
return pvs
|
||||
end
|
||||
|
||||
# ensure placeholder variables are Arrays
|
||||
dep_provs = []
|
||||
each_provs = []
|
||||
all_provs = []
|
||||
|
||||
# extract dependency provisioners
|
||||
dep_provs = pvs.find_all { |_, o| o[:before].is_a?(String) || o[:after].is_a?(String) }
|
||||
# extract each provisioners
|
||||
each_provs = pvs.find_all { |_,o| o[:before] == :each || o[:after] == :each }
|
||||
# extract all provisioners
|
||||
all_provs = pvs.find_all { |_,o| o[:before] == :all || o[:after] == :all }
|
||||
|
||||
# insert provisioners in order
|
||||
final_provs = root_provs
|
||||
dep_provs.each do |p,options|
|
||||
idx = 0
|
||||
if options[:before]
|
||||
idx = final_provs.index { |_, o| o[:name].to_s == options[:before] }
|
||||
final_provs.insert(idx, [p, options])
|
||||
elsif options[:after]
|
||||
idx = final_provs.index { |_, o| o[:name].to_s == options[:after] }
|
||||
idx += 1
|
||||
final_provs.insert(idx, [p, options])
|
||||
end
|
||||
end
|
||||
|
||||
# Add :each and :all provisioners in reverse to preserve order in Vagrantfile
|
||||
tmp_final_provs = []
|
||||
final_provs.each_with_index do |(prv,o), i|
|
||||
tmp_before = []
|
||||
tmp_after = []
|
||||
|
||||
each_provs.reverse_each do |p, options|
|
||||
if options[:before]
|
||||
tmp_before << [p,options]
|
||||
elsif options[:after]
|
||||
tmp_after << [p,options]
|
||||
end
|
||||
end
|
||||
|
||||
tmp_final_provs += tmp_before unless tmp_before.empty?
|
||||
tmp_final_provs += [[prv,o]]
|
||||
tmp_final_provs += tmp_after unless tmp_after.empty?
|
||||
end
|
||||
final_provs = tmp_final_provs
|
||||
|
||||
# Add all to final array
|
||||
all_provs.reverse_each do |p,options|
|
||||
if options[:before]
|
||||
final_provs.insert(0, [p,options])
|
||||
elsif options[:after]
|
||||
final_provs.push([p,options])
|
||||
end
|
||||
end
|
||||
|
||||
return final_provs
|
||||
end
|
||||
|
||||
# This will return a mapping of a provisioner instance to its
|
||||
# type.
|
||||
def provisioner_type_map(env)
|
||||
|
@ -47,6 +124,13 @@ module Vagrant
|
|||
# Return the type map
|
||||
@_provisioner_types
|
||||
end
|
||||
|
||||
# @private
|
||||
# Reset the cached values for platform. This is not considered a public
|
||||
# API and should only be used for testing.
|
||||
def self.reset!
|
||||
instance_variables.each(&method(:remove_instance_variable))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ require "vagrant/action/builtin/mixin_synced_folders"
|
|||
require "vagrant/config/v2/util"
|
||||
require "vagrant/util/platform"
|
||||
require "vagrant/util/presence"
|
||||
require "vagrant/util/experimental"
|
||||
|
||||
require File.expand_path("../vm_provisioner", __FILE__)
|
||||
require File.expand_path("../vm_subvm", __FILE__)
|
||||
|
@ -331,7 +332,19 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
if !prov
|
||||
prov = VagrantConfigProvisioner.new(name, type.to_sym)
|
||||
if options.key?(:before)
|
||||
before = options.delete(:before)
|
||||
end
|
||||
if options.key?(:after)
|
||||
after = options.delete(:after)
|
||||
end
|
||||
|
||||
if Vagrant::Util::Experimental.feature_enabled?("dependency_provisioners")
|
||||
opts = {before: before, after: after}
|
||||
prov = VagrantConfigProvisioner.new(name, type.to_sym, opts)
|
||||
else
|
||||
prov = VagrantConfigProvisioner.new(name, type.to_sym)
|
||||
end
|
||||
@provisioners << prov
|
||||
end
|
||||
|
||||
|
@ -760,6 +773,11 @@ module VagrantPlugins
|
|||
next
|
||||
end
|
||||
|
||||
provisioner_errors = vm_provisioner.validate(machine, @provisioners)
|
||||
if provisioner_errors
|
||||
errors = Vagrant::Config::V2::Util.merge_errors(errors, provisioner_errors)
|
||||
end
|
||||
|
||||
if vm_provisioner.config
|
||||
provisioner_errors = vm_provisioner.config.validate(machine)
|
||||
if provisioner_errors
|
||||
|
|
|
@ -3,7 +3,10 @@ require 'log4r'
|
|||
module VagrantPlugins
|
||||
module Kernel_V2
|
||||
# Represents a single configured provisioner for a VM.
|
||||
class VagrantConfigProvisioner
|
||||
class VagrantConfigProvisioner < Vagrant.plugin("2", :config)
|
||||
# Defaults
|
||||
VALID_BEFORE_AFTER_TYPES = [:each, :all].freeze
|
||||
|
||||
# Unique name for this provisioner
|
||||
#
|
||||
# @return [String]
|
||||
|
@ -29,7 +32,7 @@ module VagrantPlugins
|
|||
# @return [Object]
|
||||
attr_accessor :config
|
||||
|
||||
# When to run this provisioner. Either "once" or "always"
|
||||
# When to run this provisioner. Either "once", "always", or "never"
|
||||
#
|
||||
# @return [String]
|
||||
attr_accessor :run
|
||||
|
@ -40,7 +43,17 @@ module VagrantPlugins
|
|||
# @return [Boolean]
|
||||
attr_accessor :preserve_order
|
||||
|
||||
def initialize(name, type)
|
||||
# The name of a provisioner to run before it has started
|
||||
#
|
||||
# @return [String, Symbol]
|
||||
attr_accessor :before
|
||||
|
||||
# The name of a provisioner to run after it is finished
|
||||
#
|
||||
# @return [String, Symbol]
|
||||
attr_accessor :after
|
||||
|
||||
def initialize(name, type, **options)
|
||||
@logger = Log4r::Logger.new("vagrant::config::vm::provisioner")
|
||||
@logger.debug("Provisioner defined: #{name}")
|
||||
|
||||
|
@ -51,6 +64,8 @@ module VagrantPlugins
|
|||
@preserve_order = false
|
||||
@run = nil
|
||||
@type = type
|
||||
@before = options[:before]
|
||||
@after = options[:after]
|
||||
|
||||
# Attempt to find the provisioner...
|
||||
if !Vagrant.plugin("2").manager.provisioners[type]
|
||||
|
@ -90,6 +105,75 @@ module VagrantPlugins
|
|||
@config.finalize!
|
||||
end
|
||||
|
||||
# Validates the before/after options
|
||||
#
|
||||
# @param [Vagrant::Machine] machine - machine to validate against
|
||||
# @param [Array] provisioners - Array of defined provisioners for the guest machine
|
||||
# @return [Array] array of strings of error messages from config option validation
|
||||
def validate(machine, provisioners)
|
||||
errors = _detected_errors
|
||||
|
||||
provisioner_names = provisioners.map { |i| i.name.to_s if i.name != name }.compact
|
||||
|
||||
if @before && @after
|
||||
errors << I18n.t("vagrant.provisioners.base.both_before_after_set")
|
||||
end
|
||||
|
||||
if @before
|
||||
if !VALID_BEFORE_AFTER_TYPES.include?(@before)
|
||||
if @before.is_a?(Symbol) && !VALID_BEFORE_AFTER_TYPES.include?(@before)
|
||||
errors << I18n.t("vagrant.provisioners.base.invalid_alias_value", opt: "before", alias: VALID_BEFORE_AFTER_TYPES.join(", "))
|
||||
elsif !@before.is_a?(String) && !VALID_BEFORE_AFTER_TYPES.include?(@before)
|
||||
errors << I18n.t("vagrant.provisioners.base.wrong_type", opt: "before")
|
||||
end
|
||||
|
||||
if !provisioner_names.include?(@before)
|
||||
errors << I18n.t("vagrant.provisioners.base.missing_provisioner_name",
|
||||
name: @before,
|
||||
machine_name: machine.name,
|
||||
action: "before",
|
||||
provisioner_name: @name)
|
||||
end
|
||||
|
||||
dep_prov = provisioners.find_all { |i| i.name.to_s == @before && (i.before || i.after) }
|
||||
|
||||
if !dep_prov.empty?
|
||||
errors << I18n.t("vagrant.provisioners.base.dependency_provisioner_dependency",
|
||||
name: @name,
|
||||
dep_name: dep_prov.first.name.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if @after
|
||||
if !VALID_BEFORE_AFTER_TYPES.include?(@after)
|
||||
if @after.is_a?(Symbol)
|
||||
errors << I18n.t("vagrant.provisioners.base.invalid_alias_value", opt: "after", alias: VALID_BEFORE_AFTER_TYPES.join(", "))
|
||||
elsif !@after.is_a?(String)
|
||||
errors << I18n.t("vagrant.provisioners.base.wrong_type", opt: "after")
|
||||
end
|
||||
|
||||
if !provisioner_names.include?(@after)
|
||||
errors << I18n.t("vagrant.provisioners.base.missing_provisioner_name",
|
||||
name: @after,
|
||||
machine_name: machine.name,
|
||||
action: "after",
|
||||
provisioner_name: @name)
|
||||
end
|
||||
|
||||
dep_prov = provisioners.find_all { |i| i.name.to_s == @after && (i.before || i.after) }
|
||||
|
||||
if !dep_prov.empty?
|
||||
errors << I18n.t("vagrant.provisioners.base.dependency_provisioner_dependency",
|
||||
name: @name,
|
||||
dep_name: dep_prov.first.name.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
{"provisioner" => errors}
|
||||
end
|
||||
|
||||
# Returns whether the provisioner used was invalid or not. A provisioner
|
||||
# is invalid if it can't be found.
|
||||
#
|
||||
|
|
|
@ -2486,6 +2486,17 @@ en:
|
|||
VirtualBox has successfully been installed!
|
||||
|
||||
provisioners:
|
||||
base:
|
||||
both_before_after_set: |-
|
||||
Dependency provisioners cannot currently set both `before` and `after` options.
|
||||
dependency_provisioner_dependency: |-
|
||||
Dependency provisioner "%{name}" relies on another dependency provisioner "%{dep_name}". This is currently not supported.
|
||||
invalid_alias_value: |-
|
||||
Provisioner option `%{opt}` is not set as a valid type. Must be a string, or one of the alias shortcuts: %{alias}
|
||||
missing_provisioner_name: |-
|
||||
Could not find provisioner name `%{name}` defined for machine `%{machine_name}` to run provisioner "%{provisioner_name}" `%{action}`.
|
||||
wrong_type: |-
|
||||
Provisioner option `%{opt}` is not set as a valid type. Must be a string.
|
||||
chef:
|
||||
chef_not_detected: |-
|
||||
The chef binary (either `chef-solo` or `chef-client`) was not found on
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
require Vagrant.source_root.join("plugins/kernel_v2/config/vm")
|
||||
|
||||
require "vagrant/action/builtin/mixin_provisioners"
|
||||
|
||||
describe Vagrant::Action::Builtin::MixinProvisioners do
|
||||
include_context "unit"
|
||||
|
||||
let(:sandbox) { isolated_environment }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
sandbox.vagrantfile("")
|
||||
sandbox.create_vagrant_env
|
||||
end
|
||||
|
||||
let(:provisioner_config){ {} }
|
||||
let(:provisioner_one) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("spec-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_two) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("spec-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
|
||||
let(:provisioner_instances) { [provisioner_one,provisioner_two] }
|
||||
|
||||
let(:ui) { double("ui") }
|
||||
let(:vm) { double("vm", provisioners: provisioner_instances) }
|
||||
let(:config) { double("config", vm: vm) }
|
||||
let(:machine) { double("machine", ui: ui, config: config) }
|
||||
|
||||
let(:env) {{ machine: machine, ui: machine.ui, root_path: Pathname.new(".") }}
|
||||
|
||||
subject do
|
||||
Class.new do
|
||||
extend Vagrant::Action::Builtin::MixinProvisioners
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
sandbox.close
|
||||
described_class.reset!
|
||||
end
|
||||
|
||||
describe "#provisioner_instances" do
|
||||
it "returns all the instances of configured provisioners" do
|
||||
result = subject.provisioner_instances(env)
|
||||
expect(result.size).to eq(provisioner_instances.size)
|
||||
shell_one = result.first
|
||||
expect(shell_one.first).to be_a(VagrantPlugins::Shell::Provisioner)
|
||||
shell_two = result[1]
|
||||
expect(shell_two.first).to be_a(VagrantPlugins::Shell::Provisioner)
|
||||
end
|
||||
end
|
||||
|
||||
context "#sort_provisioner_instances" do
|
||||
describe "with no dependency provisioners" do
|
||||
it "returns the original array" do
|
||||
result = subject.provisioner_instances(env)
|
||||
expect(result.size).to eq(provisioner_instances.size)
|
||||
shell_one = result.first
|
||||
expect(shell_one.first).to be_a(VagrantPlugins::Shell::Provisioner)
|
||||
shell_two = result[1]
|
||||
expect(shell_two.first).to be_a(VagrantPlugins::Shell::Provisioner)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with before and after dependency provisioners" do
|
||||
let(:provisioner_config){ {} }
|
||||
let(:provisioner_root) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_before) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("before-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.before = "root-test"
|
||||
prov
|
||||
end
|
||||
let(:provisioner_after) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("after-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.after = "root-test"
|
||||
prov
|
||||
end
|
||||
let(:provisioner_instances) { [provisioner_root,provisioner_before,provisioner_after] }
|
||||
|
||||
it "returns the array in the correct order" do
|
||||
result = subject.provisioner_instances(env)
|
||||
expect(result[0].last[:name]).to eq("before-test")
|
||||
expect(result[1].last[:name]).to eq("root-test")
|
||||
expect(result[2].last[:name]).to eq("after-test")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with before :each dependency provisioners" do
|
||||
let(:provisioner_config){ {} }
|
||||
let(:provisioner_root) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_root2) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root2-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_before) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("before-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.before = :each
|
||||
prov
|
||||
end
|
||||
|
||||
let(:provisioner_instances) { [provisioner_root,provisioner_root2,provisioner_before] }
|
||||
|
||||
it "puts the each shortcut provisioners in place" do
|
||||
result = subject.provisioner_instances(env)
|
||||
|
||||
expect(result[0].last[:name]).to eq("before-test")
|
||||
expect(result[1].last[:name]).to eq("root-test")
|
||||
expect(result[2].last[:name]).to eq("before-test")
|
||||
expect(result[3].last[:name]).to eq("root2-test")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with after :each dependency provisioners" do
|
||||
let(:provisioner_config){ {} }
|
||||
let(:provisioner_root) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_root2) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root2-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_after) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("after-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.after = :each
|
||||
prov
|
||||
end
|
||||
|
||||
let(:provisioner_instances) { [provisioner_root,provisioner_root2,provisioner_after] }
|
||||
|
||||
it "puts the each shortcut provisioners in place" do
|
||||
result = subject.provisioner_instances(env)
|
||||
|
||||
expect(result[0].last[:name]).to eq("root-test")
|
||||
expect(result[1].last[:name]).to eq("after-test")
|
||||
expect(result[2].last[:name]).to eq("root2-test")
|
||||
expect(result[3].last[:name]).to eq("after-test")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with before and after :each dependency provisioners" do
|
||||
let(:provisioner_config){ {} }
|
||||
let(:provisioner_root) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_root2) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root2-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_after) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("after-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.after = :each
|
||||
prov
|
||||
end
|
||||
let(:provisioner_before) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("before-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.before = :each
|
||||
prov
|
||||
end
|
||||
|
||||
let(:provisioner_instances) { [provisioner_root,provisioner_root2,provisioner_before,provisioner_after] }
|
||||
|
||||
it "puts the each shortcut provisioners in place" do
|
||||
result = subject.provisioner_instances(env)
|
||||
|
||||
expect(result[0].last[:name]).to eq("before-test")
|
||||
expect(result[1].last[:name]).to eq("root-test")
|
||||
expect(result[2].last[:name]).to eq("after-test")
|
||||
expect(result[3].last[:name]).to eq("before-test")
|
||||
expect(result[4].last[:name]).to eq("root2-test")
|
||||
expect(result[5].last[:name]).to eq("after-test")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with before and after :all dependency provisioners" do
|
||||
let(:provisioner_config){ {} }
|
||||
let(:provisioner_root) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_root2) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("root2-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov
|
||||
end
|
||||
let(:provisioner_after) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("after-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.after = :all
|
||||
prov
|
||||
end
|
||||
let(:provisioner_before) do
|
||||
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("before-test", :shell)
|
||||
prov.config = provisioner_config
|
||||
prov.before = :all
|
||||
prov
|
||||
end
|
||||
|
||||
let(:provisioner_instances) { [provisioner_root,provisioner_root2,provisioner_before,provisioner_after] }
|
||||
|
||||
it "puts the each shortcut provisioners in place" do
|
||||
result = subject.provisioner_instances(env)
|
||||
|
||||
expect(result[0].last[:name]).to eq("before-test")
|
||||
expect(result[1].last[:name]).to eq("root-test")
|
||||
expect(result[2].last[:name]).to eq("root2-test")
|
||||
expect(result[3].last[:name]).to eq("after-test")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -47,3 +47,10 @@ This is a list of all the valid experimental features that Vagrant recognizes:
|
|||
|
||||
Enabling this feature allows triggers to recognize and execute `:type` triggers.
|
||||
More information about how these should be used can be found on the [trigger documentation page](/docs/triggers/configuration.html#trigger-types)
|
||||
|
||||
### `dependency_provisioners`
|
||||
|
||||
Enabling this feature allows all provisioners to specify `before` and `after`
|
||||
options. These options allow provisioners to be configured to run before or after
|
||||
any given "root" provisioner. more information about these options can be found
|
||||
on the [base provisioner documentation page](/docs/provisioning/basic_usage.html)
|
||||
|
|
|
@ -14,6 +14,31 @@ While Vagrant offers multiple options for how you are able to provision
|
|||
your machine, there is a standard usage pattern as well as some important
|
||||
points common to all provisioners that are important to know.
|
||||
|
||||
## Options
|
||||
|
||||
Every Vagrant provisioner accepts a few base options. The only required
|
||||
option is what type a provisioner is:
|
||||
|
||||
|
||||
* `name` (string) - The name of the provisioner. Note: if no `type` option is given,
|
||||
this option _must_ be the type of provisioner it is. If you wish to give it a
|
||||
different name you must also set the `type` option to define the kind of provisioner.
|
||||
* `type` (string) - The class of provisioner to configure. (i.e. `"shell"` or `"file"`)
|
||||
* `before` (string or symbol) - The exact name of an already defined provisioner
|
||||
that _this_ provisioner should run before. If defined as a symbol, its only valid
|
||||
values are `:each` or `:all`, which makes the provisioner run before each and
|
||||
every root provisioner, or before all provisioners respectively.
|
||||
__Note__: This option is currently experimental, so it needs to be explicitly
|
||||
enabled to work. More info can be found [here](/docs/experimental/index.html).
|
||||
* `after` (string or symbol) - The exact name of an already defined provisioner
|
||||
that _this_ provisioner should run after. If defined as a symbol, its only valid
|
||||
values are `:each` or `:all`, which makes the provisioner run after each and
|
||||
every root provisioner, or before all provisioners respectively.
|
||||
__Note__: This option is currently experimental, so it needs to be explicitly
|
||||
enabled to work. More info can be found [here](/docs/experimental/index.html).
|
||||
|
||||
More information about how to use `before` and `after` options can be read [below](#dependency-provisioners).
|
||||
|
||||
## Configuration
|
||||
|
||||
First, every provisioner is configured within your
|
||||
|
@ -226,3 +251,118 @@ Vagrant.configure("2") do |config|
|
|||
inline: "echo SECOND!"
|
||||
end
|
||||
```
|
||||
|
||||
## Dependency Provisioners
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Warning: Advanced Topic!</strong> Dependency provisioners are
|
||||
an advanced topic. If you are just getting started with Vagrant, you can
|
||||
safely skip this.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Warning!</strong> This feature is still experimental and may break or
|
||||
change in between releases. Use at your own risk.
|
||||
|
||||
This feature currently reqiures the experimental flag to be used. To explicitly enable this feature, you can set the experimental flag to:
|
||||
|
||||
```
|
||||
VAGRANT_EXPERIMENTAL="dependency_provisioners"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
for more info. Without this flag enabled, provisioners with the `before` and
|
||||
`after` option will be ignored.
|
||||
</div>
|
||||
|
||||
If a provisioner has been configured using the `before` or `after` options, it
|
||||
is considered a _Dependency Provisioner_. This means it has been configured to
|
||||
run before or after a _Root Provisioner_, which does not have the `before` or
|
||||
`after` options configured.
|
||||
|
||||
Dependency provisioners also have two valid shortcuts:
|
||||
`:each` and `:all`.
|
||||
|
||||
**Note**: As of 2.2.6, dependency provisioners cannot rely on other dependency
|
||||
provisioners and is considered a configuration state error in Vagrant. If you must
|
||||
order dependency provisioners, you can still order them by the order they are defined
|
||||
inside your Vagrantfile.
|
||||
|
||||
An example of these dependency provisioners can be seen below:
|
||||
|
||||
```ruby
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.provision "C", after: "B", type: "shell", inline:<<-SHELL
|
||||
echo 'C'
|
||||
SHELL
|
||||
config.vm.provision "B", type: "shell", inline:<<-SHELL
|
||||
echo 'B'
|
||||
SHELL
|
||||
config.vm.provision "D", type: "shell", inline:<<-SHELL
|
||||
echo 'D'
|
||||
SHELL
|
||||
config.vm.provision "A", before: "B", type: "shell", inline:<<-SHELL
|
||||
echo 'A'
|
||||
SHELL
|
||||
config.vm.provision "Separate After", after: :each, type: "shell", inline:<<-SHELL
|
||||
echo '=============================='
|
||||
SHELL
|
||||
config.vm.provision "Separate Before", before: :each, type: "shell", inline:<<-SHELL
|
||||
echo '++++++++++++++++++++++++++++++'
|
||||
SHELL
|
||||
config.vm.provision "Hello", before: :all, type: "shell", inline:<<-SHELL
|
||||
echo 'HERE WE GO!!'
|
||||
SHELL
|
||||
config.vm.provision "Goodbye", after: :all, type: "shell", inline:<<-SHELL
|
||||
echo 'The end'
|
||||
SHELL
|
||||
end
|
||||
```
|
||||
|
||||
The result of running `vagrant provision` with a guest configured above:
|
||||
|
||||
```
|
||||
==> default: Running provisioner: Hello (shell)...
|
||||
default: Running: inline script
|
||||
default: HERE WE GO!!
|
||||
==> default: Running provisioner: Separate Before (shell)...
|
||||
default: Running: inline script
|
||||
default: ++++++++++++++++++++++++++++++
|
||||
==> default: Running provisioner: A (shell)...
|
||||
default: Running: inline script
|
||||
default: A
|
||||
==> default: Running provisioner: Separate After (shell)...
|
||||
default: Running: inline script
|
||||
default: ==============================
|
||||
==> default: Running provisioner: Separate Before (shell)...
|
||||
default: Running: inline script
|
||||
default: ++++++++++++++++++++++++++++++
|
||||
==> default: Running provisioner: B (shell)...
|
||||
default: Running: inline script
|
||||
default: B
|
||||
==> default: Running provisioner: Separate After (shell)...
|
||||
default: Running: inline script
|
||||
default: ==============================
|
||||
==> default: Running provisioner: Separate Before (shell)...
|
||||
default: Running: inline script
|
||||
default: ++++++++++++++++++++++++++++++
|
||||
==> default: Running provisioner: C (shell)...
|
||||
default: Running: inline script
|
||||
default: C
|
||||
==> default: Running provisioner: Separate After (shell)...
|
||||
default: Running: inline script
|
||||
default: ==============================
|
||||
==> default: Running provisioner: Separate Before (shell)...
|
||||
default: Running: inline script
|
||||
default: ++++++++++++++++++++++++++++++
|
||||
==> default: Running provisioner: D (shell)...
|
||||
default: Running: inline script
|
||||
default: D
|
||||
==> default: Running provisioner: Separate After (shell)...
|
||||
default: Running: inline script
|
||||
default: ==============================
|
||||
==> default: Running provisioner: Goodbye (shell)...
|
||||
default: Running: inline script
|
||||
default: The end
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue