2

I'm trying to implement new custom option for Vagrant as in the following Vagrantfile:

# -*- mode: ruby -*-
require 'getoptlong'

opts = GetoptLong.new(
  [ '--vm-name',        GetoptLong::OPTIONAL_ARGUMENT ],
)

vm_name        = ENV['VM_NAME'] || 'default'

begin
  opts.each do |opt, arg|
    case opt
      when '--vm-name';        vm_name        = arg
    end
  end
  rescue
# @fixme: An invalid option error happens here.
end

Vagrant.configure(2) do |config|
  config.vm.define vm_name
  config.vm.provider "virtualbox" do |vbox, override|
    override.vm.box = "ubuntu/wily64"
  end
end

Now, each time when I run any vagrant command it's showing the following warning, e.g.

vagrant destroy -f

/opt/vagrant/embedded/gems/gems/vagrant-1.8.1/bin/vagrant: invalid option -- f

Another example:

$ vagrant --vm-name=foo up --no-provision
/opt/vagrant/embedded/gems/gems/vagrant-1.8.1/bin/vagrant: unrecognized option `--no-provision'
Bringing machine 'foo' up with 'virtualbox' provider...
==> foo: Importing base box 'ubuntu/wily64'...

Is there any way that I can ignore such warning from happening in the above rescue section?


This post is similar, but it doesn't help much in this case.

Community
  • 1
  • 1
kenorb
  • 155,785
  • 88
  • 678
  • 743

3 Answers3

5

It's impossible to do this in Vagrantfile. Vagrant parses options before loading Vagrantfile. The moment Vagrantfile is executed, Vagrant process is already in the ensure block after the exception that occurred because of the custom option in the command line. There is nothing one can do in Vagrantfile to recover from that.

Ilya Vassilevsky
  • 981
  • 6
  • 14
3

I think it may be possible to avoid the error. Warning - I'm new to vagrant. However, this seems to do what you are looking for:

opts = GetoptLong.new(
  [ '--vm-name',        GetoptLong::OPTIONAL_ARGUMENT ],
  [ '--host-name',      GetoptLong::OPTIONAL_ARGUMENT ],
  [ '--provider',       GetoptLong::OPTIONAL_ARGUMENT ],
  [ '--no-provision',   GetoptLong::OPTIONAL_ARGUMENT ],
)
vm_name        = ENV['VM_NAME'] || 'default'
host_name      = ENV['HOST_NAME'] || 'localhost.localdomain'

If you can anticipate all the command line options you think will be passed to your vagrant invocation, you can add them to the getopts array and then just ignore the elements that you want to be handled by default vagrant processing.

troyfolger
  • 2,388
  • 2
  • 15
  • 14
0

you could do in this fashion by just adding the option to your Vagrantfile as example:

opts = GetoptLong.new(
 [ '--ip', GetoptLong::OPTIONAL_ARGUMENT ],
 [ '-f', GetoptLong::OPTIONAL_ARGUMENT ]
)

and do not implement this option in the opt block as example:

opts.each do |opt, arg|
  case opt
    when '--ip'
        IP = arg
  end
end

then you can do vagrant destroy -f without of issue. and for any other switch which is default to vagrant commands you would need to do same as example ❯ vagrant global-status --prune would gave you exception:

Message: GetoptLong::InvalidOption: unrecognized option `--prune'

so to fix this you need to:

opts = GetoptLong.new(
 [ '--ip', GetoptLong::OPTIONAL_ARGUMENT ],
 [ '-f', GetoptLong::OPTIONAL_ARGUMENT ],
 [ '--prune', GetoptLong::OPTIONAL_ARGUMENT ]
)

and then you can execute vagrant command:

❯ vagrant global-status --prune
id       name   provider state  directory
--------------------------------------------------------------------
There are no active Vagrant environments on this computer! Or,
you haven't destroyed and recreated Vagrant environments that were
started with an older version of Vagrant.
nonus25
  • 343
  • 2
  • 10