core: provision "once" or "always" [GH-2421]

This commit is contained in:
Mitchell Hashimoto 2014-04-09 15:28:44 -07:00
parent f6fb9016a1
commit aad8e7f80d
8 changed files with 78 additions and 28 deletions

View File

@ -5,6 +5,9 @@ FEATURES:
- Can now specify a `post_up_message` in your Vagrantfile that is shown
after a `vagrant up`. This is useful for putting some instructions of how
to use the development environment.
- Can configure provisioners to run "once" or "always" (defaults to "once"),
so that subsequent `vagrant up` or `reload` calls will always run a
provisioner. [GH-2421]
## 1.5.4 (April 21, 2014)

View File

@ -5,7 +5,7 @@ module Vagrant
# This returns all the instances of the configured provisioners.
# This is safe to call multiple times since it will cache the results.
#
# @return [Array<Provisioner>]
# @return [Array<Provisioner, Hash>]
def provisioner_instances(env)
return @_provisioner_instances if @_provisioner_instances
@ -21,8 +21,13 @@ module Vagrant
# Store in the type map so that --provision-with works properly
@_provisioner_types[result] = provisioner.name
# Build up the options
options = {
run: provisioner.run,
}
# Return the result
result
[result, options]
end
return @_provisioner_instances

View File

@ -22,8 +22,12 @@ module Vagrant
def call(env)
@env = env
# Tracks whether we were configured to provision
config_enabled = true
config_enabled = env[:provision_enabled] if env.has_key?(:provision_enabled)
# Check if we already provisioned, and if so, disable the rest
enabled = true
sentinel_enabled = true
ignore_sentinel = true
if env.has_key?(:provision_ignore_sentinel)
@ -52,11 +56,11 @@ module Vagrant
if parts.length == 1
@logger.info("Old-style sentinel found! Not provisioning.")
enabled = false
sentinel_enabled = false
update_sentinel = true
elsif parts[0] == "1.5" && parts[1] == env[:machine].id.to_s
@logger.info("Sentinel found! Not provisioning.")
enabled = false
sentinel_enabled = false
else
@logger.info("Sentinel found with another machine ID. Removing.")
sentinel_path.unlink
@ -65,10 +69,10 @@ module Vagrant
end
# Store the value so that other actions can use it
env[:provision_enabled] = enabled if !env.has_key?(:provision_enabled)
env[:provision_enabled] = sentinel_enabled if !env.has_key?(:provision_enabled)
# Ask the provisioners to modify the configuration if needed
provisioner_instances(env).each do |p|
provisioner_instances(env).each do |p, _|
p.configure(env[:machine].config)
end
@ -85,14 +89,27 @@ module Vagrant
end
end
# Actually provision if we enabled it
if env[:provision_enabled]
# If we're configured to not provision, notify the user and stop
if !config_enabled
env[:ui].info(I18n.t("vagrant.actions.vm.provision.disabled_by_config"))
return
end
# If we're not provisioning because of the sentinel, tell the user
# but continue trying for the "always" provisioners
if !sentinel_enabled
env[:ui].info(I18n.t("vagrant.actions.vm.provision.disabled_by_sentinel"))
end
type_map = provisioner_type_map(env)
provisioner_instances(env).each do |p|
provisioner_instances(env).each do |p, options|
type_name = type_map[p]
next if env[:provision_types] && \
!env[:provision_types].include?(type_name)
# Don't run if sentinel is around and we're not always running
next if !sentinel_enabled && options[:run] != :always
env[:ui].info(I18n.t(
"vagrant.actions.vm.provision.beginning",
provisioner: type_name))
@ -103,9 +120,6 @@ module Vagrant
provisioner_name: type_name,
))
end
elsif !enabled
env[:ui].info(I18n.t("vagrant.actions.vm.provision.disabled_by_sentinel"))
end
end
# This is pulled out into a seperate method so that users can

View File

@ -30,7 +30,7 @@ module Vagrant
type_map = provisioner_type_map(env)
# Ask the provisioners to modify the configuration if needed
provisioner_instances(env).each do |p|
provisioner_instances(env).each do |p, _|
env[:ui].info(I18n.t(
"vagrant.provisioner_cleanup",
name: type_map[p].to_s))

View File

@ -126,6 +126,7 @@ module VagrantPlugins
if other_p
# There is an override. Take it.
other_p.config = p.config.merge(other_p.config)
other_p.run ||= p.run
next if !other_p.preserve_order
# We're preserving order, delete from other
@ -269,6 +270,7 @@ module VagrantPlugins
end
prov.preserve_order = !!options[:preserve_order]
prov.run = options.delete(:run) if options.has_key?(:run)
prov.add_config(options, &block)
nil
end
@ -395,6 +397,7 @@ module VagrantPlugins
# Finalize all the provisioners
@provisioners.each do |p|
p.config.finalize! if !p.invalid?
p.run = p.run.to_sym if p.run
end
# If we didn't share our current directory, then do it

View File

@ -20,6 +20,11 @@ module VagrantPlugins
# @return [Object]
attr_accessor :config
# When to run this provisioner. Either "once" or "always"
#
# @return [String]
attr_accessor :run
# Whether or not to preserve the order when merging this with a
# parent scope.
#
@ -35,6 +40,7 @@ module VagrantPlugins
@invalid = false
@name = name
@preserve_order = false
@run = nil
# Attempt to find the provisioner...
if !Vagrant.plugin("2").manager.provisioners[name]

View File

@ -1490,8 +1490,11 @@ en:
mounting: Mounting NFS shared folders...
provision:
beginning: "Running provisioner: %{provisioner}..."
disabled_by_config: |-
Machine not provisioning because `--no-provision` is specified.
disabled_by_sentinel: |-
VM already provisioned. Run `vagrant provision` or use `--provision` to force it
Machine already provisioned. Run `vagrant provision` or use the `--provision`
to force provisioning. Provisioners marked to run always will still run.
resume:
resuming: Resuming suspended VM...
unpausing: |-

View File

@ -214,14 +214,16 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
describe "#provision" do
it "stores the provisioners" do
subject.provision("shell", inline: "foo")
subject.provision("shell", inline: "bar") { |s| s.path = "baz" }
subject.provision("shell", inline: "bar", run: "always") { |s| s.path = "baz" }
subject.finalize!
r = subject.provisioners
expect(r.length).to eql(2)
expect(r[0].run).to be_nil
expect(r[0].config.inline).to eql("foo")
expect(r[1].config.inline).to eql("bar")
expect(r[1].config.path).to eql("baz")
expect(r[1].run).to eql(:always)
end
it "allows provisioner settings to be overriden" do
@ -264,6 +266,20 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
end
describe "merging" do
it "ignores non-overriding runs" do
subject.provision("shell", inline: "foo", run: "once")
other = described_class.new
other.provision("shell", inline: "bar", run: "always")
merged = subject.merge(other)
merged_provs = merged.provisioners
expect(merged_provs.length).to eql(2)
expect(merged_provs[0].run).to eq("once")
expect(merged_provs[1].run).to eq("always")
end
it "copies the configs" do
subject.provision("shell", inline: "foo")
subject_provs = subject.provisioners