Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top