JSON 元数据文件的 Vagrant box URL

JSON 元数据文件的 Vagrant box URL

在我的 Vagrantfile 中,我可以指定一个框的 URL:

config.vm.box_url = "http://example.com/my-box.pkg"

根据最新文献,我应该能够创建一个包含不同版本盒子的 URL 的 JSON 文件。文档还说,我可以在运行 时使用此 JSON 文件的 URL vagrant box add。我希望能够将该 JSON 文件的 URL 用于config.vm.box_url。但是,这似乎不起作用。当我尝试时,它将其视为一个盒子文件:

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'my-box' could not be found. Attempting to find and install...
    default: Box Provider: virtualbox
    default: Box Version: >= 0
==> default: Adding box 'my-box' (v0) for provider: virtualbox
    default: Downloading: http://example.com/my-box.pkg.json
    default: Progress: 100% (Rate: 876k/s, Estimated time remaining: 0:00:01)
The box failed to unpackage properly. Please verify that the box
file you're trying to add is not corrupted and try again. The
output from attempting to unpackage (if any):

bsdtar.EXE: Unrecognized archive format: Illegal byte sequence
bsdtar.EXE: Error exit delayed from previous errors.

是否可以告诉 Vagrant 在我的 Vagrantfile 中使用框元数据 JSON 文件?我宁愿不使用 Vagrant Cloud。

答案1

从今天起(2016-07-12,vagrant 1.8.4),如果您想以手动方式运行自己的目录(即手动更新框并编辑metadata.json文件),但仍让它像实际目录一样运行,请记住以下几点:

  • 该文件无需命名为“metadata.json”。它可以被命名为任何名称,只要它包含预期的值即可。我在metadata.json这里使用它来进一步阐明下面的步骤。

  • 每个metadata.json文件只能包含一个单独的 box。它可以有多个版本,每个版本可以有多个提供程序(virtualbox、vmware、libvirt)。如果您需要多个 box(例如fedoraubuntu),则需要两个不同的元数据文件。

  • Vagrant 期望metadata.json文件具有某种类型application/json(正如 Nicholas Hinds 上面提到的那样)。如果您的网络服务器没有返回它(或者返回text/plain),vagrant 将假定它是一个实际的盒子文件,并尝试解析它(并惨遭失败)。

  • Hashicorp 的 Atlas (以前是 Vagrant Cloud) 是个例外,因为重定向会将您引导至以 提供的内容text/html。我对此的最佳猜测是它与重定向有关 (有关更多信息,请参见下文)。

  • 盒子文件不需要与元数据文件放在同一个位置。您可以将元数据文件放在本地 Web 服务器中,将盒子放在 Amazon S3 中,这样没有问题。

因此,据我所知,我发现在网络服务器上运行这个并且仍然具有正常功能的最简单方法是这样做:

在您的网站主机上,创建类似于这样的文件和目录结构:

d wwwroot/
d wwwroot/boxes
d wwwroot/boxes/yourname
f wwwroot/boxes/yourname/.htaccess
d wwwroot/boxes/yourname/box1
f wwwroot/boxes/yourname/box1/metadata.json
f wwwroot/boxes/yourname/box1/box1-$version1-$provider.box
f wwwroot/boxes/yourname/box1/box1-$version2-$provider.box
f wwwroot/boxes/yourname/box1/box1-$version2-$otherprovider.box
d wwwroot/boxes/yourname/box2
f wwwroot/boxes/yourname/box2/metadata.json
f wwwroot/boxes/yourname/box2/box2-$version1-$provider.box
(... etc)

(此布局意味着 box1 的“metadata.json”必须具有指向类似内容的 URL http://yourhost/boxes/yourname/box1/box1-$version1-$provider.box

在您的 上.htaccess,确保已metadata.json为目录索引设置。其余的是可选的,用于负缓存和隐藏实际内容:

Header unset Pragma
FileETag None
Header unset ETag
DirectoryIndex metadata.json
IndexIgnore *
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate, private"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"

在您的环境中,导出VAGRANT_SERVER_URL指向您的网络主机的链接。注意不要有尾部斜杠!

export VAGRANT_SERVER_URL="http://yourhost/boxes"

有了这个(以及所有具有正确内容的文件),您可以直接添加您的盒子:

vagrant box add yourname/box1

由于metadata.json是目录的索引文件box1,它应该将内容重定向到它,vagrant 将获取它,解释元数据并下载适当的框。

答案2

再次阅读你的问题后,似乎你正在尝试做一些与我略有不同的事情 - 但我认为我们的最终目标是相同的。

我不想使用 Vagrant Cloud 服务来托管我的基本盒子,但我希望能够将开发环境分发给我的开发团队,并利用文件的功能metadata.json来维护开发环境的版本控制系统,然后我的开发团队只需使用 vagrant 内置的功能就可以使用该系统。

在撰写本文时(2014 年 8 月 5 日),vagrant 文档在这方面非常稀少,大概是因为它是一个相对较新的功能,但我确信 VagrantCloud 有付费层也与此有关。

为了弄清楚如何利用该metadata.json文件来版本控制和分发盒子,我查看了 VagrantCloud 上可用的部分虚拟机。查看完这些虚拟机并阅读了一些 vagrant 代码后,我很容易就弄清楚了如何实现我的目标。

  • 像平常一样打包您的盒子。就我而言,我仅针对虚拟盒子进行打包,因为我们的开发人员将使用它来运行虚拟机。我还将 Vagrantfile 与我的 basebox 一起打包,它为开发环境进行了一些配置(设置适当文件夹的共享、一些基本的 apache 配置、错误日志记录等)
  • 创建一个metadata.json文件来描述你的基本框,我的看起来与此类似:

    {
        "description": "long box description",
        "short_description": "short box description",
        "name": "company/developer-environment",
        "versions": [{
            "version": "1",
            "status": "active",
            "description_html": "<p>Dev Environment</p>",
            "description_markdown": "Dev Environment",
            "providers": [{
                "name": "virtualbox",
                "url": "http:\/\/vagrant.domain.local/dev/company-developer-environment-1.box"
            }]
        }]
    }
    

创建metadata.json文件后,我将其上传到内部网络上运行的本地服务器 ( vagrant.domain.local/metadata.json)。完成后,剩下的就是使用 vagrant 进行测试:

# add the box to vagrant using the definition from metadata.json
# (the box is actually downloaded here, so it can take a minute...or 10)
$ vagrant box add http://vagrant.domain.local/dev/metadata.json

# init the box (this creates a .vagrant folder and a Vagrantfile in the cwd with the appropriate box name)
$ vagrant init company/developer-environment

# boot the box
$ vagrant up

Voila,一个远程托管、共享和版本控制的私人盒子,不需要使用 Vagrant Cloud。

当您创建 box 的新版本时,您将打包它并编辑文件metadata.json。据我所知,您可以使用任何您想要的版本控制方案,无论是语义版本控制(1.0.0、1.0.1 等)还是只是简单的整数版本(1、2、3 等)。当您的 box 用户vagrant upvagrant 会自动检查您的 metadata.json 文件是否有新版本,并会提示他们vagrant box update更新 box。

您还可以通过使用框名称和框 URL 定义基本 Vagrantfile 来跳过vagrant box add <metadata.json url>和位,如下所示:vagrant init

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

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "company/developer-environment"
  config.vm.box_url = "https://vagrant.domain.local/dev/metadata.json"
end

您可以分发包含这些内容的 Vagrantfile,所有用户都可以使用vagrant up。不过,我不确定版本更新后它如何工作。

答案3

Vagrant 要求提供包含application/json内容类型的框元数据 URL。您收到的错误表明 vagrant 已将您的 URL 解释为常规框。

确保您的 HTTP 服务器正确设置了标头。如果您的文件具有扩展名,Content-Type大多数 HTTP 服务器都会自动将标Content-Type 头设置为application/json.json

答案4

你可以试试https://github.com/sparkoo/boxitory。它只是一个简单的 jar 服务器。您将其指向您拥有 vagrant 盒子的目录,它会为 vagrant 创建兼容的 http 接口。然后您只需从 vagrantfile 指向它,就大功告成了。您不必手动处理描述您的盒子的 json 文件、添加新版本、提供商等。这一切都是免费为您完成的。只需添加新的盒子文件,Boxitory 就会在请求时立即返回它。

相关内容