diff --git a/website/Gemfile b/website/Gemfile index a2c4d1525..bb10a536e 100644 --- a/website/Gemfile +++ b/website/Gemfile @@ -1,3 +1,3 @@ source "https://rubygems.org" -gem "middleman-hashicorp", "0.3.28" +gem "middleman-hashicorp", "0.3.29" diff --git a/website/Gemfile.lock b/website/Gemfile.lock index dea170939..acf65a9ef 100644 --- a/website/Gemfile.lock +++ b/website/Gemfile.lock @@ -1,12 +1,12 @@ GEM remote: https://rubygems.org/ specs: - activesupport (4.2.8) + activesupport (4.2.10) i18n (~> 0.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - autoprefixer-rails (7.1.1.2) + autoprefixer-rails (7.1.5) execjs bootstrap-sass (3.3.7) autoprefixer-rails (>= 5.2.1) @@ -39,10 +39,10 @@ GEM eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) erubis (2.7.0) - eventmachine (1.2.3) + eventmachine (1.2.5) execjs (2.7.0) ffi (1.9.18) - haml (5.0.1) + haml (5.0.4) temple (>= 0.8.0) tilt hike (1.2.3) @@ -51,7 +51,7 @@ GEM http_parser.rb (0.6.0) i18n (0.7.0) json (2.1.0) - kramdown (1.13.2) + kramdown (1.15.0) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -78,7 +78,7 @@ GEM rack (>= 1.4.5, < 2.0) thor (>= 0.15.2, < 2.0) tilt (~> 1.4.1, < 2.0) - middleman-hashicorp (0.3.28) + middleman-hashicorp (0.3.29) bootstrap-sass (~> 3.3) builder (~> 3.2) middleman (~> 3.4) @@ -101,11 +101,11 @@ GEM mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) - mini_portile2 (2.2.0) - minitest (5.10.2) - multi_json (1.12.1) - nokogiri (1.8.0) - mini_portile2 (~> 2.2.0) + mini_portile2 (2.3.0) + minitest (5.10.3) + multi_json (1.12.2) + nokogiri (1.8.1) + mini_portile2 (~> 2.3.0) padrino-helpers (0.12.8.1) i18n (~> 0.6, >= 0.6.7) padrino-support (= 0.12.8.1) @@ -115,14 +115,14 @@ GEM rack (1.6.8) rack-livereload (0.3.16) rack - rack-test (0.6.3) - rack (>= 1.0) - rb-fsevent (0.9.8) + rack-test (0.7.0) + rack (>= 1.0, < 3) + rb-fsevent (0.10.2) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) redcarpet (3.4.0) - rouge (2.1.1) - sass (3.4.24) + rouge (2.2.1) + sass (3.4.25) sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) @@ -134,7 +134,7 @@ GEM sprockets (~> 2.0) tilt (~> 1.1) temple (0.8.0) - thor (0.19.4) + thor (0.20.0) thread_safe (0.3.6) tilt (1.4.1) turbolinks (5.0.1) @@ -153,7 +153,7 @@ PLATFORMS ruby DEPENDENCIES - middleman-hashicorp (= 0.3.28) + middleman-hashicorp (= 0.3.29) BUNDLED WITH - 1.15.1 + 1.15.4 diff --git a/website/Makefile b/website/Makefile index 4d3d361b7..ccc3ae634 100644 --- a/website/Makefile +++ b/website/Makefile @@ -1,4 +1,4 @@ -VERSION?="0.3.28" +VERSION?="0.3.29" build: @echo "==> Starting build in Docker..." diff --git a/website/packer.json b/website/packer.json index fd2618f17..cbfb5c565 100644 --- a/website/packer.json +++ b/website/packer.json @@ -8,7 +8,7 @@ "builders": [ { "type": "docker", - "image": "hashicorp/middleman-hashicorp:0.3.28", + "image": "hashicorp/middleman-hashicorp:0.3.29", "discard": "true", "volumes": { "{{ pwd }}": "/website" diff --git a/website/source/docs/vagrant-cloud/api.html.md.erb b/website/source/docs/vagrant-cloud/api.html.md.erb new file mode 100644 index 000000000..3558322b9 --- /dev/null +++ b/website/source/docs/vagrant-cloud/api.html.md.erb @@ -0,0 +1,1395 @@ +--- +layout: "vagrant-cloud" +page_title: "Vagrant Cloud API" +sidebar_current: "vagrant-cloud-api" +--- + +<% content_for :head do %> + + + +<% end %> + +# Vagrant Cloud API + +## Using the API + +Vagrant Cloud provides an API for users to interact with Vagrant Cloud for experimentation, automation, or building new features and tools on top of our existing application. + +### Authentication + +Some API endpoints require authentication to create new resources, update or delete existing resources, or to read a private resource. + +Clients can authenticate using an authentication token. +The token can be passed to Vagrant Cloud one of two ways: + +1. (Preferred) Set the `Authorization` header to `"Bearer "` and the value of the authentication token. +2. Pass the authentication token as an `access_token` URL parameter. + +Examples below will set the header, but feel free to use whichever method is easier for your implementation. + +-> The `X-Atlas-Token` header is also supported for backwards-compatibility. + +### Request and Response Format + +Requests to Vagrant Cloud which include data attributes (`POST` or `PUT`/`PATCH`) should set the `Content-Type` header to `"application/json"`, and include a valid JSON body with the request. + +JSON responses may include an `errors` key, which will contain an array of error strings, as well as a `success` key. +For example: + +```json +{ + "errors": [ + "Resource not found!" + ], + "success": false +} +``` + +### Response Codes + +Vagrant Cloud may respond with the following response codes, depending on the status of the request and context: + +#### Success + +##### **200** OK +##### **201** Created + +#### Client Errors + +##### **401** Unauthorized + +You do not have authorization to access the requested resource. + +##### **402** Payment Required + +You are trying to access a resource which is delinquent on billing. +Please contact the owner of the resource so that they can update their billing information. + +##### **403** Forbidden + +You are attempting to use the system in a way which is not allowed. +There could be required request parameters that are missing, or one of the parameters is invalid. +Please check the response `errors` key, and double-check the examples below for any discrepancies. + +##### **404** Not Found + +The resource you are trying to access does not exist. This may also be returned if you attempt to access a private resource that you don't have authorization to view. + +##### **422** Unprocessable Entity + +##### **429** Too Many Requests + +You are currently being rate-limited. Please decrease your frequency of usage, or contact us at [support+vagrantcloud@hashicorp.com](mailto:support+vagrantcloud@hashicorp.com) with a description of your use case so that we can consider creating an exception. + +#### Server Errors + +##### **500** Internal Server Error + +The server failed to respond to the request for an unknown reason. +Please contact [support+vagrantcloud@hashicorp.com](mailto:support+vagrantcloud@hashicorp.com) with a description of the problem so that we can investigate. + +##### **503** Service Unavailable + +Vagrant Cloud is temporarily in maintenance mode. +Please check the [HashiCorp Status Site](http://status.hashicorp.com) for more information. + +## Creating a usable box from scratch + +-> This assumes that you have a valid Vagrant Cloud authentication token. You can [create one via the API](#create-a-token), or [create one on the Vagrant Cloud website](https://app.vagrantup.com/settings/security). + +In order to create a usable box on Vagrant Cloud, perform the following steps: + +1. [Create a new box](#create-a-box) +1. [Create a new version](#create-a-version) +1. [Create a new provider](#create-a-provider) +1. [Upload a box image for that provider](#upload-a-provider) +1. [Release the version](#release-a-version) + +#### Example Requests + +
+ +
+ ```shell + # Create a new box + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/boxes \ + --data '{ "box": { "username": "myuser", "name": "test" } }' + + # Create a new version + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/versions \ + --data '{ "version": { "version": "1.2.3" } }' + + # Create a new provider + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/providers \ + --data '{ "provider": { "name": "virtualbox" } }' + + # Prepare the provider for upload/get an upload URL + response=$(curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox/upload) + + # Extract the upload URL from the response (requires the jq command) + upload_path=$(echo "$response" | jq .upload_path) + + # Perform the upload + curl $upload_path --request PUT --upload-file virtualbox-1.2.3.box + + # Release the version + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release \ + --request PUT + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json", + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + # Create a new box + api.post "/api/v1/boxes", + json: { box: { username: "myuser", name: "test" } } + + # Create a new version + api.post "/api/v1/box/myuser/test/versions", + json: { version: { version: "1.2.3" } } + + # Create a new provider + api.post "/api/v1/box/myuser/test/version/1.2.3/providers", + json: { provider: { name: "virtualbox" } } + + # Prepare the provider for upload + response = api.get("/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox/upload") + + # Extract the upload URL + upload_path = response.parse['upload_path'] + + # Upload the box image + HTTP.post upload_path, body: File.open("virtualbox-1.2.3.box") + ``` +
+
+ +## Authentication + +### Create a token + +`POST /api/v1/authenticate` + +Creates a new token for the given user. + +#### Arguments + +* `token` + * `desription` (Optional) - A description of the token. +* `two_factor` + * `code` - A two-factor authentication code. Required to use this API method if 2FA is enabled. See [Request a 2FA code](#request-a-2fa-code) if not using a TOTP application. +* `user` + * `login` - Username or email address of the user authenticating. + * `password` - The user's password. + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + https://app.vagrantup.com/api/v1/authenticate \ + --data ' + { + "token": { + "description": "Login from cURL" + }, + "user": { + "login": "myuser", + "password": "secretpassword" + } + } + ' + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json" + ) + + response = api.post("/api/v1/authenticate", json: { + token: { description: "Login from Ruby" }, + user: { login: "myuser", password: "secretpassword" } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +```json +{ + "description": "Login from cURL", + "token": "qwlIE1qBVUafsg.atlasv1.FLwfJSSYkl49i4qZIu8R31GBnI9r8DrW4IQKMppkGq5rD264lRksTqaIN0zY9Bmy0zs", + "token_hash": "7598236a879ecb42cb0f25399d6f25d1d2cfbbc6333392131bbdfba325eb352795c169daa4a61a8094d44afe817a857e0e5fc7dc72a1401eb434577337d1246c", + "created_at": "2017-10-18T19:16:24.956Z" +} +``` + +### Validate a token + +`GET /api/v1/authenticate` + +Responds [`200 OK`](#200-ok) if the authentication request was successful, otherwise responds [`401 Unauthorized`](#401-unauthorized). + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/authenticate + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.get("/api/v1/authenticate") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +### Request a 2FA code + +`POST /api/v1/two-factor/request-code` + +Sends a 2FA code to the requested delivery method. + +#### Arguments + +* `two_factor` + * `delivery_method` - A valid 2FA delivery method. Currently only `sms` is supported. +* `user` + * `login` - Username or email address of the user authenticating. + * `password` - The user's password. + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + https://app.vagrantup.com/api/v1/authenticate \ + --data ' + { + "two_factor": { + "delivery_method": "sms" + }, + "user": { + "login": "myuser", + "password": "secretpassword" + } + } + ' + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json" + ) + + response = api.post("/api/v1/two-factor/request-code", json: { + two_factor: { delivery_method: "sms" }, + user: { login: "myuser", password: "secretpassword" } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +```json +{ + "two_factor": { + "obfuscated_destination": "SMS number ending in 7890" + } +} +``` + +## Organizations + +### Read an organization + +`GET /api/v1/user/:username` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/user/myuser + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.get("/api/v1/user/myuser") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +```json +{ + "username": "myuser", + "avatar_url": "https://www.gravatar.com/avatar/130a640278870c3dada38b3d912ee022?s=460&d=mm", + "profile_html": "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

\n", + "profile_markdown": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "boxes": [] +} +``` + +## Boxes + +### Read a box + +`GET /api/v1/box/:username/:name` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.get("/api/v1/box/myuser/test") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +```json +{ + "created_at": "2017-10-20T14:19:59.842Z", + "updated_at": "2017-10-20T15:23:53.363Z", + "tag": "myuser/test", + "name": "test", + "short_description": "My dev box", + "description_html": "

My development Vagrant box

\n", + "username": "myuser", + "description_markdown": "My development Vagrant box", + "private": true, + "current_version": { + "version": "1.2.3", + "status": "active", + "description_html": "

A new version

\n", + "description_markdown": "A new version", + "created_at": "2017-10-20T15:23:17.184Z", + "updated_at": "2017-10-20T15:23:53.355Z", + "number": "1.2.3", + "release_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release", + "revoke_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke", + "providers": [ + { + "name": "virtualbox", + "hosted": false, + "hosted_token": null, + "original_url": "https://example.com/virtualbox-1.2.3.box", + "created_at": "2017-10-20T15:23:35.718Z", + "updated_at": "2017-10-20T15:23:35.718Z", + "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box" + } + ] + }, + "versions": [ + { + "version": "1.2.3", + "status": "active", + "description_html": "

A new version

\n", + "description_markdown": "A new version", + "created_at": "2017-10-20T15:23:17.184Z", + "updated_at": "2017-10-20T15:23:53.355Z", + "number": "1.2.3", + "release_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release", + "revoke_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke", + "providers": [ + { + "name": "virtualbox", + "hosted": false, + "hosted_token": null, + "original_url": "https://example.com/virtualbox-1.2.3.box", + "created_at": "2017-10-20T15:23:35.718Z", + "updated_at": "2017-10-20T15:23:35.718Z", + "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box" + } + ] + } + ] +} +``` + +### Create a box + +`POST /api/v1/boxes` + +#### Arguments + +* `box` + * `username` - The username of the organization that will own this box. + * `name` - The name of the box. + * `short_description` - A short summary of the box. + * `description` - A longer description of the box. Can be formatted with [Markdown][markdown]. + * `is_private` (Optional, default: `true`) - Whether or not this box is private. + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/boxes \ + --data ' + { + "box": { + "username": "myuser", + "name": "test", + "short_description": "My dev box", + "description": "My development Vagrant box", + "is_private": true + } + } + ' + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json", + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.post("/api/v1/boxes", json: { + box: { + username: "myuser", + name: "test", + short_description: "My dev box", + description: "My development Vagrant box", + is_private: true + } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a box](#read-a-box). + +### Update a box + +`PUT /api/v1/box/:username/:name` + +#### Arguments + +* `box` + * `name` - The name of the box. + * `short_description` - A short summary of the box. + * `description` - A longer description of the box. Can be formatted with [Markdown](https://daringfireball.net/projects/markdown/syntax). + * `is_private` (Optional, default: `true`) - Whether or not this box is private. + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test \ + --request PUT \ + --data ' + { + "box": { + "name": "test", + "short_description": "My dev box", + "description": "My development Vagrant box", + "is_private": true + } + } + ' + ``` + + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json", + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.put("/api/v1/box/myuser/test", json: { + box: { + name: "test", + short_description: "My dev box", + description: "My development Vagrant box", + is_private: true + } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +### Delete a box + +`DELETE /api/v1/box/:username/:name` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + --request DELETE \ + https://app.vagrantup.com/api/v1/box/myuser/test + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.delete("/api/v1/box/myuser/test") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a box](#read-a-box). + +## Versions + +### Read a version + +`GET /api/v1/box/:username/:name/version/:version` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3 + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.get("/api/v1/box/myuser/test/version/1.2.3") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +```json +{ + "version": "1.2.3", + "status": "active", + "description_html": "

A new version

\n", + "description_markdown": "A new version", + "created_at": "2017-10-20T15:23:17.184Z", + "updated_at": "2017-10-20T15:23:53.355Z", + "number": "1.2.3", + "release_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release", + "revoke_url": "https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke", + "providers": [ + { + "name": "virtualbox", + "hosted": false, + "hosted_token": null, + "original_url": "https://example.com/virtualbox-1.2.3.box", + "created_at": "2017-10-20T15:23:35.718Z", + "updated_at": "2017-10-20T15:23:35.718Z", + "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box" + } + ] +} +``` + +### Create a version + +`POST /api/v1/box/:username/:name/versions` + +-> New versions start as `unreleased`. You must create a valid provider before releasing a new version. + +#### Arguments + +* `version` + * `version` - The version number of this version. + * `description` - A description for this version. Can be formatted with [Markdown](https://daringfireball.net/projects/markdown/syntax). + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/versions \ + --data ' + { + "version": { + "version": "1.2.3", + "description": "A new version" + } + } + ' + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json", + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.post("/api/v1/box/myuser/test/versions", json: { + version: { + version: "1.2.3", + description: "A new version" + } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a version](#read-a-version). + +### Update a version + +`PUT /api/v1/box/:username/:name/version/1.2.3` + +#### Arguments + +* `version` + * `version` - The version number of this version. + * `description` - A description for this version. Can be formatted with [Markdown][markdown]. + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3 \ + --request PUT \ + --data ' + { + "version": { + "version": "1.2.3", + "description": "A new version" + } + } + ' + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json", + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.put("/api/v1/box/myuser/test/version/1.2.3", json: { + version: { + name: "1.2.3", + description: "A new version" + } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a version](#read-a-version). + +### Delete a version + +`DELETE /api/v1/box/:username/:name/version/:version` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + --request DELETE \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3 + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.delete("/api/v1/box/myuser/test/version/1.2.3") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a version](#read-a-version). + +### Release a version + +`PUT /api/v1/box/:username/:name/version/1.2.3/release` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/release \ + --request PUT + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.put("/api/v1/box/myuser/test/version/1.2.3/release") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a version](#read-a-version). + +### Revoke a version + +`PUT /api/v1/box/:username/:name/version/1.2.3/revoke` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/revoke \ + --request PUT + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.put("/api/v1/box/myuser/test/version/1.2.3/revoke") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a version](#read-a-version). + +## Providers + +### Read a provider + +`GET /api/v1/box/:username/:name/version/:version/provider/:provider` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.get("/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ + +#### Example Response + +```json +{ + "name": "virtualbox", + "hosted": false, + "hosted_token": null, + "original_url": "https://example.com/virtualbox-1.2.3.box", + "created_at": "2017-10-20T15:23:35.718Z", + "updated_at": "2017-10-20T15:23:35.718Z", + "download_url": "https://vagrantcloud.com/myuser/boxes/test/versions/1.2.3/providers/virtualbox.box" +} +``` + +### Create a provider + +`POST /api/v1/box/:username/:name/version/:version/providers` + +#### Arguments + +* `provider` + * `name` - The name of the provider. + * `url` - A valid URL to download this provider. If omitted, you must [upload](#upload-a-provider) the Vagrant box image for this provider to Vagrant Cloud before the provider can be used. + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/providers \ + --data ' + { + "provider": { + "name": "virtualbox", + "url": "https://example.com/virtualbox-1.2.3.box" + } + } + ' + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json", + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.post("/api/v1/box/myuser/test/version/1.2.3/providers", json: { + provider: { + name: "virtualbox", + url: "https://example.com/virtualbox-1.2.3.box" + } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a provider](#read-a-provider). + +### Update a provider + +`PUT /api/v1/box/:username/:name/version/:version/provider/:provider` + +#### Arguments + +* `provider` + * `name` - The name of the provider. + * `url` - A valid URL to download this provider. If omitted, you must [upload](#TODO) the Vagrant box image for this provider to Vagrant Cloud before the provider can be used. + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Content-Type: application/json" \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/virtualbox \ + --request PUT \ + --data ' + { + "provider": { + "name": "virtualbox", + "url": "https://example.com/virtualbox-1.2.3.box" + } + } + ' + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Content-Type" => "application/json", + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.put("/api/v1/box/myuser/test/version/1.2.3/virtualbox", json: { + provider: { + name: "virtualbox", + url: "https://example.com/virtualbox-1.2.3.box" + } + }) + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a provider](#read-a-provider). + +### Delete a provider + +`DELETE /api/v1/box/:username/:name/version/:version/provider/:provider` + +#### Example Request + +
+ +
+ ```shell + curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + --request DELETE \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/provider/virtualbox + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.delete("/api/v1/box/myuser/test/verison/1.2.3/provider/virtualbox") + + if response.status.success? + # Success, the response attributes are available here. + p response.parse + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +Response body is identical to [Reading a provider](#read-a-provider). + +### Upload a provider + +`GET /api/v1/box/:username/:name/version/:version/provider/:provider/upload` + +Prepares the provider for upload, and returns a JSON blob containing an `upload_path`. + +~> The upload must begin shortly after the response is returned, otherwise the URL will expire. If the URL expires, you can request this same API method again for a new upload URL. + +#### Example Request + +
+ +
+ ```shell + response=$(curl \ + --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \ + https://app.vagrantup.com/api/v1/box/myuser/test/version/1.2.3/virtualbox/upload) + + # Requires the jq command + upload_path=$(echo "$response" | jq .upload_path) + + curl \ + $upload_path \ + --request PUT \ + --upload-file virtualbox-1.2.3.box + ``` + + ```ruby + # gem install http, or add `gem "http"` to your Gemfile + require "http" + + api = HTTP.persistent("https://app.vagrantup.com").headers( + "Authorization" => "Bearer #{ENV['VAGRANT_CLOUD_TOKEN']}" + ) + + response = api.get("/api/v1/box/myuser/test/version/1.2.3/virtualbox/upload") + + if response.status.success? + # Success, you can now upload the box image to the returned URL + upload_path = response.parse['upload_path'] + HTTP.post upload_path, body: File.open("virtualbox-1.2.3.box") + else + # Error, inspect the `errors` key for more information. + p response.code, response.body + end + ``` +
+
+ +#### Example Response + +```json +{ + "upload_path": "https://archivist.hashicorp.com/v1/object/630e42d9-2364-2412-4121-18266770468e" +} +``` + +[markdown]: https://daringfireball.net/projects/markdown/syntax diff --git a/website/source/docs/vagrant-cloud/boxes/catalog.html.md b/website/source/docs/vagrant-cloud/boxes/catalog.html.md index fdd718d67..0153bf388 100644 --- a/website/source/docs/vagrant-cloud/boxes/catalog.html.md +++ b/website/source/docs/vagrant-cloud/boxes/catalog.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Discovering Vagrant Boxes" sidebar_current: "vagrant-cloud-boxes-catalog" --- diff --git a/website/source/docs/vagrant-cloud/boxes/create-version.html.md b/website/source/docs/vagrant-cloud/boxes/create-version.html.md index d171e8704..64fbb1683 100644 --- a/website/source/docs/vagrant-cloud/boxes/create-version.html.md +++ b/website/source/docs/vagrant-cloud/boxes/create-version.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Create a New Box Version" sidebar_current: "vagrant-cloud-boxes-create-version" --- diff --git a/website/source/docs/vagrant-cloud/boxes/create.html.md b/website/source/docs/vagrant-cloud/boxes/create.html.md index 48083c802..c310f5d74 100644 --- a/website/source/docs/vagrant-cloud/boxes/create.html.md +++ b/website/source/docs/vagrant-cloud/boxes/create.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Creating a New Vagrant Box" sidebar_current: "vagrant-cloud-boxes-create-x" --- diff --git a/website/source/docs/vagrant-cloud/boxes/distributing.html.md b/website/source/docs/vagrant-cloud/boxes/distributing.html.md index 7a0fe232b..0b603e9c3 100644 --- a/website/source/docs/vagrant-cloud/boxes/distributing.html.md +++ b/website/source/docs/vagrant-cloud/boxes/distributing.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Distributing Boxes" sidebar_current: "vagrant-cloud-boxes-distributing" --- diff --git a/website/source/docs/vagrant-cloud/boxes/index.html.md b/website/source/docs/vagrant-cloud/boxes/index.html.md index d5f80d00c..33b2f30f3 100644 --- a/website/source/docs/vagrant-cloud/boxes/index.html.md +++ b/website/source/docs/vagrant-cloud/boxes/index.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "About Vagrant Boxes" sidebar_current: "vagrant-cloud-boxes" --- diff --git a/website/source/docs/vagrant-cloud/boxes/lifecycle.html.md b/website/source/docs/vagrant-cloud/boxes/lifecycle.html.md index 9ab31a692..461b25966 100644 --- a/website/source/docs/vagrant-cloud/boxes/lifecycle.html.md +++ b/website/source/docs/vagrant-cloud/boxes/lifecycle.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Box Versioning and Lifecycle" sidebar_current: "vagrant-cloud-boxes-lifecycle" --- diff --git a/website/source/docs/vagrant-cloud/boxes/private.html.md b/website/source/docs/vagrant-cloud/boxes/private.html.md index 3b884270d..283ec6534 100644 --- a/website/source/docs/vagrant-cloud/boxes/private.html.md +++ b/website/source/docs/vagrant-cloud/boxes/private.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Private Boxes" sidebar_current: "vagrant-cloud-boxes-private" --- diff --git a/website/source/docs/vagrant-cloud/boxes/release-workflow.html.md b/website/source/docs/vagrant-cloud/boxes/release-workflow.html.md index b9ed3339f..fb99741de 100644 --- a/website/source/docs/vagrant-cloud/boxes/release-workflow.html.md +++ b/website/source/docs/vagrant-cloud/boxes/release-workflow.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "API Release Workflow" sidebar_current: "vagrant-cloud-boxes-release-workflow" --- diff --git a/website/source/docs/vagrant-cloud/boxes/using.html.md b/website/source/docs/vagrant-cloud/boxes/using.html.md index 41e15bdab..efecef153 100644 --- a/website/source/docs/vagrant-cloud/boxes/using.html.md +++ b/website/source/docs/vagrant-cloud/boxes/using.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Finding and Using Boxes" sidebar_current: "vagrant-cloud-boxes-using" --- diff --git a/website/source/docs/vagrant-cloud/index.html.md b/website/source/docs/vagrant-cloud/index.html.md index 7e2b9d1df..194bbff41 100644 --- a/website/source/docs/vagrant-cloud/index.html.md +++ b/website/source/docs/vagrant-cloud/index.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Vagrant Cloud" sidebar_current: "vagrant-cloud" --- diff --git a/website/source/docs/vagrant-cloud/organizations/authentication-policy.html.md b/website/source/docs/vagrant-cloud/organizations/authentication-policy.html.md index f07e7af2d..65228ba49 100755 --- a/website/source/docs/vagrant-cloud/organizations/authentication-policy.html.md +++ b/website/source/docs/vagrant-cloud/organizations/authentication-policy.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Organization Authentication Policy" sidebar_current: "vagrant-cloud-organizations-authentication-policy" --- diff --git a/website/source/docs/vagrant-cloud/organizations/create.html.md b/website/source/docs/vagrant-cloud/organizations/create.html.md index 82178df6d..efdffac63 100755 --- a/website/source/docs/vagrant-cloud/organizations/create.html.md +++ b/website/source/docs/vagrant-cloud/organizations/create.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Create an Organization" sidebar_current: "vagrant-cloud-organizations-create" --- diff --git a/website/source/docs/vagrant-cloud/organizations/index.html.md b/website/source/docs/vagrant-cloud/organizations/index.html.md index 04c54c73f..7b1bca659 100755 --- a/website/source/docs/vagrant-cloud/organizations/index.html.md +++ b/website/source/docs/vagrant-cloud/organizations/index.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_page_title: "Organizations in Vagrant Cloud" sidebar_current: "vagrant-cloud-organizations" --- diff --git a/website/source/docs/vagrant-cloud/organizations/migrate.html.md b/website/source/docs/vagrant-cloud/organizations/migrate.html.md index 3a61ee4a8..b9431e0e5 100755 --- a/website/source/docs/vagrant-cloud/organizations/migrate.html.md +++ b/website/source/docs/vagrant-cloud/organizations/migrate.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Migrate User to Organization" sidebar_current: "vagrant-cloud-organizations-migrate" --- diff --git a/website/source/docs/vagrant-cloud/request-limits.html.md b/website/source/docs/vagrant-cloud/request-limits.html.md index 085db9931..4d2df895b 100644 --- a/website/source/docs/vagrant-cloud/request-limits.html.md +++ b/website/source/docs/vagrant-cloud/request-limits.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Request Limits" sidebar_current: "vagrant-cloud-request-limits" --- diff --git a/website/source/docs/vagrant-cloud/support.html.md b/website/source/docs/vagrant-cloud/support.html.md index ba3cfcc1d..e5ccff14a 100755 --- a/website/source/docs/vagrant-cloud/support.html.md +++ b/website/source/docs/vagrant-cloud/support.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Vagrant Cloud Support" sidebar_current: "vagrant-cloud-support" --- diff --git a/website/source/docs/vagrant-cloud/users/authentication.html.md b/website/source/docs/vagrant-cloud/users/authentication.html.md index a99945dde..9a8f55ef9 100755 --- a/website/source/docs/vagrant-cloud/users/authentication.html.md +++ b/website/source/docs/vagrant-cloud/users/authentication.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Authentication" sidebar_current: "vagrant-cloud-users-authentication" --- diff --git a/website/source/docs/vagrant-cloud/users/index.html.md b/website/source/docs/vagrant-cloud/users/index.html.md index 2776db9b0..967a4a4ae 100755 --- a/website/source/docs/vagrant-cloud/users/index.html.md +++ b/website/source/docs/vagrant-cloud/users/index.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "User Accounts" sidebar_current: "vagrant-cloud-users" --- diff --git a/website/source/docs/vagrant-cloud/users/recovery.html.md b/website/source/docs/vagrant-cloud/users/recovery.html.md index 17252c864..ed108c83f 100755 --- a/website/source/docs/vagrant-cloud/users/recovery.html.md +++ b/website/source/docs/vagrant-cloud/users/recovery.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Account Recovery" sidebar_current: "vagrant-cloud-users-recovery" --- diff --git a/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md b/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md index c45721b12..3f4b136f1 100644 --- a/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md +++ b/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md @@ -1,5 +1,5 @@ --- -layout: "docs" +layout: "vagrant-cloud" page_title: "Vagrant Cloud Migration" sidebar_current: "vagrant-cloud-migration" --- diff --git a/website/source/layouts/docs.erb b/website/source/layouts/docs.erb index 47f014f59..3bee5f94f 100644 --- a/website/source/layouts/docs.erb +++ b/website/source/layouts/docs.erb @@ -218,42 +218,6 @@ > Vagrant Cloud - <% end %> diff --git a/website/source/layouts/vagrant-cloud.erb b/website/source/layouts/vagrant-cloud.erb new file mode 100644 index 000000000..7cf82278e --- /dev/null +++ b/website/source/layouts/vagrant-cloud.erb @@ -0,0 +1,128 @@ +<% content_for :head do %> + + +<% end %> + +<% wrap_layout :inner do %> + <% content_for :sidebar do %> + + <% end %> + + <%= yield %> +<% end %>