【问题标题】:Demand a Vagrant plugin within the Vagrantfile?在 Vagrantfile 中需要一个 Vagrant 插件?
【发布时间】:2013-10-29 20:09:32
【问题描述】:

假设执行 Vagrantfile 需要安装特定的 Vagrant 插件。所以,基本上你需要做的是

$ vagrant plugin install foobar-plugin
$ vagrant up

如果您跳过第一步,vagrant up 将失败。

Vagrant 中是否有一个选项可以让它自动安装插件?换句话说:是否可以在 Vagrantfile 中指定在创建和启动机器之前自动安装哪些插件?

【问题讨论】:

    标签: vagrant


    【解决方案1】:

    2018 年 8 月 31 日更新:请参阅 @Starx's fix below 了解更高版本的 Vagrant(1.8 及更高版本)

    这是基于 Louis St. Amour 的解决方案的版本以及 Rob Kinyon 关于 re-exec 如果安装了新插件的评论,我在自己的设置中成功使用它:

    required_plugins = %w(vagrant-share vagrant-vbguest...)
    
    plugins_to_install = required_plugins.select { |plugin| not Vagrant.has_plugin? plugin }
    if not plugins_to_install.empty?
      puts "Installing plugins: #{plugins_to_install.join(' ')}"
      if system "vagrant plugin install #{plugins_to_install.join(' ')}"
        exec "vagrant #{ARGV.join(' ')}"
      else
        abort "Installation of one or more plugins has failed. Aborting."
      end
    end
    

    【讨论】:

    • 绝对是目前最好的解决方案
    • 我在 4 月 20 日更新了解决方案,只使用一个“系统”调用来安装所有缺少的插件。
    • 这不起作用。它进入了安装插件的无限循环。不知何故,新的 vagrant 进程无法在父 vagrant 进程中获取新安装的插件
    • 感谢您的更新。实际上,我最终在这里遵循了 mkuzmin 建议的解决方案:github.com/mitchellh/vagrant/issues/4347。它涉及使用一个名为 vagrant plugins 的插件,然后在 Vagrantfile 中使用一些代码(与您非常相似)。
    • @SteveHenty 我对您的评论表示同情,但是将其移至插件中会破坏代码的目的(第一次只能git clone...; cd ...; vagrant up)。
    【解决方案2】:

    由于我是一名 Ruby 开发人员,并且不再维护 Bindler,我发现在我的 Vagrantfile 顶部编写一些代码来安装所需的插件是最自然的(例如在 Vagrant.configure 行之前)

    以下对我有用:

    required_plugins = %w( vagrant-hostmanager vagrant-someotherplugin )
    required_plugins.each do |plugin|
      system "vagrant plugin install #{plugin}" unless Vagrant.has_plugin? plugin
    end
    

    system 与使用反引号不同,它将命令回显到标准输出,就像自己运行命令一样。这样我就不需要另一个奇怪的插件或系统来跟踪所需的插件,这些插件无论如何都可以由 Vagrant 更新。

    【讨论】:

    • 您需要 'exec "vagrant #{ARGV.join' '}"' 以重新启动安装插件的 vagrant 进程。
    • 好点。就我而言,我遇到了一个错误,但看到安装插件的输出并知道重新运行该命令。让它自动重新运行将是一个更好的增强。如果重写它,也许我会检查是否未安装任何插件,如果是,请先安装插件然后重新运行脚本,而不是一次检查并安装每个插件...
    • 如果有Vagrant.has_plugin? 命令在shell 级别或者只是有vagrant plugin install 检查插件是否已经存在,那就太棒了。
    • 好吧,你总是可以做类似if [ $(vagrant plugin list | egrep 'vagrant-hostsupdater|vagrant-share' -c) == 2 ] ; then echo "All plugins installed." ; else echo "Missing plugin"; fi 的事情,但是如果他们可以帮助的话,没有人编写 bash 脚本是有原因的 ;-) 也许进一步试验 vagrant plugin 命令?
    【解决方案3】:

    正如我 pointed out on my answer to your other question,您可以使用 bindler 使用单个命令安装一组特定于项目的插件。

    如果安装了binder,但没有安装所需的插件,binder 将出错并中止进程。在vagrant ups 上还有与自动安装插件相关的an open issue,但目前还没有人注册。

    如果你不想使用binder,你可以在Vagrantfile顶部使用Vagrant.has_plugin?(1.3.0+可用),如果没有安装所需的插件则会报错。

    类似:

    unless Vagrant.has_plugin?("vagrant-some-plugin")
      raise 'some-plugin is not installed!'
    end
    
    Vagrant.configure("2") do |config|
      config.vm.box = "box-name"
    end
    

    更新:自 2015 年 5 月 11 日起,不再支持 Bindler,并且 Vagrant 核心未提供等效功能

    【讨论】:

    • 对于未来的 Google 员工,请注意这个答案有点过时了。您现在可以在 Vagrant 将检查的 :plugins 组下的 Gemfile 中指定您的依赖项。有关详细信息,请参阅下面的答案。
    • Gemfile 用于 Vagrant 插件开发。见github.com/mitchellh/vagrant/issues/8370
    【解决方案4】:

    2019 年更新:Vagrant 现在具有通过 Vagrantfile 要求插件的功能:

    Vagrant.configure("2") do |config|
      config.vagrant.plugins = "vagrant-some-plugin"
    
      # or as array:
      config.vagrant.plugins = ["vagrant-some-plugin", "vagrant-some-other-plugin"]
    
      # or as hash
      config.vagrant.plugins = {"vagrant-some-plugin" => {"version" => "1.0.0"}}
    end
    

    如果 Vagrant 检测到有插件尚未安装,它会提示用户自行安装:

    $ vagrant up
    Vagrant has detected project local plugins configured for this
    project which are not installed.
    
      vagrant-some-plugin
    Install local plugins (Y/N) [N]: y
    Installing the 'vagrant-some-plugin' plugin. This can take a few minutes...
    Fetching vagrant-some-plugin-1.0.0.gem
    Installed the plugin 'vagrant-some-plugin (1.0.0)'!
    
    
    Vagrant has completed installing local plugins for the current Vagrant
    project directory. Please run the requested command again.
    

    https://www.vagrantup.com/docs/vagrantfile/vagrant_settings.html

    【讨论】:

    • 如果我想跳过提示并自动安装所有必需的插件怎么办?
    【解决方案5】:

    请注意,从 Vagrant 1.5 开始,您可以在 Gemfile 中指定您的依赖项。根据blog post on the update

    现在,Vagrant 1.5 将自动加载“插件”中的所有 gem 在您的 Gemfile 中分组。例如,这里是一个 Gemfile “流浪酒吧”插件:

    source "https://rubygems.org"
    
    group :development do
      gem "vagrant",
        git: "https://github.com/mitchellh/vagrant.git"
    end
    
    group :plugins do
      gem "vagrant-foo",
      gem "vagrant-bar", path: "."
    end
    

    【讨论】:

    • 那篇博文不是指 Vagrant plugin 开发吗? Vagrant boxes 通常没有 Gemfiles,它们使用 Vagrantfiles。
    • 您是正确的,Vagrant 盒子本身没有 Gemfile(您可能有一个不需要任何插件的 Vagrantfile),但如果您正在使用插件(上下文博客的依赖项是您自己的插件的依赖项,但对于 Vagrantfiles 也是如此),您应该使用 Gemfile 来指定这些要求。
    • 谢谢,这很有帮助。由于许多 Vagrant 用户不是 ruby​​ 开发人员,并且还没有Gemfile,您介意解释一下您是如何设置的吗?我创建了一个与您的示例类似的示例,但 vagrant up 不会自动加载任何内容。尝试过bundle install,但这会提示系统 Rubygems 权限,这听起来不对。
    • 我猜你在 OSX 中使用 stock ruby​​ 安装,遇到了这个问题:stackoverflow.com/questions/14607193?
    • 在厨师食谱的世界里,很少有人会有 gemfile
    【解决方案6】:

    无法对 Louis St-Amour 的回答添加评论,但我想发布此内容以防万一有人需要帮助扩展他的解决方案。

    # Check for missing plugins
    required_plugins = %w(vagrant-list)
    plugin_installed = false
    required_plugins.each do |plugin|
      unless Vagrant.has_plugin?(plugin)
        system "vagrant plugin install #{plugin}"
        plugin_installed = true
      end
    end
    
    # If new plugins installed, restart Vagrant process
    if plugin_installed === true
      exec "vagrant #{ARGV.join' '}"
    end
    

    【讨论】:

    • // ,注意上面的vagrant-list是一个插件的例子,不是代码的必要部分。您可以在此处查看其他 Vagrant 插件:vagrant-lists.github.io
    【解决方案7】:

    在新版本的 Vagrant 上,@Amos Shapira 的回答陷入了无限循环。原因是每次调用vagrant plugin install 也会处理Vagrantfile 并且在处理时执行与安装插件相关的代码,以此类推。

    这是我避免循环的解决方案。

    # Plugins
    #
    # Check if the first argument to the vagrant
    # command is plugin or not to avoid the loop
    if ARGV[0] != 'plugin'
    
      # Define the plugins in an array format
      required_plugins = [
        'vagrant-vbguest', 'vagrant-hostmanager', 
        'vagrant-disksize'
      ]         
      plugins_to_install = required_plugins.select { |plugin| not Vagrant.has_plugin? plugin }
      if not plugins_to_install.empty?
    
        puts "Installing plugins: #{plugins_to_install.join(' ')}"
        if system "vagrant plugin install #{plugins_to_install.join(' ')}"
          exec "vagrant #{ARGV.join(' ')}"
        else
          abort "Installation of one or more plugins has failed. Aborting."
        end
    
      end
    end
    

    【讨论】:

      【解决方案8】:

      我刚刚注意到http://docs.vagrantup.com/v2/plugins/packaging.html这里有一条指令

      Vagrant.require_plugin "vagrant-aws"
      

      这与描述的 fgrehm 完全相同:如果未安装插件,则快速引发错误。

      据我所知,目前还没有办法自动安装插件

      【讨论】:

      • Vagrant.require_plugin 在 1.5+ 已被弃用
      • 这是关于弃用的官方博客文章:vagrantup.com/blog/vagrant-1-5-plugin-improvements.html 根据我的有限理解,它已被弃用,因为它不再需要,Vagrant 现在将自动检查插件依赖项。虽然我并不完全相信我理解这篇博文......
      • 这篇文章谈到自动检查 plugin 依赖项,但我没有看到任何关于 Vagrant 框本身的依赖项。
      • Vagrant.require_plugin 已弃用。与 Vagrant 1.7.4 核对。
      【解决方案9】:

      我的答案非常接近Louis St-Amour's answer,但不是自动安装插件,而是引发错误消息,因此用户必须手动安装插件。

      我希望用户知道任何已安装的插件,因为它们全局应用于所有 Vagrant 实例,而不仅仅是当前的 Vagrantfile。

      Vagrantfile 的顶部为每个插件添加这样一行,在本例中为vagrant-vbguest

       raise "vagrant-vbguest plugin must be installed" unless Vagrant.has_plugin? "vagrant-vbguest"
      

      【讨论】:

        【解决方案10】:

        你可以使用这个项目(我是作者):https://github.com/DevNIX/Vagrant-dependency-manager

        它基于类似的答案,但试图更加完整和稳定。这个想法的最大优点是,你可以分发你的 Vagrantfile,它会在每台计算机上运行,​​而不管在那个环境中安装了插件。

        使用方便:

        1. 复制你的 Vagrantfile 旁边的 dependency_manager.rb
        2. 包含它并调用 check_plugins 将您的依赖项作为数组传递

          例子:

          # -*- mode: ruby -*-
          # vi: set ft=ruby :
          
          require File.dirname(__FILE__)+"./dependency_manager"
          
          check_plugins ["vagrant-exec", "vagrant-hostsupdater", "vagrant-cachier", "vagrant-triggers"]
          
          Vagrant.configure(2) do |config|
          
            config.vm.box = "base"
          
          end
          
        3. ???

        4. 利润!

        我很想合并拉取请求,解决您可能遇到的任何问题,并获得有关新功能的想法。目前我正在考虑更新依赖管理器本身,并需要特定的插件版本:D

        问候!

        【讨论】:

          【解决方案11】:

          我在新安装 Vagrant 时遇到问题,其中 .vagrant.d 目录尚未创建。通过捕获异常,我能够使 Luis St. Amour 的 sn-p 工作。

          required_plugins = %w(vagrant-share vagrant-vbguest)
          
          begin
              plugins_to_install = required_plugins.select { |plugin| not Vagrant.has_plugin? plugin }
              if not plugins_to_install.empty?
                  puts "Installing plugins: #{plugins_to_install.join(' ')}"
                  if system "vagrant plugin install #{plugins_to_install.join(' ')}"
                      exec "vagrant #{ARGV.join(' ')}"
                  else
                      abort "Installation of one or more plugins has failed. Aborting."
                  end
              end
          rescue
              exec "vagrant #{ARGV.join(' ')}"
          end
          

          【讨论】:

          • 在 Windows 上,这给了我错误“使用 'virtualbox' 提供程序将机器 'default' 启动......但另一个进程已经在机器上执行操作”,因为 up 正在运行up。有没有办法避免这种情况而不运行vagrant up 两次?
          【解决方案12】:

          这是我在 Vagrant 1.8 上使用的,它运行良好。把它放在你的 Vagrantfile 中配置块之前的某个地方。

          # install required plugins if necessary
          if ARGV[0] == 'up'
              # add required plugins here
              required_plugins = %w( plugin1 plugin2 plugin3 )
              missing_plugins = []
              required_plugins.each do |plugin|
                  missing_plugins.push(plugin) unless Vagrant.has_plugin? plugin
              end
          
              if ! missing_plugins.empty?
                  install_these = missing_plugins.join(' ')
                  puts "Found missing plugins: #{install_these}.  Installing using sudo..."
                  exec "sudo vagrant plugin install #{install_these}; vagrant up"
              end
          end
          

          【讨论】:

          • 好像不是跨平台的。
          猜你喜欢
          • 2023-04-05
          • 2015-09-13
          • 2018-10-27
          • 1970-01-01
          • 2020-03-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-18
          • 1970-01-01
          相关资源
          最近更新 更多