Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run code in Vagrantfile only if provisioning

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?

like image 781
iconoclast Avatar asked Feb 19 '14 19:02

iconoclast


2 Answers

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
like image 86
tmatilai Avatar answered Sep 19 '22 16:09

tmatilai


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
like image 41
spoorcc Avatar answered Sep 20 '22 16:09

spoorcc