Question

I'm wondering if there is a way to specify defaults for provisioners when creating a multi-machine environment with Vagrant?

I was trying to do something like the following:

Vagrant.configure("2") do |config|
  config.vm.box = "andyshinn/ubuntu-precise64"

  config.vm.provision :chef_client do |chef|
    chef.chef_server_url = "https://api.opscode.com/organizations/myorg"
    chef.validation_key_path = "~/.chef/myorg-validator.pem"
    chef.delete_node = true
    chef.delete_client = true
    chef.validation_client_name = "myorg-validator"
  end

  config.vm.define :app do |app|
    app.vm.network "private_network", ip: "172.16.64.61"
    app.vm.host_name = "vagrant-app-#{ENV['USER']}"

    app.vm.provision :chef_client do |chef|
      chef.add_recipe "myrecipe1"
      chef.add_recipe "myrecipe2"
      chef.add_recipe "sudo"
    end
  end

  config.vm.define :web do |web|
    web.vm.network "private_network", ip: "172.16.64.62"
    web.vm.host_name = "vagrant-web-#{ENV['USER']}"

    web.vm.provision :chef_client do |chef|
      chef.add_recipe "myrecipe3"
      chef.add_recipe "myrecipe4"
      chef.add_recipe "sudo"
    end
  end
end

But each VM block does not appear to pick up any of the main config block settings. I get this error:

There are errors in the configuration of this machine. Please fix
the following errors and try again:

chef client provisioner:
* Chef server URL must be populated.
* Validation key path must be valid path to your chef server validation key.

Possible via another method?

Was it helpful?

Solution 2

Maybe you already have this working, but in case not, check this out:

It partially solved my problem; maybe it will help you.

OTHER TIPS

Your issue is one of scope. The variable chef has block scope in the config.vm.provision do block.

once this block exits your changes disappear. You should follow the example in the multi-machine docs on the vagrant site.

config.vm.provision "shell", inline: "echo Hello"

Vagrant.configure("2") do |config|
  config.vm.box = "andyshinn/ubuntu-precise64"


  config.vm.provision "chef_client", chef_server_url: "https://api.opscode.com/organizations/myorg"
  config.vm.provision "chef_client", validation_key_path:  "~/.chef/myorg-validator.pem                
  config.vm.provision "chef_client", delete_node: true
  config.vm.provision "chef_client", delete_client: true
  config.vm.provision "chef_client", validation_client_name: "myorg-validator"


  config.vm.define :app do |app|
    app.vm.network "private_network", ip: "172.16.64.61"
    app.vm.host_name = "vagrant-app-#{ENV['USER']}"

    app.vm.provision :chef_client do |chef|
      chef.add_recipe "myrecipe1"
      chef.add_recipe "myrecipe2"
      chef.add_recipe "sudo"
    end
  end

Should do the trick

I think the inner block "overrides" the outer one. You can, however, do something like I ended up doing in my answer (to my own question) to fake inside out ordering of provisioners rather than outside-in as Vagrant provides. In your case you wouldn't have a shell and puppet provisioner like I had, but you'd apply something like a template method pattern to extend a chef provisioner with more recipes. Perhaps something like:

module Vagrant
  module Config
    module V2
      class Root
        def provision(extra_recipes)
          config.vm.provision :chef_client do |chef|
            chef.chef_server_url = "https://api.opscode.com/organizations/myorg"
            chef.validation_key_path = "~/.chef/myorg-validator.pem"
            chef.delete_node = true
            chef.delete_client = true
            chef.validation_client_name = "myorg-validator"
            extra_recipes.each { |recipe| chef.add_recipe(recipe) }
          end
        end
      end
    end
  end
end

Vagrant.configure("2") do |config|
  config.vm.box = "andyshinn/ubuntu-precise64"

  config.vm.define :app do |app|
    app.vm.network "private_network", ip: "172.16.64.61"
    app.vm.host_name = "vagrant-app-#{ENV['USER']}"

    app.provision("myrecipe1", "myrecipe2", "sudo")
  end

  config.vm.define :web do |web|
    web.vm.network "private_network", ip: "172.16.64.62"
    web.vm.host_name = "vagrant-web-#{ENV['USER']}"

    app.provision("myrecipe3", "myrecipe4", "sudo")
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top