如何在没有无效选项警告的情况下为 Vagrant 实现自定义选项?

How to implement custom option for Vagrant without having invalid option warning?

我正在尝试为 Vagrant 实现新的自定义选项,如下所示 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

现在,每次我 运行 任何 vagrant 命令时,它都会显示以下警告,例如

vagrant destroy -f

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

另一个例子:

$ 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'...

有什么方法可以忽略上述 rescue 部分中发生的此类警告?


这个post是相似的,但在这种情况下没有太大帮助。

Vagrantfile 中不可能做到这一点。 Vagrant 在加载 Vagrantfile 之前解析选项。在执行 Vagrantfile 的那一刻,由于命令行中的自定义选项而发生异常后,Vagrant 进程已经在 ensure 块中。在 Vagrantfile 中没有什么可以从中恢复。

我认为有可能避免错误。警告 - 我是流浪汉的新手。但是,这似乎可以满足您的需求:

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'

如果您可以预料到您认为将传递给您的 vagrant 调用的所有命令行选项,您可以将它们添加到 getopts 数组,然后忽略您希望由默认 vagrant 处理处理的元素。

您可以通过将选项添加到您的 Vagrantfile 来以这种方式进行操作,例如:

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

并且不要在 opt 块中实现此选项,例如:

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

那么您可以毫无问题地执行 vagrant destroy -f。 对于默认为 vagrant 命令的任何其他开关,您需要执行与示例相同的操作 ❯ vagrant global-status --prune 会给您例外:

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

因此,要解决此问题,您需要:

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

然后你可以执行vagrant命令:

❯ 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.