I want to display some text on the screen when running vagrant up
(or vagrant provision
, etc.) if and only if provisioning is being done. (For vagrant up
it is only run the first time, or if specifically forced with --provision
.)
How can this be done?
Adding a shell provisioner is probably the easiest solution, with the small cost that it is executed on the VM over SSH.
Another option is to use the vagrant-host-shell plugin:
Vagrant.configure('2') do |config|
# other config and provisioners
# [...]
config.vm.provision :host_shell, inline: 'echo "Provisioned!"'
end
If you like over-engineering, you can even make your own plugin in Vagrantfile. ;)
class EchoPlugin < Vagrant.plugin('2')
class EchoAction
def initialize(app, env)
@app = app
end
def call(env)
@app.call(env)
puts "Provisioned!"
end
end
name 'echo'
action_hook 'echo' do |hook|
hook.before Vagrant::Action::Builtin::Provision, EchoAction
end
end
Vagrant.configure('2') do |config|
# ...
end
I'm not sure if I understood your question correctly, but if you want to show a text message if and only if provisioning runs, and you already know that provisioning runs only on first vagrant up
and when forcing it using the --provision
switch - then why not just add the output of the message to the provisioning itself?
This could be as simple as using a shell provisioner and running an echo
command inside of that.
As Vagrant supports multiple provisioners within one Vagrantfile and is able to run all of them when provisioning a virtual machine, this is a dead-easy step, no matter whether you use the shell provisioner anyway, or if you use any other provisioner.
According to the Vagrant issue #7043 where somebody wanted to use @env[:provision_enabled]
to see if provisioning is being run. It was answered that you could also check the arguments your Vagrantfile was called with:
This is not currently possible because the Vagrantfile is parsed before the environment is created. This information is available to
provisioners and plugins, but not the Vagrantfile itself because of
the load ordering. In other words, that @env
doesn't exist until after
all Vagrantfile's have been parsed, and unfortunately that's a hard
requirement because information in the Vagrantfile determines the way
that object is created. It's a catch-22 for your use case.
One possible alternative is to inspect ARGV
in your Vagrantfile.
Something like:
if ARGV.include?("up") || (ARGV.include?("reload") && ARGV.include?("--provision"))
...
end
Example usage
I added two functions to the bottom of my Vagrantfile:
def provisioned?(vm_name='default', provider='virtualbox')
File.exists?(File.join(File.dirname(__FILE__),".vagrant/machines/#{vm_name}/#{provider}/action_provision"))
end
def explicit_provisioning?()
(ARGV.include?("reload") && ARGV.include?("--provision")) || ARGV.include?("provision")
end
Which I can use around any statement in my Vagrantfile:
if (not provisioned?) || explicit_provisioning?
...
end