New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get current provider in Vagrantfile #1867

Closed
p0deje opened this Issue Jun 25, 2013 · 17 comments

Comments

Projects
None yet
8 participants
@p0deje
Contributor

p0deje commented Jun 25, 2013

It would be great to have some API to get the current provider in Vagrantfile. Something like:

Vagrant.configure('2') do |config|
  config.vm.provider :virtualbox do |vbox, override|
    # some code
  end

  config.vm.provider :vmware_fusion do |vmware, override|
    # some code
  end

  config.vm.provider :kvm do |_, override|
    # some code
  end

  unless config.vm.provider == :kvm
    config.vm.network :forwarded_port, guest: 1080, host: 1080
    config.vm.network :forwarded_port, guest: 3000, host: 3000
    config.vm.synced_folder '.', '/vagrant', nfs: true
  end
end

I suppose I can still get this info by some internals, but I didn't manage to find a way through.

P.S. Would be happy to send PR if anyones knows where I can get current provider info.

@deanmalmgren

This comment has been minimized.

deanmalmgren commented Jul 10, 2013

If its possible to do this, its not terribly obvious at the moment. I'd like this as well so I can customize puppet manifests for particular providers (for example, to install rackspace monitoring for the rackspace provider), in which case I would want to do something like:

Vagrant.configure('2') do |config|
 config.vm.provider :virtualbox do |vb, override|
    # some code
  end

  config.vm.provider :rackspace do |rs, override|
    # some code
  end

  config.vm.provision :puppet do |pp|
    pp.facter = {
      "provider" => config.vm.provider, # let puppet install rackspace monitoring as necessary
    }
  end
end
@fgrehm

This comment has been minimized.

Collaborator

fgrehm commented Jul 10, 2013

@p0deje if that's all you want to do I'm pretty sure that your example could be changed to something like the following code with vagrant >= 1.2.0 :)

Vagrant.configure('2') do |config|
  config.vm.provider :virtualbox do |_, override|
    # some code
  end

  config.vm.provider :kvm do |_, override|
    # some code
    override.vm.network :forwarded_port, guest: 1080, host: 1080
    override.vm.network :forwarded_port, guest: 3000, host: 3000
    override.vm.synced_folder '.', '/vagrant', nfs: true
  end
end

for @deanmalmgren's one, although it makes things a bit more verbose it could be rewritten as:

Vagrant.configure('2') do |config|
  config.vm.provider :virtualbox do |vb, override|
    override.vm.provision :puppet do |pp|
      pp.facter = { "provider" => 'virtualbox' }
    end
  end

  config.vm.provider :rackspace do |rs, override|
    override.vm.provision :puppet do |pp|
      pp.facter = { "provider" => 'rackspace' }
    end
  end
end

I'm not sure how @mitchellh sees this but at least you guys can do what you want without any changes to vagrant :D

@p0deje

This comment has been minimized.

Contributor

p0deje commented Jul 10, 2013

@fgrehm No, it's not true, because your example works fine 2 providers, but when there are 3 providers and I'd like to share some configuration between 2 of them, I have to explicitly set them in both.

@fgrehm

This comment has been minimized.

Collaborator

fgrehm commented Jul 10, 2013

@p0deje no worries :)

Vagrant.configure('2') do |config|
  # shared networking configuration
  network_configs = lambda do |network|
    network.vm.network :forwarded_port, guest: 1080, host: 1080
    network.vm.network :forwarded_port, guest: 3000, host: 3000
    network.vm.synced_folder '.', '/vagrant', nfs: true
  end

  config.vm.provider :virtualbox do |_, override|
    # some code
    network_configs.call override
  end

  config.vm.provider :vmware_fusion do |_, override|
    # some code
  end

  config.vm.provider :kvm do |_, override|
    # some code
    network_configs.call override
  end
end

I know, its not perfect but it works :)

@deanmalmgren

This comment has been minimized.

deanmalmgren commented Jul 11, 2013

@fgrehm Good point on separating out a provisioning step for provider-specific provisioning. Your solution is certainly an option, but definitely suboptimal in situations when the provider-specific provisioning is not loosely coupled from other provisioning steps within the same puppet manifest.

I poked around the source code a bit yesterday and ran across Vagrant::Machine.provider. Is there any way to use this (or something similar) in the manifests to send the provider as a facter fact? Something like this, perhaps?

Vagrant.configure('2') do |config|
 config.vm.provider :virtualbox do |vb, override|
    # some code
  end

  config.vm.provider :rackspace do |rs, override|
    # some code
  end

  config.vm.provision :puppet do |pp|
    pp.facter = {
      "provider" => Vagrant::Machine.provider['name'],
    }
  end
end
@p0deje

This comment has been minimized.

Contributor

p0deje commented Jul 11, 2013

@fgrehm That's neat 👍 I'll use this so far.

@fgrehm

This comment has been minimized.

Collaborator

fgrehm commented Jul 11, 2013

@deanmalmgren well, I'm not sure if that's going to be possible, I might be wrong but vagrant builds Machine objects after the Vagrantfile has been parsed and to me it kinda makes sense since we need to know which machines are available prior to finding out what provider is active. I hope I'm wrong but I'm almost sure that it's not going to be possible without some good amount of work =/

let's wait for @mitchellh to jump in :D

@mitchellh

This comment has been minimized.

Member

mitchellh commented Jul 16, 2013

Yep, use the overrides as stated earlier.

@mitchellh mitchellh closed this Jul 16, 2013

@deanmalmgren

This comment has been minimized.

deanmalmgren commented Jul 17, 2013

@mitchellh I see how this addresses @p0deje's issue, but any thoughts on how to detect the provider so that it can be passed into a provisioning step? Something like this?

Vagrant.configure('2') do |config|
 config.vm.provider :virtualbox do |vb, override|
    # some code
  end
  config.vm.provider :rackspace do |rs, override|
    # some code
  end
  config.vm.provision :puppet do |pp|
    pp.facter = {
      "provider" => Vagrant::Machine.provider['name'],
    }
  end
end

I'd like to avoid the following workaround, which separates provider-specific provisioning from non-provider specific versioning to try and keep the Vagrantfile as readable/maintainable as possible:

Vagrant.configure('2') do |config|
 config.vm.provider :virtualbox do |vb, override|
    # some code + provider-specific provisioning
    override.vm.provision :puppet do |pp|
      pp.facter = {
        "provider" => "virtualbox",
      }
  end
  config.vm.provider :rackspace do |rs, override|
    # some code + provider-specific provisioning
    override.vm.provision :puppet do |pp|
      pp.facter = {
        "provider" => "rackspace",
      }
    end
  end
  config.vm.provision :puppet do |pp|
    # non-provider specific provisioning
  end
end
@mitchellh

This comment has been minimized.

Member

mitchellh commented Jul 17, 2013

@deanmalmgren For now, just pull it out into a function or something:

def puppet(config, provider)
  config.vm.provision :puppet do |pp|
    pp.facter = {
      "provider" => provider,
    }
  end
end

Then anywhere:

puppet(config, "virtualbox")

There is another issue open where you'll be able to override specific provisioners. Once that is in, you could do that.

@deanmalmgren

This comment has been minimized.

deanmalmgren commented Jul 18, 2013

right...a function. definitely should have thought of that... thanks!

@nirvdrum

This comment has been minimized.

nirvdrum commented Sep 17, 2014

How does this work if one needs to customize a host in a multi-box setup, based upon the provider being used?

@canausa

This comment has been minimized.

Contributor

canausa commented Sep 17, 2014

customize the host?

On Wed, Sep 17, 2014 at 7:08 PM, Kevin Menard notifications@github.com
wrote:

How does this work if one needs to customize a host in a multi-box setup,
based upon the provider being used?


Reply to this email directly or view it on GitHub
#1867 (comment).

@nirvdrum

This comment has been minimized.

nirvdrum commented Sep 18, 2014

I meant config.vm.define. Bit looks likes the provider-specific overrides can be applied in there as well. I must have just fat-fingered it the first time. Sorry for the noise.

roc pushed a commit to alphagov/pp-puppet that referenced this issue Oct 24, 2014

Ralph Cowling
Add logic around vmware specific clause
- Really temporary fix for suckers in the team who aren't lucky enough to have :money_with)wings: vmware 💸 as their vm provider
- It's difficult to switch on current provider in your vagrantfile, there are some workarounds listed here: hashicorp/vagrant#1867
- Will have a bash at refactoring to match some of those solutions, but this temporarily fixes this issue: http://cl.ly/image/0n0m0E1F3b2y

rutsky added a commit to rutsky/contrib that referenced this issue Mar 24, 2016

include proper flannel_opts on VBox provider
It's ugly due to the fact that there is no simple way to get current
provider, see <hashicorp/vagrant#1867> for
discussion.

I made some variables global (with "$" sign), since they are more like
global constants then local variables, plus in this ways it's easier
to use them inside functions.

rutsky added a commit to rutsky/contrib that referenced this issue Mar 24, 2016

include proper flannel_opts on VBox provider
It's ugly due to the fact that there is no simple way to get current
provider, see <hashicorp/vagrant#1867> for
discussion.

I made some variables global (with "$" sign), since they are more like
global constants then local variables, plus in this ways it's easier
to use them inside functions.

mikedanese added a commit to mikedanese/kube-deploy that referenced this issue Mar 29, 2016

include proper flannel_opts on VBox provider
It's ugly due to the fact that there is no simple way to get current
provider, see <hashicorp/vagrant#1867> for
discussion.

I made some variables global (with "$" sign), since they are more like
global constants then local variables, plus in this ways it's easier
to use them inside functions.
@kenorb

This comment has been minimized.

Contributor

kenorb commented Jun 10, 2016

Workaround for the title question how to get the current provider name:

require 'getoptlong'
opts = GetoptLong.new(
  [ '--provider', GetoptLong::OPTIONAL_ARGUMENT ]
)

provider='virtualbox'
begin
  opts.each do |opt, arg|
    case opt
      when '--provider'
        provider=arg
    end
  end
  rescue
# @see: http://stackoverflow.com/q/38234133/55075
end

Vagrant.configure(2) do |config|
  config.vm.define "default-#{provider}"
  # ...
end
@stevekuznetsov

This comment has been minimized.

stevekuznetsov commented Aug 31, 2016

@kenorb since the Vagrantfile is loaded and run on every single vagrant command line invocation (why??), the getoptlong hack breaks CLI interactions with Vagrant.

    $ vagrant ssh-config --help
    Usage: vagrant ssh-config [options] [name]

    Options:

            --host NAME                  Name the host for the config
        -h, --help                       Print this help
    /usr/share/vagrant/bin/vagrant: unrecognized option `--help'
    There was an error loading a Vagrantfile. The file being loaded
    and the error message are shown below. This is usually caused by
    a syntax error.

    Path: /home/skuznets/Vagrantfile
    Line number: 394
    Message: GetoptLong::InvalidOption: unrecognized option `--help'

    $ vagrant ssh-config --host=default
    /usr/share/vagrant/bin/vagrant: unrecognized option `--host'
    There was an error loading a Vagrantfile. The file being loaded
    and the error message are shown below. This is usually caused by
    a syntax error.

    Path: /home/skuznets/Vagrantfile
    Line number: 394
    Message: GetoptLong::InvalidOption: unrecognized option `--host'
@kenorb

This comment has been minimized.

Contributor

kenorb commented Sep 1, 2016

@stevekuznetsov To ignore the error for other command you can add empty rescue I guess, I've updated the code. It shouldn't fail, however it'll always show unrecognized option. See this post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment