mitchellh / vagrant-aws

Use Vagrant to manage your EC2 and VPC instances.
MIT License
2.61k stars 573 forks source link

All providers run when multiple are included #349

Open blaw2422 opened 9 years ago

blaw2422 commented 9 years ago

Problem

Including 2 providers in 1 Vagrant file causes both to run no matter which command I use, or how I call it.

Usage

vagrant up --provider=virtualbox will cause code in both providers to execute. When the AWS provider runs, it will make sure all values are provided, or will raise exception. The values are not required for virtualbox, but still fail when I try to use virtualbox.

Solution

Use conditional statements in the providers to determine if the block should execute based on the provider specified in the vagrant command.

Example Vagranttfile

    # -*- mode: ruby -*-
    # vi: set ft=ruby :

    Vagrant.configure('2') do |config|
      config.vm.box = 'centos-64-x64-vbox4210'
      config.vm.box_url = 'http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210.box'

      provider_is_aws  = (!ARGV.nil? && ARGV.join('').include?('provider=aws'))

      unless (provider_is_aws)
        config.vm.provider :virtualbox do |vb|
          vb.customize [
            # Key                Value
            'modifyvm',          :id,
            '--cpuexecutioncap', '90',
            '--memory',          '1376',
            '--nictype2',        'virtio',
          ]

        end
      end

      if (provider_is_aws)
        config.vm.provider :aws do |aws, override|

          config.vm.box = 'dummy'
          config.vm.box_url = 'https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box'

         # the following calls will raise errors if values are not found
          aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] or raise "AWS_ACCESS_KEY_ID not provided'
          aws.secret_access_key = ENV['SECRET_ACCESS_KEY'] or raise "SECRET_ACCESS_KEY not provided"
          aws.keypair_name = ENV['ACCESS_KEYPAIR_NAME'] or raise "ACCESS_KEYPAIR_NAME not provided"
          aws.iam_instance_profile_name = ENV['IAM_ROLE'] or raise "IAM_ROLE not provided"
        end
      end
    end
smccarthy commented 9 years ago

I removed unless (provider_is_aws) and if (provider_is_aws) (plus their end statements), and also changed config.vm.box = 'dummy' to aws.vm.box = 'dummy' and config.vm.box_url = 'https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box' to aws.vm.box_url = 'https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box'

and it worked for me when I did vagrant up --provider=virtualbox (only vbox provider booted up)

blaw2422 commented 9 years ago

@smccarthy, I tried that with no avail.

myoung34 commented 9 years ago

Happens for me too.

Vagrantfile:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure('2') do |config|
  config.vm.box = 'centos-64-x64-vbox4210'
  config.vm.box_url = 'http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210.box'

  config.vm.provider :virtualbox do |vb|
    vb.customize [
      # Key                Value
      'modifyvm',          :id,
      '--cpuexecutioncap', '90',
      '--memory',          '1376',
      '--nictype2',        'virtio',
    ]

  end

  config.vm.provider :aws do |aws, override|

    override.vm.box = 'dummy'
    override.vm.box_url = 'https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box'

    # the following calls will raise errors if values are not found
    aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] or raise "AWS_ACCESS_KEY_ID not provided"
    aws.secret_access_key = ENV['SECRET_ACCESS_KEY'] or raise "SECRET_ACCESS_KEY not provided"
    aws.keypair_name = ENV['ACCESS_KEYPAIR_NAME'] or raise "ACCESS_KEYPAIR_NAME not provided"
    aws.iam_instance_profile_name = ENV['IAM_ROLE'] or raise "IAM_ROLE not provided"
  end
end

Output:

marcuss-mbp:~ $ vagrant -v
Vagrant 1.7.1
marcuss-mbp:~ $ vagrant plugin list | grep vagrant-aws
vagrant-aws (0.6.0)

marcuss-mbp:~ $ vagrant up #default is vbox
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: <provider config: aws>
Message: AWS_ACCESS_KEY_ID not provided

marcuss-mbp:~ $ vagrant up --provider=virtualbox
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: <provider config: aws>
Message: AWS_ACCESS_KEY_ID not provided
myoung34 commented 9 years ago

According to the documentation:

LIMITATIONS Vagrant currently restricts you to bringing up one provider per machine. If you have a multi-machine environment, you can bring up one machine backed by VirtualBox and another backed by VMware Fusion, for example, but you can't back the same machine with both VirtualBox and VMware Fusion.

This is a limitation that will be removed in a future version of Vagrant.

That's fine as a limitation, but why then, do you have to specify a provider? If the saying is "one provider per box" then it should error when multiple providers are defined for a box or not require you to say --provider={provider} since you can only have one. As far as I can see, this is either: a bug in vagrant or the vagrant-aws plugin acting a bit strange.

Maybe we should summon the almight @mitchellh and see what the correct usage is. The workaround is fine in my book, but it's a bit strange. I don't see any potential issues with multiple providers per box, especially when all you want to do is run the same provisioners etc against a single instance, and that instance only changes on different platforms. The only thing it would take to make this work (given that I have not read through code) is that it would not execute/validate blocks for unspecified providers.

ie. "This is what it takes to create a running VM in vbox. In AWS, just point to this base AMI. In Digitalocean, this droplet". I don't want to manage multiple box references in a Vagrantfile when the only difference is that it has metadata for aws, digitalocean, etc.

chris-redekop commented 9 years ago

@myoung34 I interpreted the limitation you mention differently: a single Vagrantfile can support multiple providers but you can have only a single running machine--using a single provider--from each Vagrantfile instance. So for a Vagrantfile that supports openstack and virtualbox, I observe

$ vagrant up # --provider virtualbox implied
... runs successfully
$ vagrant up --provider openstack
An active machine was found with a different provider. Vagrant
currently allows each machine to be brought up with only a single
provider at a time. A future version will remove this limitation.
Until then, please destroy the existing machine to up with a new
provider.

Machine name: default
Active provider: virtualbox
Requested provider: openstack
$ vagrant destroy
... runs successfully
$ vagrant up --provider openstack
... runs successfully

As a Vagrantfile novice, I find the behaviour noted by you and @blaw2422 (and now me, that's how I got here) mysterious: Vagrant doesn't run all of the code for the unspecified providers--i.e. running vagrant up with my Vagrantfile doesn't result in a machine on both VirtualBox and OpenStack--so why does it run any of the code for the unspecified providers?

blaw2422 commented 9 years ago

@chris-redekop, that's the same question I asked. That's why we used code determine what was called in order to ensure when code is called

dangra commented 9 years ago

I don't think it is a vagrant-aws only issue, the same happens to me with a Vagrantfile that includes config.vm.provider sections for virtualbox and vmware_fusion.

dankimmel commented 9 years ago

Yes, you should be able to supply multiple configurations in your Vagrantfile to allow users to use their favorite provider, however, code that you place in a provider-specific blocks should not run unless you are provisioning using that provider. Instead of that behavior, you're allowed to specify multiple providers, but they all run no matter what!

I am also having this problem; it's very counterintuitive, and ugly to hack around.

agilmore2 commented 9 years ago

There ought to be a way to make this less ugly, that avoids processing command line arguments! Isn't there a variable indicating which provider was selected?

defnnn commented 8 years ago

I can get multiple providers to work together (virtualbox, aws, and digital_ocean) if I run vagrant up and list all of the guest names. Without names, the aws provider will config check guests that are meant to run on other providers. vagrant status and vagrant destroy will do the right thing on all guests without needing to name them on the command-line.

So maybe one solution is to name all the guests of a provider when using vagrant up to avoid triggering checks on all guests.

agilmore2 commented 8 years ago

Example Vagrantfile please?

defnnn commented 8 years ago

https://github.com/defn/home/blob/master/Vagrantfile

agilmore2 commented 8 years ago

Thanks. So you're suggesting that you can vagrant up the virtualbox provider without the environment variables set?

defnnn commented 8 years ago

Just unset my aws credential variables, and vagrant up vbox brought up my virtualbox guest. At the time, I had aws and digital_ocean guests running already in the same vagrant working area.

See my vagrant status: https://gist.github.com/defn/bed4cfb4bf6bda858007

I bring the guests up with:

vagrant up vbox vagrant up $(aws regions) --parallel vagrant up $(digitalocean regions) --parallel

Notice no --provider yyy

agilmore2 commented 8 years ago

Thanks! I will definitely try that.

Now, does it also ignore provisioners defined in those other providers? Hmm.

On Fri, Nov 13, 2015 at 10:48 PM, DEFN notifications@github.com wrote:

Just unset my aws credential variables, and vagrant up vbox brought up my virtualbox guest. At the time, I had aws and digital_ocean guests running already in the same vagrant working area.

— Reply to this email directly or view it on GitHub https://github.com/mitchellh/vagrant-aws/issues/349#issuecomment-156638637 .