Merge branch 'main' into kc.docs-install-updates
This commit is contained in:
commit
7acb94cac8
1792
.ci/.ci-utility-files/common.sh
Normal file
1792
.ci/.ci-utility-files/common.sh
Normal file
File diff suppressed because it is too large
Load Diff
55
.ci/build.sh
55
.ci/build.sh
@ -1,24 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
success="✅"
|
||||
|
||||
csource="${BASH_SOURCE[0]}"
|
||||
while [ -h "$csource" ] ; do csource="$(readlink "$csource")"; done
|
||||
root="$( cd -P "$( dirname "$csource" )/../" && pwd )"
|
||||
|
||||
. "${root}/.ci/init.sh"
|
||||
|
||||
pushd "${root}" > "${output}"
|
||||
pushd "${root}"
|
||||
|
||||
echo -n "Building RubyGem... "
|
||||
|
||||
# Build our gem
|
||||
wrap gem build *.gemspec \
|
||||
wrap gem build ./*.gemspec \
|
||||
"Failed to build Vagrant RubyGem"
|
||||
|
||||
echo "${success}"
|
||||
|
||||
# Get the path of our new gem
|
||||
g=(vagrant*.gem)
|
||||
gem=$(printf "%s" "${g}")
|
||||
gem=$(printf "%s" "${g[0]}")
|
||||
|
||||
# Store the gem asset
|
||||
wrap aws s3 cp "${gem}" "${ASSETS_PRIVATE_BUCKET}/${repository}/vagrant-main.gem" \
|
||||
"Failed to store Vagrant RubyGem main build"
|
||||
# Create folder to store artifacts
|
||||
wrap mkdir -p "generated-artifacts" \
|
||||
"Failed to create artifiact directory"
|
||||
|
||||
wrap mv "${gem}" ./generated-artifacts \
|
||||
"Failed to move Vagrant RubyGem"
|
||||
|
||||
# Install submodules
|
||||
wrap git submodule update --init --recursive \
|
||||
@ -26,6 +35,8 @@ wrap git submodule update --init --recursive \
|
||||
|
||||
# Build our binaries
|
||||
|
||||
echo -n "Building vagrant-go linux amd64... "
|
||||
|
||||
# Build linux amd64 binary
|
||||
wrap make bin/linux \
|
||||
"Failed to build the Vagrant go linux amd64 binary"
|
||||
@ -38,9 +49,12 @@ wrap mv vagrant vagrant-go_linux_amd64 \
|
||||
wrap zip vagrant-go_linux_amd64 vagrant-go_linux_amd64 \
|
||||
"Failed to compress go linux amd64 binary"
|
||||
|
||||
# Store the binary asset
|
||||
wrap aws s3 cp vagrant-go_linux_amd64.zip "${ASSETS_PRIVATE_BUCKET}/${repository}/vagrant-go_main_linux_amd64.zip" \
|
||||
"Failed to store Vagrant Go linux amd64 main build"
|
||||
# Move the binary asset
|
||||
wrap mv vagrant-go_linux_amd64.zip ./generated-artifacts \
|
||||
"Failed to move Vagrant Go linux amd64 build"
|
||||
|
||||
echo "${success}"
|
||||
echo -n "Building vagrant-go linux 386... "
|
||||
|
||||
# Build linux 386 binary
|
||||
wrap make bin/linux-386 \
|
||||
@ -54,9 +68,12 @@ wrap mv vagrant vagrant-go_linux_386 \
|
||||
wrap zip vagrant-go_linux_386 vagrant-go_linux_386 \
|
||||
"Failed to compress go linux 386 binary"
|
||||
|
||||
# Store the binary asset
|
||||
wrap aws s3 cp vagrant-go_linux_386.zip "${ASSETS_PRIVATE_BUCKET}/${repository}/vagrant-go_main_linux_386.zip" \
|
||||
"Failed to store Vagrant Go linux 386 main build"
|
||||
# Move the binary asset
|
||||
wrap mv vagrant-go_linux_386.zip ./generated-artifacts \
|
||||
"Failed to move Vagrant Go linux 386 build"
|
||||
|
||||
echo "${success}"
|
||||
echo -n "Building vagrant-go darwin amd64... "
|
||||
|
||||
# Build darwin binary
|
||||
wrap make bin/darwin \
|
||||
@ -70,6 +87,14 @@ wrap mv vagrant vagrant-go_darwin_amd64 \
|
||||
wrap zip vagrant-go_darwin_amd64 vagrant-go_darwin_amd64 \
|
||||
"Failed to compress go darwin amd64 binary"
|
||||
|
||||
# Store the binary asset
|
||||
wrap aws s3 cp vagrant-go_darwin_amd64.zip "${ASSETS_PRIVATE_BUCKET}/${repository}/vagrant-go_main_darwin_amd64.zip" \
|
||||
"Failed to store Vagrant Go darwin amd64 main build"
|
||||
# Move the binary asset
|
||||
wrap mv vagrant-go_darwin_amd64.zip ./generated-artifacts \
|
||||
"Failed to move Vagrant Go darwin amd64 build"
|
||||
|
||||
echo "${success}"
|
||||
echo -n "Storing artifacts... "
|
||||
|
||||
# Store the artifacts for the builders
|
||||
draft_release "${ident_ref}" ./generated-artifacts
|
||||
|
||||
echo "${success}"
|
||||
|
||||
@ -1,86 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
echo "🤖 Loading VagrantCI 🤖"
|
||||
|
||||
ldir="$(realpath ./.ci-utility-files)"
|
||||
|
||||
# Disable IMDS lookup
|
||||
export AWS_EC2_METADATA_DISABLED=true
|
||||
|
||||
# If utility files have not yet been pulled, fetch them
|
||||
if [ ! -e "${ldir}/.complete" ]; then
|
||||
|
||||
# Validate that we have the AWS CLI available
|
||||
if ! command -v aws > /dev/null 2>&1; then
|
||||
echo "⚠ ERROR: Missing required aws executable ⚠"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate that we have the jq tool available
|
||||
if ! command -v jq > /dev/null 2>&1; then
|
||||
echo "⚠ ERROR: Missing required jq executable ⚠"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If we have a role defined, assume it so we can get access to files
|
||||
if [ "${AWS_ASSUME_ROLE_ARN}" != "" ] && [ "${AWS_SESSION_TOKEN}" = "" ]; then
|
||||
if output="$(aws sts assume-role --role-arn "${AWS_ASSUME_ROLE_ARN}" --role-session-name "CI-initializer")"; then
|
||||
export CORE_AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}"
|
||||
export CORE_AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}"
|
||||
id="$(printf '%s' "${output}" | jq -r .Credentials.AccessKeyId)" || failed=1
|
||||
key="$(printf '%s' "${output}" | jq -r .Credentials.SecretAccessKey)" || failed=1
|
||||
token="$(printf '%s' "${output}" | jq -r .Credentials.SessionToken)" || failed=1
|
||||
expire="$(printf '%s' "${output}" | jq -r .Credentials.Expiration)" || failed=1
|
||||
if [ "${failed}" = "1" ]; then
|
||||
echo "🛑 ERROR: Failed to extract role credentials 🛑"
|
||||
exit 1
|
||||
fi
|
||||
unset output
|
||||
export AWS_ACCESS_KEY_ID="${id}"
|
||||
export AWS_SECRET_ACCESS_KEY="${key}"
|
||||
export AWS_SESSION_TOKEN="${token}"
|
||||
export AWS_SESSION_EXPIRATION="${expire}"
|
||||
else
|
||||
echo "⛔ ERROR: Failed to assume configured AWS role ⛔"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Create a local directory to stash our stuff in
|
||||
if ! mkdir -p "${ldir}"; then
|
||||
echo "⛔ ERROR: Failed to create utility file directory ⛔"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Jump into local directory and grab files
|
||||
if ! pushd "${ldir}"; then
|
||||
echo "⁉ ERROR: Unexpected error, failed to relocate to expected directory ⁉"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! aws s3 sync "${VAGRANT_CI_LOADER_BUCKET}/ci-files/" ./; then
|
||||
echo "🛑 ERROR: Failed to retrieve utility files 🛑"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! chmod a+x ./*; then
|
||||
echo "⛔ ERROR: Failed to set permissions on CI files ⛔"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Mark that we have pulled files
|
||||
touch .complete || echo "WARNING: Failed to mark CI files as fetched"
|
||||
|
||||
# Time to load and configure
|
||||
if ! popd; then
|
||||
echo "⁉ ERROR: Unexpected error, failed to relocate to expected directory ⁉"
|
||||
exit 1
|
||||
fi
|
||||
csource="${BASH_SOURCE[0]}"
|
||||
while [ -h "$csource" ] ; do csource="$(readlink "$csource")"; done
|
||||
if ! root="$( cd -P "$( dirname "$csource" )/../" && pwd )"; then
|
||||
echo "⛔ ERROR: Failed to determine root local directory ⛔"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "${ldir}/common.sh"
|
||||
export PATH="${PATH}:${ldir}"
|
||||
export root
|
||||
export ci_bin_dir="${root}/.ci/.ci-utility-files"
|
||||
|
||||
if ! source "${ci_bin_dir}/common.sh"; then
|
||||
echo "⛔ ERROR: Failed to source Vagrant CI common file ⛔"
|
||||
exit 1
|
||||
fi
|
||||
export PATH="${PATH}:${ci_bin_dir}"
|
||||
|
||||
# And we are done!
|
||||
echo "🎉 VagrantCI Loaded! 🎉"
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ghr_version="0.13.0"
|
||||
|
||||
# NOTE: This release will generate a new release on the installers
|
||||
# repository which in turn triggers a full package build
|
||||
target_owner="hashicorp"
|
||||
@ -13,15 +11,10 @@ root="$( cd -P "$( dirname "$csource" )/../" && pwd )"
|
||||
|
||||
. "${root}/.ci/init.sh"
|
||||
|
||||
pushd "${root}" > "${output}" 2>&1
|
||||
pushd "${root}"
|
||||
|
||||
# Install ghr
|
||||
wrap curl -Lso /tmp/ghr.tgz "https://github.com/tcnksm/ghr/releases/download/v${ghr_version}/ghr_v${ghr_version}_linux_amd64.tar.gz" \
|
||||
"Failed to download ghr utility"
|
||||
wrap tar -C /tmp/ -xf /tmp/ghr.tgz \
|
||||
"Failed to unpack ghr archive"
|
||||
wrap mv "/tmp/ghr_v${ghr_version}_linux_amd64/ghr" "${root}/.ci/" \
|
||||
"Failed to install ghr utility"
|
||||
install_ghr
|
||||
|
||||
# Build our gem
|
||||
wrap gem build ./*.gemspec \
|
||||
@ -29,7 +22,7 @@ wrap gem build ./*.gemspec \
|
||||
|
||||
# Get the path of our new gem
|
||||
g=(vagrant*.gem)
|
||||
gem=$(printf "%s" "${g}")
|
||||
gem=$(printf "%s" "${g[0]}")
|
||||
|
||||
# Determine the version of the release
|
||||
vagrant_version="$(gem specification "${gem}" version)"
|
||||
@ -91,16 +84,17 @@ repo_owner="${target_owner}"
|
||||
repo_name="${target_repository}"
|
||||
full_sha="main"
|
||||
|
||||
# Use the hashibot token since we are creating the (pre)release
|
||||
# in a different repository.
|
||||
export GITHUB_TOKEN="${HASHIBOT_TOKEN}"
|
||||
|
||||
if [ "${tag}" = "" ]; then
|
||||
if [ -z "${tag}" ]; then
|
||||
echo "Generating Vagrant RubyGem pre-release... "
|
||||
version="v${vagrant_version}+${short_sha}"
|
||||
prerelease "${version}" ./release-assets
|
||||
else
|
||||
# Validate this is a proper release version
|
||||
valid_release_version "${vagrant_version}"
|
||||
if [ $? -ne 0 ]; then
|
||||
if ! valid_release_version "${vagrant_version}"; then
|
||||
fail "Invalid version format for Vagrant release: ${vagrant_version}"
|
||||
fi
|
||||
|
||||
|
||||
1
.github/CONTRIBUTING.md
vendored
1
.github/CONTRIBUTING.md
vendored
@ -21,6 +21,7 @@ To ensure that the Vagrant community remains an open and safe space for everyone
|
||||
3. Unless it is critical, the issue is left for a period of time, giving outside contributors a chance to address the issue. Later, the issue may be assigned to a Vagrant collaborator and planned for a specific release [milestone](https://github.com/hashicorp/vagrant/milestones)
|
||||
4. The issue is addressed in a pull request or commit. The issue will be referenced in the commit message so that the code that fixes it is clearly linked.
|
||||
5. The issue is closed. Sometimes, valid issues will be closed to keep the issue tracker clean. The issue is still indexed and available for future viewers, or can be re-opened if necessary.
|
||||
6. The issue is locked. After about 30 days the issue will be locked. This is done to keep issue activity in open issues and encourge users to open a new issue if an old issue is being encountered again.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/bug-report.md
vendored
2
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Let us know about an unexpected error, a crash, or an incorrect behavior.
|
||||
labels: "bug"
|
||||
labels: "waiting-intake"
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
name: Vagrant Feature request
|
||||
about: Suggest an idea or enhancement for Vagrant
|
||||
title: 'Enhancement Request: Your description here'
|
||||
labels: 'enhancement'
|
||||
labels: ['enhancement', 'waiting-intake']
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
@ -6,18 +6,21 @@ on:
|
||||
- 'CHANGELOG.md'
|
||||
- 'website/**'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-gem:
|
||||
if: github.repository == 'hashicorp/vagrant'
|
||||
name: Build Vagrant RubyGem
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v1
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '2.7'
|
||||
ruby-version: '3.1'
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
@ -26,19 +29,5 @@ jobs:
|
||||
run: ./.ci/build.sh
|
||||
working-directory: ${{github.workspace}}
|
||||
env:
|
||||
ASSETS_LONGTERM_PREFIX: elt
|
||||
ASSETS_PRIVATE_BUCKET: ${{ secrets.ASSETS_PRIVATE_BUCKET }}
|
||||
ASSETS_PRIVATE_LONGTERM: ${{ secrets.ASSETS_PRIVATE_LONGTERM }}
|
||||
ASSETS_PRIVATE_SHORTTERM: ${{ secrets.ASSETS_PRIVATE_SHORTTERM }}
|
||||
ASSETS_PUBLIC_BUCKET: ${{ secrets.ASSETS_PUBLIC_BUCKET }}
|
||||
ASSETS_PUBLIC_LONGTERM: ${{ secrets.ASSETS_PUBLIC_LONGTERM }}
|
||||
ASSETS_PUBLIC_SHORTTERM: ${{ secrets.ASSETS_PUBLIC_SHORTTERM }}
|
||||
ASSETS_SHORTTERM_PREFIX: est
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_ASSUME_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }}
|
||||
HASHIBOT_EMAIL: ${{ secrets.HASHIBOT_EMAIL }}
|
||||
HASHIBOT_TOKEN: ${{ secrets.HASHIBOT_TOKEN }}
|
||||
HASHIBOT_USERNAME: ${{ secrets.HASHIBOT_USERNAME }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
VAGRANT_CI_LOADER_BUCKET: ${{ secrets.VAGRANT_CI_LOADER_BUCKET }}
|
||||
|
||||
17
.github/workflows/check-legacy-links-format.yml
vendored
Normal file
17
.github/workflows/check-legacy-links-format.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: Legacy Link Format Checker
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'website/content/**/*.mdx'
|
||||
- 'website/data/*-nav-data.json'
|
||||
|
||||
jobs:
|
||||
check-links:
|
||||
uses: hashicorp/dev-portal/.github/workflows/docs-content-check-legacy-links-format.yml@d7c2fceac2dc41e3f857f1ce7c344141fd6a13dd
|
||||
with:
|
||||
repo-owner: 'hashicorp'
|
||||
repo-name: 'vagrant'
|
||||
commit-sha: ${{ github.sha }}
|
||||
mdx-directory: 'website/content'
|
||||
nav-data-directory: 'website/data'
|
||||
10
.github/workflows/code.yml
vendored
10
.github/workflows/code.yml
vendored
@ -7,25 +7,17 @@ on:
|
||||
jobs:
|
||||
sync-acceptance:
|
||||
if: github.repository == 'hashicorp/vagrant'
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- name: Set Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '2.6'
|
||||
- name: Sync Acceptance Testing Repository
|
||||
run: ./.ci/sync.sh
|
||||
working-directory: ${{github.workspace}}
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_ASSUME_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }}
|
||||
HASHIBOT_TOKEN: ${{ secrets.HASHIBOT_TOKEN }}
|
||||
HASHIBOT_USERNAME: ${{ secrets.HASHIBOT_USERNAME }}
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
VAGRANT_CI_LOADER_BUCKET: ${{ secrets.VAGRANT_CI_LOADER_BUCKET }}
|
||||
|
||||
11
.github/workflows/go-spectest.yml
vendored
11
.github/workflows/go-spectest.yml
vendored
@ -15,15 +15,15 @@ on:
|
||||
|
||||
jobs:
|
||||
vagrant-spec-tests:
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: ['^1.16']
|
||||
ruby: ['2.7']
|
||||
ruby: ['3.1']
|
||||
name: Vagrant acceptance tests
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
# Also fetch all tags, since we need our version number in the build
|
||||
@ -37,10 +37,7 @@ jobs:
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{matrix.ruby}}
|
||||
- name: Setup ruby vagrant
|
||||
run: |
|
||||
gem install --no-document bundler
|
||||
bundle install
|
||||
bundler-cache: true
|
||||
- name: Build Vagrant
|
||||
run: |
|
||||
git config --global url."https://${HASHIBOT_USERNAME}:${HASHIBOT_TOKEN}@github.com".insteadOf "https://github.com"
|
||||
|
||||
11
.github/workflows/go-testing.yml
vendored
11
.github/workflows/go-testing.yml
vendored
@ -22,15 +22,15 @@ on:
|
||||
|
||||
jobs:
|
||||
unit-tests-go:
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: ['^1.16']
|
||||
ruby: ['2.7', '3.0']
|
||||
ruby: ['3.0', '3.1']
|
||||
name: Vagrant unit tests on Go
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
@ -39,10 +39,7 @@ jobs:
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{matrix.ruby}}
|
||||
- name: Setup ruby vagrant
|
||||
run: |
|
||||
gem install --no-document bundler
|
||||
bundle install
|
||||
bundler-cache: true
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
git config --global url."https://${HASHIBOT_USERNAME}:${HASHIBOT_TOKEN}@github.com".insteadOf "https://github.com"
|
||||
|
||||
11
.github/workflows/lock.yml
vendored
11
.github/workflows/lock.yml
vendored
@ -7,17 +7,12 @@ on:
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-lock-comment: >
|
||||
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
|
||||
|
||||
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
|
||||
issue-lock-inactive-days: '30'
|
||||
pr-lock-comment: >
|
||||
I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
|
||||
|
||||
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
|
||||
pr-lock-inactive-days: '30'
|
||||
|
||||
19
.github/workflows/release.yml
vendored
19
.github/workflows/release.yml
vendored
@ -9,15 +9,16 @@ on:
|
||||
|
||||
jobs:
|
||||
trigger-release:
|
||||
if: github.repository == 'hashicorp/vagrant'
|
||||
name: Trigger Installers Build
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '2.7'
|
||||
ruby-version: '3.1'
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
@ -26,19 +27,7 @@ jobs:
|
||||
run: ./.ci/release.sh
|
||||
working-directory: ${{github.workspace}}
|
||||
env:
|
||||
ASSETS_LONGTERM_PREFIX: elt
|
||||
ASSETS_PRIVATE_BUCKET: est
|
||||
ASSETS_PRIVATE_LONGTERM: ${{ secrets.ASSETS_PRIVATE_LONGTERM }}
|
||||
ASSETS_PRIVATE_SHORTTERM: ${{ secrets.ASSETS_PRIVATE_SHORTTERM }}
|
||||
ASSETS_PUBLIC_BUCKET: ${{ secrets.ASSETS_PUBLIC_BUCKET }}
|
||||
ASSETS_PUBLIC_LONGTERM: ${{ secrets.ASSETS_PUBLIC_LONGTERM }}
|
||||
ASSETS_PUBLIC_SHORTTERM: ${{ secrets.ASSETS_PUBLIC_SHORTTERM }}
|
||||
ASSETS_SHORTTERM_PREFIX: ${{ secrets.ASSETS_SHORTTERM_PREFIX }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_ASSUME_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }}
|
||||
HASHIBOT_EMAIL: ${{ secrets.HASHIBOT_EMAIL }}
|
||||
HASHIBOT_TOKEN: ${{ secrets.HASHIBOT_TOKEN }}
|
||||
HASHIBOT_USERNAME: ${{ secrets.HASHIBOT_USERNAME }}
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
VAGRANT_CI_LOADER_BUCKET: ${{ secrets.VAGRANT_CI_LOADER_BUCKET }}
|
||||
|
||||
59
.github/workflows/spectesting.yml
vendored
59
.github/workflows/spectesting.yml
vendored
@ -8,22 +8,35 @@ on:
|
||||
- cron: '0 5 * * 1-5'
|
||||
|
||||
jobs:
|
||||
slack-vars:
|
||||
if: github.repository == 'hashicorp/vagrant-builders'
|
||||
name: Populate vars
|
||||
runs-on: ['self-hosted', 'ondemand', 'linux', 'type=t3.nano']
|
||||
uses: ./.github/workflows/slack-vars.yml
|
||||
packet-vars:
|
||||
if: github.repository == 'hashicorp/vagrant-builders'
|
||||
name: Populate vars
|
||||
runs-on: ['self-hosted', 'ondemand', 'linux', 'type=t3.nano']
|
||||
uses: ./.github/workflows/packet-vars.yml
|
||||
setup-packet:
|
||||
if: github.repository == 'hashicorp/vagrant-acceptance'
|
||||
runs-on: self-hosted
|
||||
runs-on: ['self-hosted', 'ondemand', 'linux', 'type=t3.nano']
|
||||
name: Build Packet Instance
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v3
|
||||
- name: Create packet instance
|
||||
run: ./.ci/spec/create-packet.sh
|
||||
working-directory: ${{github.workspace}}
|
||||
env:
|
||||
VAGRANT_CI_LOADER_BUCKET: ${{ secrets.VAGRANT_CI_LOADER_BUCKET }}
|
||||
|
||||
PACKET_EXEC_TOKEN: ${{ needs.packet-vars.outputs.PACKET_EXEC_TOKEN }}
|
||||
PACKET_EXEC_PROJECT_ID: ${{ needs.packet-vars.outputs.PACKET_EXEC_PROJECT_ID }}
|
||||
PACKET_SSH_KEY_CONTENT: ${{ needs.packet-vars.outputs.PACKET_SSH_KEY_CONTENT }}
|
||||
PKT_SECRET_PHRASE: ${{ needs.packaging-vars.outputs.ASSETS_PASSWORD }}
|
||||
SLACK_WEBHOOK: ${{ needs.slack-vars.outputs.SLACK_WEBHOOK }}
|
||||
setup-hosts:
|
||||
if: github.repository == 'hashicorp/vagrant-acceptance'
|
||||
runs-on: self-hosted
|
||||
runs-on: ['self-hosted', 'ondemand', 'linux', 'type=t3.nano']
|
||||
name: Vagrant-Spec Start Hosts
|
||||
needs: setup-packet
|
||||
strategy:
|
||||
@ -33,22 +46,26 @@ jobs:
|
||||
providers: ['virtualbox', 'docker']
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Create hosts for tests (provider ${{ matrix.providers }})
|
||||
run: ./.ci/spec/create-hosts.sh
|
||||
working-directory: ${{github.workspace}}
|
||||
env:
|
||||
PACKET_EXEC_TOKEN: ${{ needs.packet-vars.outputs.PACKET_EXEC_TOKEN }}
|
||||
PACKET_EXEC_PROJECT_ID: ${{ needs.packet-vars.outputs.PACKET_EXEC_PROJECT_ID }}
|
||||
PACKET_SSH_KEY_CONTENT: ${{ needs.packet-vars.outputs.PACKET_SSH_KEY_CONTENT }}
|
||||
PKT_SECRET_PHRASE: ${{ needs.packaging-vars.outputs.ASSETS_PASSWORD }}
|
||||
SLACK_WEBHOOK: ${{ needs.slack-vars.outputs.SLACK_WEBHOOK }}
|
||||
VAGRANT_HOST_BOXES: ${{matrix.host_os}}
|
||||
VAGRANT_GUEST_BOXES: ${{matrix.guest_os}}
|
||||
VAGRANT_PRERELEASE_VERSION: ${{ github.event.client_payload.prerelease_version }}
|
||||
VAGRANT_SPEC_PROVIDERS: ${{matrix.providers}}
|
||||
VAGRANT_CI_LOADER_BUCKET: ${{ secrets.VAGRANT_CI_LOADER_BUCKET }}
|
||||
|
||||
spec-tests:
|
||||
if: github.repository == 'hashicorp/vagrant-acceptance'
|
||||
runs-on: self-hosted
|
||||
runs-on: ['self-hosted', 'ondemand', 'linux', 'type=t3.nano']
|
||||
name: Vagrant-Spec Tests
|
||||
needs: setup-hosts
|
||||
strategy:
|
||||
@ -62,31 +79,34 @@ jobs:
|
||||
run: ./.ci/spec/run-test.sh
|
||||
working-directory: ${{github.workspace}}
|
||||
env:
|
||||
PACKET_EXEC_TOKEN: ${{ needs.packet-vars.outputs.PACKET_EXEC_TOKEN }}
|
||||
PACKET_EXEC_PROJECT_ID: ${{ needs.packet-vars.outputs.PACKET_EXEC_PROJECT_ID }}
|
||||
PACKET_SSH_KEY_CONTENT: ${{ needs.packet-vars.outputs.PACKET_SSH_KEY_CONTENT }}
|
||||
PKT_SECRET_PHRASE: ${{ needs.packaging-vars.outputs.ASSETS_PASSWORD }}
|
||||
SLACK_WEBHOOK: ${{ needs.slack-vars.outputs.SLACK_WEBHOOK }}
|
||||
VAGRANT_HOST_BOXES: ${{matrix.host_os}}
|
||||
VAGRANT_GUEST_BOXES: ${{matrix.guest_os}}
|
||||
VAGRANT_SPEC_PROVIDERS: ${{matrix.providers}}
|
||||
VAGRANT_DOCKER_IMAGES: ${{matrix.docker_images}}
|
||||
VAGRANT_CI_LOADER_BUCKET: ${{ secrets.VAGRANT_CI_LOADER_BUCKET }}
|
||||
HASHIBOT_USERNAME: ${{ secrets.HASHIBOT_USERNAME }}
|
||||
HASHIBOT_TOKEN: ${{ secrets.HASHIBOT_TOKEN }}
|
||||
- name: Pull log from guest
|
||||
if: always()
|
||||
run: ./.ci/spec/pull-log.sh
|
||||
env:
|
||||
PACKET_EXEC_TOKEN: ${{ needs.packet-vars.outputs.PACKET_EXEC_TOKEN }}
|
||||
PACKET_EXEC_PROJECT_ID: ${{ needs.packet-vars.outputs.PACKET_EXEC_PROJECT_ID }}
|
||||
PACKET_SSH_KEY_CONTENT: ${{ needs.packet-vars.outputs.PACKET_SSH_KEY_CONTENT }}
|
||||
PKT_SECRET_PHRASE: ${{ needs.packaging-vars.outputs.ASSETS_PASSWORD }}
|
||||
SLACK_WEBHOOK: ${{ needs.slack-vars.outputs.SLACK_WEBHOOK }}
|
||||
VAGRANT_HOST_BOXES: ${{matrix.host_os}}
|
||||
VAGRANT_GUEST_BOXES: ${{matrix.guest_os}}
|
||||
VAGRANT_SPEC_PROVIDERS: ${{matrix.providers}}
|
||||
VAGRANT_DOCKER_IMAGES: ${{matrix.docker_images}}
|
||||
VAGRANT_CI_LOADER_BUCKET: ${{ secrets.VAGRANT_CI_LOADER_BUCKET }}
|
||||
HASHIBOT_USERNAME: ${{ secrets.HASHIBOT_USERNAME }}
|
||||
HASHIBOT_TOKEN: ${{ secrets.HASHIBOT_TOKEN }}
|
||||
- name: Upload log
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: vagrant-spec-${{matrix.providers}}.log
|
||||
path: ${{ github.workspace }}/vagrant-spec.log
|
||||
|
||||
notify-on-success:
|
||||
if: github.repository == 'hashicorp/vagrant-acceptance' && success()
|
||||
runs-on: self-hosted
|
||||
@ -95,6 +115,8 @@ jobs:
|
||||
steps:
|
||||
- name: Notify on Success
|
||||
run: ./.ci/spec/notify-success.sh
|
||||
env:
|
||||
SLACK_WEBHOOK: ${{ needs.slack-vars.outputs.SLACK_WEBHOOK }}
|
||||
|
||||
cleanup:
|
||||
if: github.repository == 'hashicorp/vagrant-acceptance'
|
||||
@ -104,6 +126,11 @@ jobs:
|
||||
steps:
|
||||
- name: Clean Packet
|
||||
run: ./.ci/spec/clean-packet.sh
|
||||
env:
|
||||
PACKET_EXEC_TOKEN: ${{ needs.packet-vars.outputs.PACKET_EXEC_TOKEN }}
|
||||
PACKET_EXEC_PROJECT_ID: ${{ needs.packet-vars.outputs.PACKET_EXEC_PROJECT_ID }}
|
||||
PACKET_SSH_KEY_CONTENT: ${{ needs.packet-vars.outputs.PACKET_SSH_KEY_CONTENT }}
|
||||
PKT_SECRET_PHRASE: ${{ needs.packaging-vars.outputs.ASSETS_PASSWORD }}
|
||||
SLACK_WEBHOOK: ${{ needs.slack-vars.outputs.SLACK_WEBHOOK }}
|
||||
- name: Clean Workspace
|
||||
run: rm -rf ${{ github.workspace }}
|
||||
|
||||
|
||||
16
.github/workflows/test-link-rewrites.yml
vendored
Normal file
16
.github/workflows/test-link-rewrites.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
name: Test Link Rewrites
|
||||
|
||||
on: [deployment_status]
|
||||
|
||||
jobs:
|
||||
test-link-rewrites:
|
||||
if: github.event.deployment_status.state == 'success'
|
||||
uses: hashicorp/dev-portal/.github/workflows/docs-content-link-rewrites-e2e.yml@2aceb60125f6c15f4c8dbe2e4d79148047bfa437
|
||||
with:
|
||||
repo-owner: 'hashicorp'
|
||||
repo-name: 'vagrant'
|
||||
commit-sha: ${{ github.sha }}
|
||||
main-branch-preview-url: 'https://vagrant-git-main-hashicorp.vercel.app/'
|
||||
# Workflow is only intended to run for one single migration PR
|
||||
# This variable does not need to be updated
|
||||
pr-branch-preview-url: 'https://vagrant-git-docs-ambmigrate-link-formats-hashicorp.vercel.app/'
|
||||
12
.github/workflows/testing.yml
vendored
12
.github/workflows/testing.yml
vendored
@ -27,17 +27,21 @@ on:
|
||||
|
||||
jobs:
|
||||
unit-tests-ruby:
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
ruby: [ '2.6', '2.7', '3.0', '3.1' ]
|
||||
ruby: [ '3.0', '3.1', '3.2' ]
|
||||
name: Vagrant unit tests on Ruby ${{ matrix.ruby }}
|
||||
steps:
|
||||
- name: Code Checkout
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{matrix.ruby}}
|
||||
bundler-cache: true
|
||||
- name: install dependencies
|
||||
run: sudo apt -y install libarchive-tools
|
||||
- name: Run Tests
|
||||
run: .ci/test.sh
|
||||
run: bundle exec rake test:unit
|
||||
|
||||
36
CHANGELOG.md
36
CHANGELOG.md
@ -1,4 +1,4 @@
|
||||
## 2.3.2 (Unreleased)
|
||||
## UNRELEASED
|
||||
|
||||
FEATURES:
|
||||
|
||||
@ -8,6 +8,40 @@ BUG FIXES:
|
||||
|
||||
VAGRANT-GO:
|
||||
|
||||
## 2.3.4 (December 9, 2022)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
- host/darwin: Isolate loading incompatible libraries to support EOL platforms [GH-13022]
|
||||
- provider/virtualbox: Detect network type when not provided [GH-13024]
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- host/windows: Add fix for Powershell 7.3.0 [GH-13006]
|
||||
- provider/virtualbox: Adjust hostnet DHCP configuration, ignore invalid devices [GH-13004]
|
||||
- provisioner/ansible: Fix install package names on older debian (and derivatives) versions [GH-13017]
|
||||
|
||||
## 2.3.3 (November 15, 2022)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
- core: Bump net-ssh dependency to 7.0 and remove patches [GH-12979]
|
||||
- synced_folders/rsync: Include ssh `extra_args` value [GH-12973]
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- command/serve: Force root level namespace for Google constant [GH-12989]
|
||||
- guest/solaris: Fix insecure key authorized keys removal [GH-12740]
|
||||
- provider/virtualbox: Fix `:private_network` support for VirtualBox 7 on macOS [GH-12983]
|
||||
- provider/virtualbox: Prevent localization of command output [GH-12994]
|
||||
- provisioner/ansible: Update setup packages in debian capability [GH-12832]
|
||||
|
||||
## 2.3.2 (October 18, 2022)
|
||||
|
||||
FEATURES:
|
||||
|
||||
- provider/virtualbox: Add support for VirtualBox 7.0 [GH-12947]
|
||||
|
||||
## 2.3.1 (September 29, 2022)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
4
LICENSE
4
LICENSE
@ -1,6 +1,4 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2019 Mitchell Hashimoto
|
||||
Copyright (c) 2010 HashiCorp, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@ -153,6 +153,21 @@ _vagrant() {
|
||||
COMPREPLY=($(compgen -W "${box_list}" -- ${cur}))
|
||||
return 0
|
||||
;;
|
||||
"add")
|
||||
local add_commands="\
|
||||
--name \
|
||||
--checksum \
|
||||
--checksum-type \
|
||||
-c --clean \
|
||||
-f --force \
|
||||
"
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=($(compgen -W "${add_commands}" -- ${cur}))
|
||||
else
|
||||
COMPREPLY=($(compgen -o default -- "${cur}"))
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -15,9 +15,6 @@ class Log4r::BasicFormatter
|
||||
end
|
||||
end
|
||||
|
||||
# Add our patches to net-ssh
|
||||
require "vagrant/patches/net-ssh"
|
||||
|
||||
require "optparse"
|
||||
|
||||
module Vagrant
|
||||
@ -42,11 +39,27 @@ module VagrantPlugins
|
||||
OptionParser = Vagrant::OptionParser
|
||||
end
|
||||
|
||||
# Load in our helpers and utilities
|
||||
require "vagrant/shared_helpers"
|
||||
require "rubygems"
|
||||
require "vagrant/util"
|
||||
require "vagrant/plugin/manager"
|
||||
|
||||
# Update the load path so our protos can be located
|
||||
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs").to_s
|
||||
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs/proto").to_s
|
||||
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs/proto/vagrant_plugin_sdk").to_s
|
||||
|
||||
# Load our protos so they are available
|
||||
require 'vagrant/protobufs/proto/vagrant_server/server_pb'
|
||||
require 'vagrant/protobufs/proto/vagrant_server/server_services_pb'
|
||||
require 'vagrant/protobufs/proto/ruby_vagrant/ruby-server_pb'
|
||||
require 'vagrant/protobufs/proto/ruby_vagrant/ruby-server_services_pb'
|
||||
require 'vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb'
|
||||
require 'vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_services_pb'
|
||||
require 'vagrant/protobufs/proto/plugin/grpc_broker_pb'
|
||||
require 'vagrant/protobufs/proto/plugin/grpc_broker_services_pb'
|
||||
|
||||
# Enable logging if it is requested. We do this before
|
||||
# anything else so that we can setup the output before
|
||||
# any logging occurs.
|
||||
|
||||
@ -846,7 +846,7 @@ module Vagrant
|
||||
begin
|
||||
@logger.info("Creating: #{dir}")
|
||||
FileUtils.mkdir_p(dir)
|
||||
rescue Errno::EACCES
|
||||
rescue Errno::EACCES, Errno::EROFS
|
||||
raise Errors::HomeDirectoryNotAccessible, home_path: @home_path.to_s
|
||||
end
|
||||
end
|
||||
|
||||
@ -972,6 +972,10 @@ module Vagrant
|
||||
error_key(:virtualbox_broken_version_040214)
|
||||
end
|
||||
|
||||
class VirtualBoxConfigNotFound < VagrantError
|
||||
error_key(:virtualbox_config_not_found)
|
||||
end
|
||||
|
||||
class VirtualBoxDisksDefinedExceedLimit < VagrantError
|
||||
error_key(:virtualbox_disks_defined_exceed_limit)
|
||||
end
|
||||
@ -1016,6 +1020,10 @@ module Vagrant
|
||||
error_key(:virtualbox_install_incomplete)
|
||||
end
|
||||
|
||||
class VirtualBoxMachineFolderNotFound < VagrantError
|
||||
error_key(:virtualbox_machine_folder_not_found)
|
||||
end
|
||||
|
||||
class VirtualBoxNoName < VagrantError
|
||||
error_key(:virtualbox_no_name)
|
||||
end
|
||||
|
||||
@ -1,286 +0,0 @@
|
||||
require "net/ssh/version"
|
||||
|
||||
# Only patch if we have version 6.1.0 loaded as
|
||||
# these patches pull 6.1.0 up to the as of now
|
||||
# current 6.2.0 beta
|
||||
if Net::SSH::Version::STRING == "6.1.0"
|
||||
module DeprecatedRsaSha1
|
||||
module KeyManager
|
||||
def initialize(logger, options={})
|
||||
@deprecated_rsa_sha1 = options.delete(:deprecated_rsa_sha1)
|
||||
super
|
||||
end
|
||||
|
||||
def sign(identity, data)
|
||||
info = known_identities[identity] or raise Net::SSH::Authentication::KeyManager::KeyManagerError, "the given identity is unknown to the key manager"
|
||||
|
||||
if info[:key].nil? && info[:from] == :file
|
||||
begin
|
||||
info[:key] = Net::SSH::KeyFactory.load_private_key(info[:file], options[:passphrase], !options[:non_interactive], options[:password_prompt])
|
||||
if @deprecated_rsa_sha1 && info[:key].respond_to?(:deprecated_rsa_sha1=)
|
||||
info[:key].deprecated_rsa_sha1 = true
|
||||
Vagrant.global_logger.debug("set RSA SHA1 deprecation on private key: #{info[:key].fingerprint}")
|
||||
end
|
||||
rescue OpenSSL::OpenSSLError, Exception => e
|
||||
raise Net::SSH::Authentication::KeyManager::KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})"
|
||||
end
|
||||
end
|
||||
|
||||
if info[:key]
|
||||
return Net::SSH::Buffer.from(:string, identity.ssh_signature_type,
|
||||
:mstring, info[:key].ssh_do_sign(data.to_s)).to_s
|
||||
end
|
||||
|
||||
if info[:from] == :agent
|
||||
raise Net::SSH::Authentication::KeyManager::KeyManagerError, "the agent is no longer available" unless agent
|
||||
return agent.sign(info[:identity], data.to_s)
|
||||
end
|
||||
|
||||
raise Net::SSH::Authentication::KeyManager::KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})"
|
||||
end
|
||||
|
||||
def load_identities(identities, ask_passphrase, ignore_decryption_errors)
|
||||
identities.map do |identity|
|
||||
begin
|
||||
case identity[:load_from]
|
||||
when :pubkey_file
|
||||
key = Net::SSH::KeyFactory.load_public_key(identity[:pubkey_file])
|
||||
if @deprecated_rsa_sha1 && key.respond_to?(:deprecated_rsa_sha1=)
|
||||
key.deprecated_rsa_sha1 = true
|
||||
Vagrant.global_logger.debug("set RSA SHA1 deprecation on public key: #{key.fingerprint}")
|
||||
end
|
||||
{ public_key: key, from: :file, file: identity[:privkey_file] }
|
||||
when :privkey_file
|
||||
private_key = Net::SSH::KeyFactory.load_private_key(
|
||||
identity[:privkey_file], options[:passphrase], ask_passphrase, options[:password_prompt]
|
||||
)
|
||||
key = private_key.send(:public_key)
|
||||
if @deprecated_rsa_sha1 && key.respond_to?(:deprecated_rsa_sha1=)
|
||||
key.deprecated_rsa_sha1 = true
|
||||
private_key.deprecated_rsa_sha1 = true
|
||||
Vagrant.global_logger.debug("set RSA SHA1 deprecation on public key: #{key.fingerprint}")
|
||||
Vagrant.global_logger.debug("set RSA SHA1 deprecation on private key: #{private_key.fingerprint}")
|
||||
end
|
||||
{ public_key: key, from: :file, file: identity[:privkey_file], key: private_key }
|
||||
when :data
|
||||
private_key = Net::SSH::KeyFactory.load_data_private_key(
|
||||
identity[:data], options[:passphrase], ask_passphrase, "<key in memory>", options[:password_prompt]
|
||||
)
|
||||
key = private_key.send(:public_key)
|
||||
if @deprecated_rsa_sha1 && key.respond_to?(:deprecated_rsa_sha1=)
|
||||
key.deprecated_rsa_sha1 = true
|
||||
private_key.deprecated_rsa_sha1 = true
|
||||
Vagrant.global_logger.debug("set RSA SHA1 deprecation on public key: #{key.fingerprint}")
|
||||
Vagrant.global_logger.debug("set RSA SHA1 deprecation on private key: #{private_key.fingerprint}")
|
||||
end
|
||||
{ public_key: key, from: :key_data, data: identity[:data], key: private_key }
|
||||
else
|
||||
identity
|
||||
end
|
||||
rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError, OpenSSL::PKey::PKeyError, ArgumentError => e
|
||||
if ignore_decryption_errors
|
||||
identity
|
||||
else
|
||||
process_identity_loading_error(identity, e)
|
||||
nil
|
||||
end
|
||||
rescue Exception => e
|
||||
process_identity_loading_error(identity, e)
|
||||
nil
|
||||
end
|
||||
end.compact
|
||||
end
|
||||
end
|
||||
|
||||
module AuthenticationSession
|
||||
def initialize(transport, options={})
|
||||
s_ver_str = transport.server_version.version.
|
||||
match(/OpenSSH_.*?(?<version>\d+\.\d+)/)&.[](:version).to_s
|
||||
Vagrant.global_logger.debug("ssh server version detected: #{s_ver_str}")
|
||||
if !s_ver_str.empty?
|
||||
begin
|
||||
ver = Gem::Version.new(s_ver_str)
|
||||
if ver >= Gem::Version.new("7.2")
|
||||
Vagrant.global_logger.debug("ssh server supports deprecation of RSA SHA1, deprecating")
|
||||
options[:deprecated_rsa_sha1] = true
|
||||
else
|
||||
Vagrant.global_logger.debug("ssh server does not support deprecation of RSA SHA1")
|
||||
end
|
||||
rescue ArgumentError => err
|
||||
Vagrant.global_logger.debug("failed to determine valid ssh server version - #{err}")
|
||||
end
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "net/ssh/transport/algorithms"
|
||||
# net/ssh/transport/algorithms
|
||||
[:kex, :host_key].each do |key|
|
||||
idx = Net::SSH::Transport::Algorithms::ALGORITHMS[key].index(
|
||||
Net::SSH::Transport::Algorithms::DEFAULT_ALGORITHMS[key].last
|
||||
)
|
||||
Net::SSH::Transport::Algorithms::DEFAULT_ALGORITHMS[key].push("rsa-sha2-512")
|
||||
Net::SSH::Transport::Algorithms::DEFAULT_ALGORITHMS[key].push("rsa-sha2-256")
|
||||
Net::SSH::Transport::Algorithms::ALGORITHMS[key].insert(idx, "rsa-sha2-256")
|
||||
Net::SSH::Transport::Algorithms::ALGORITHMS[key].insert(idx, "rsa-sha2-512")
|
||||
end
|
||||
|
||||
require "net/ssh/authentication/key_manager"
|
||||
Net::SSH::Authentication::KeyManager.prepend(DeprecatedRsaSha1::KeyManager)
|
||||
require "net/ssh/authentication/session"
|
||||
Net::SSH::Authentication::Session.prepend(DeprecatedRsaSha1::AuthenticationSession)
|
||||
|
||||
require "net/ssh/authentication/agent"
|
||||
# net/ssh/authentication/agent
|
||||
Net::SSH::Authentication::Agent.class_eval do
|
||||
SSH2_AGENT_LOCK = 22
|
||||
SSH2_AGENT_UNLOCK = 23
|
||||
|
||||
# lock the ssh agent with password
|
||||
def lock(password)
|
||||
type, = send_and_wait(SSH2_AGENT_LOCK, :string, password)
|
||||
raise AgentError, "could not lock agent" if type != SSH_AGENT_SUCCESS
|
||||
end
|
||||
|
||||
# unlock the ssh agent with password
|
||||
def unlock(password)
|
||||
type, = send_and_wait(SSH2_AGENT_UNLOCK, :string, password)
|
||||
raise AgentError, "could not unlock agent" if type != SSH_AGENT_SUCCESS
|
||||
end
|
||||
end
|
||||
|
||||
require "net/ssh/authentication/certificate"
|
||||
# net/ssh/authentication/certificate
|
||||
Net::SSH::Authentication::Certificate.class_eval do
|
||||
def ssh_do_verify(sig, data, options = {})
|
||||
key.ssh_do_verify(sig, data, options)
|
||||
end
|
||||
end
|
||||
|
||||
require "net/ssh/authentication/ed25519"
|
||||
# net/ssh/authentication/ed25519
|
||||
Net::SSH::Authentication::ED25519::PubKey.class_eval do
|
||||
def ssh_do_verify(sig, data, options = {})
|
||||
@verify_key.verify(sig,data)
|
||||
end
|
||||
end
|
||||
|
||||
require "net/ssh/transport/cipher_factory"
|
||||
# net/ssh/transport/cipher_factory
|
||||
Net::SSH::Transport::CipherFactory::SSH_TO_OSSL["aes256-ctr"] = ::OpenSSL::Cipher.ciphers.include?("aes-256-ctr") ? "aes-256-ctr" : "aes-256-ecb"
|
||||
Net::SSH::Transport::CipherFactory::SSH_TO_OSSL["aes192-ctr"] = ::OpenSSL::Cipher.ciphers.include?("aes-192-ctr") ? "aes-192-ctr" : "aes-192-ecb"
|
||||
Net::SSH::Transport::CipherFactory::SSH_TO_OSSL["aes128-ctr"] = ::OpenSSL::Cipher.ciphers.include?("aes-128-ctr") ? "aes-128-ctr" : "aes-128-ecb"
|
||||
|
||||
require "net/ssh/transport/kex/abstract"
|
||||
# net/ssh/transport/kex/abstract
|
||||
Net::SSH::Transport::Kex::Abstract.class_eval do
|
||||
def matching?(key_ssh_type, host_key_alg)
|
||||
return true if key_ssh_type == host_key_alg
|
||||
return true if key_ssh_type == 'ssh-rsa' && ['rsa-sha2-512', 'rsa-sha2-256'].include?(host_key_alg)
|
||||
end
|
||||
|
||||
def verify_server_key(key) #:nodoc:
|
||||
unless matching?(key.ssh_type, algorithms.host_key)
|
||||
raise Net::SSH::Exception, "host key algorithm mismatch '#{key.ssh_type}' != '#{algorithms.host_key}'"
|
||||
end
|
||||
|
||||
blob, fingerprint = generate_key_fingerprint(key)
|
||||
|
||||
unless connection.host_key_verifier.verify(key: key, key_blob: blob, fingerprint: fingerprint, session: connection)
|
||||
raise Net::SSH::Exception, 'host key verification failed'
|
||||
end
|
||||
end
|
||||
|
||||
def verify_signature(result) #:nodoc:
|
||||
response = build_signature_buffer(result)
|
||||
|
||||
hash = digester.digest(response.to_s)
|
||||
|
||||
server_key = result[:server_key]
|
||||
server_sig = result[:server_sig]
|
||||
unless connection.host_key_verifier.verify_signature { server_key.ssh_do_verify(server_sig, hash, host_key: algorithms.host_key) }
|
||||
raise Net::SSH::Exception, 'could not verify server signature'
|
||||
end
|
||||
|
||||
hash
|
||||
end
|
||||
end
|
||||
|
||||
require "net/ssh/transport/openssl"
|
||||
# net/ssh/transport/openssl
|
||||
OpenSSL::PKey::RSA.class_eval do
|
||||
attr_accessor :deprecated_rsa_sha1
|
||||
|
||||
def ssh_do_verify(sig, data, options = {})
|
||||
digester =
|
||||
if options[:host_key] == "rsa-sha2-512"
|
||||
OpenSSL::Digest::SHA512.new
|
||||
elsif options[:host_key] == "rsa-sha2-256"
|
||||
OpenSSL::Digest::SHA256.new
|
||||
else
|
||||
OpenSSL::Digest::SHA1.new
|
||||
end
|
||||
|
||||
verify(digester, sig, data)
|
||||
end
|
||||
|
||||
def ssh_type
|
||||
deprecated_rsa_sha1 ? signature_algorithm : "ssh-rsa"
|
||||
end
|
||||
|
||||
def signature_algorithm
|
||||
"rsa-sha2-256"
|
||||
end
|
||||
|
||||
def ssh_do_sign(data)
|
||||
if deprecated_rsa_sha1
|
||||
sign(OpenSSL::Digest::SHA256.new, data)
|
||||
else
|
||||
sign(OpenSSL::Digest::SHA1.new, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
OpenSSL::PKey::DSA.class_eval do
|
||||
def ssh_do_verify(sig, data, options = {})
|
||||
sig_r = sig[0,20].unpack("H*")[0].to_i(16)
|
||||
sig_s = sig[20,20].unpack("H*")[0].to_i(16)
|
||||
a1sig = OpenSSL::ASN1::Sequence([
|
||||
OpenSSL::ASN1::Integer(sig_r),
|
||||
OpenSSL::ASN1::Integer(sig_s)
|
||||
])
|
||||
return verify(OpenSSL::Digest::SHA1.new, a1sig.to_der, data)
|
||||
end
|
||||
end
|
||||
|
||||
OpenSSL::PKey::EC.class_eval do
|
||||
def ssh_do_verify(sig, data, options = {})
|
||||
digest = digester.digest(data)
|
||||
a1sig = nil
|
||||
|
||||
begin
|
||||
sig_r_len = sig[0, 4].unpack('H*')[0].to_i(16)
|
||||
sig_l_len = sig[4 + sig_r_len, 4].unpack('H*')[0].to_i(16)
|
||||
|
||||
sig_r = sig[4, sig_r_len].unpack('H*')[0]
|
||||
sig_s = sig[4 + sig_r_len + 4, sig_l_len].unpack('H*')[0]
|
||||
|
||||
a1sig = OpenSSL::ASN1::Sequence([
|
||||
OpenSSL::ASN1::Integer(sig_r.to_i(16)),
|
||||
OpenSSL::ASN1::Integer(sig_s.to_i(16))
|
||||
])
|
||||
rescue StandardError
|
||||
end
|
||||
|
||||
if a1sig.nil?
|
||||
return false
|
||||
else
|
||||
dsa_verify_asn1(digest, a1sig.to_der)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "net/ssh"
|
||||
@ -3,7 +3,7 @@ module Vagrant
|
||||
# Generic installation of content to shell config file
|
||||
class InstallShellConfig
|
||||
|
||||
PERPEND_STRING = "# >>>> Vagrant command completion (start)".freeze
|
||||
PREPEND_STRING = "# >>>> Vagrant command completion (start)".freeze
|
||||
APPEND_STRING = "# <<<< Vagrant command completion (end)".freeze
|
||||
|
||||
attr_accessor :prepend_string
|
||||
@ -12,7 +12,7 @@ module Vagrant
|
||||
attr_accessor :config_paths
|
||||
|
||||
def initialize(string_insert, config_paths)
|
||||
@prepend_string = PERPEND_STRING
|
||||
@prepend_string = PREPEND_STRING
|
||||
@string_insert = string_insert
|
||||
@append_string = APPEND_STRING
|
||||
@config_paths = config_paths
|
||||
@ -29,7 +29,7 @@ module Vagrant
|
||||
@logger.info("Searching for config in home #{home}")
|
||||
@config_paths.each do |path|
|
||||
config_file = File.join(home, path)
|
||||
if File.exists?(config_file)
|
||||
if File.exist?(config_file)
|
||||
@logger.info("Found config file #{config_file}")
|
||||
return config_file
|
||||
end
|
||||
|
||||
@ -1,27 +1,11 @@
|
||||
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs").to_s
|
||||
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs/proto").to_s
|
||||
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs/proto/vagrant_plugin_sdk").to_s
|
||||
|
||||
require 'vagrant/protobufs/proto/vagrant_server/server_pb'
|
||||
require 'vagrant/protobufs/proto/vagrant_server/server_services_pb'
|
||||
require 'vagrant/protobufs/proto/ruby_vagrant/ruby-server_pb'
|
||||
require 'vagrant/protobufs/proto/ruby_vagrant/ruby-server_services_pb'
|
||||
require 'vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb'
|
||||
require 'vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_services_pb'
|
||||
require 'vagrant/protobufs/proto/plugin/grpc_broker_pb'
|
||||
require 'vagrant/protobufs/proto/plugin/grpc_broker_services_pb'
|
||||
|
||||
require "optparse"
|
||||
require 'grpc'
|
||||
require 'grpc/health/checker'
|
||||
require 'grpc/health/v1/health_services_pb'
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandServe
|
||||
# Simple constant aliases to reduce namespace typing
|
||||
SDK = Hashicorp::Vagrant::Sdk
|
||||
SRV = Hashicorp::Vagrant
|
||||
Empty = Google::Protobuf::Empty
|
||||
Empty = ::Google::Protobuf::Empty
|
||||
|
||||
autoload :Broker, Vagrant.source_root.join("plugins/commands/serve/broker").to_s
|
||||
autoload :Client, Vagrant.source_root.join("plugins/commands/serve/client").to_s
|
||||
@ -34,6 +18,17 @@ module VagrantPlugins
|
||||
attr_accessor :broker
|
||||
attr_accessor :server
|
||||
attr_reader :cache
|
||||
|
||||
# Loads the required dependencies for this command. This is isolated
|
||||
# into a method so that the dependencies can be loaded just in time when
|
||||
# the command is actually executed.
|
||||
def load_dependencies!
|
||||
return if @dependencies_loaded
|
||||
require 'grpc'
|
||||
require 'grpc/health/checker'
|
||||
require 'grpc/health/v1/health_services_pb'
|
||||
@dependencies_loaded = true
|
||||
end
|
||||
end
|
||||
@cache = Util::Cacher.new
|
||||
|
||||
@ -49,6 +44,9 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def execute
|
||||
# Load dependencies before we start
|
||||
CommandServe.load_dependencies!
|
||||
|
||||
options = {
|
||||
bind: DEFAULT_BIND,
|
||||
min_port: DEFAULT_PORT_RANGE.first,
|
||||
|
||||
@ -5,14 +5,14 @@ module VagrantPlugins
|
||||
module Cap
|
||||
class RemovePublicKey
|
||||
def self.remove_public_key(machine, contents)
|
||||
# TODO: code is identical to linux/cap/remove_public_key
|
||||
# "sed -i" is specific to GNU sed and is not a posix standard option
|
||||
contents = contents.chomp
|
||||
contents = Vagrant::Util::ShellQuote.escape(contents, "'")
|
||||
|
||||
machine.communicate.tap do |comm|
|
||||
if comm.test("test -f ~/.ssh/authorized_keys")
|
||||
comm.execute(
|
||||
"sed -i '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys")
|
||||
"cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.temp && sed '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys.temp > ~/.ssh/authorized_keys && rm ~/.ssh/authorized_keys.temp")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -4,7 +4,7 @@ module VagrantPlugins
|
||||
module HostGentoo
|
||||
class Host < Vagrant.plugin("2", :host)
|
||||
def detect?(env)
|
||||
File.exists?("/etc/gentoo-release")
|
||||
File.exist?("/etc/gentoo-release")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -4,7 +4,7 @@ module VagrantPlugins
|
||||
module HostSlackware
|
||||
class Host < Vagrant.plugin("2", :host)
|
||||
def detect?(env)
|
||||
return File.exists?("/etc/slackware-version") ||
|
||||
return File.exist?("/etc/slackware-version") ||
|
||||
!Dir.glob("/usr/lib/setup/Plamo-*").empty?
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,6 +1,21 @@
|
||||
# Always stop when errors are encountered unless instructed not to
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Check the version of Powershell currently in use. If it's
|
||||
# under 7.3.0 we need to restrict the maximum version of the
|
||||
# security module to prevent errors.
|
||||
# Source: https://github.com/PowerShell/PowerShell/issues/18530
|
||||
$checkVersion = $PSVersionTable.PSVersion
|
||||
if($checkVersion -eq "") {
|
||||
$checkVersion = $(Get-Host).Version
|
||||
}
|
||||
|
||||
if([System.Version]$checkVersion -lt [System.Version]"7.3.0") {
|
||||
Import-Module Microsoft.Powershell.Security -MaximumVersion 3.0.0.0
|
||||
} else {
|
||||
Import-Module Microsoft.Powershell.Security
|
||||
}
|
||||
|
||||
# Vagrant VM creation functions
|
||||
|
||||
function New-VagrantVM {
|
||||
|
||||
@ -21,6 +21,8 @@ module VagrantPlugins
|
||||
VBOX_NET_CONF = "/etc/vbox/networks.conf".freeze
|
||||
# Version of VirtualBox that introduced hostonly network range restrictions
|
||||
HOSTONLY_VALIDATE_VERSION = Gem::Version.new("6.1.28")
|
||||
# Version of VirtualBox on darwin platform that ignores restrictions
|
||||
DARWIN_IGNORE_HOSTONLY_VALIDATE_VERSION = Gem::Version.new("7.0.0")
|
||||
# Default valid range for hostonly networks
|
||||
HOSTONLY_DEFAULT_RANGE = [IPAddr.new("192.168.56.0/21").freeze].freeze
|
||||
|
||||
@ -69,6 +71,21 @@ module VagrantPlugins
|
||||
type = :internal_network
|
||||
end
|
||||
|
||||
if !options.key?(:type) && options.key?(:ip)
|
||||
begin
|
||||
addr = IPAddr.new(options[:ip])
|
||||
options[:type] = if addr.ipv4?
|
||||
:static
|
||||
else
|
||||
:static6
|
||||
end
|
||||
rescue IPAddr::Error => err
|
||||
raise Vagrant::Errors::NetworkAddressInvalid,
|
||||
address: options[:ip], mask: options[:netmask],
|
||||
error: err.message
|
||||
end
|
||||
end
|
||||
|
||||
# Configure it
|
||||
data = nil
|
||||
if type == :private_network
|
||||
@ -479,10 +496,7 @@ module VagrantPlugins
|
||||
#-----------------------------------------------------------------
|
||||
# This creates a host only network for the given configuration.
|
||||
def hostonly_create_network(config)
|
||||
@env[:machine].provider.driver.create_host_only_network(
|
||||
adapter_ip: config[:adapter_ip],
|
||||
netmask: config[:netmask]
|
||||
)
|
||||
@env[:machine].provider.driver.create_host_only_network(config)
|
||||
end
|
||||
|
||||
# This finds a matching host only network for the given configuration.
|
||||
@ -517,7 +531,11 @@ module VagrantPlugins
|
||||
# placed on the valid ranges
|
||||
def validate_hostonly_ip!(ip, driver)
|
||||
return if Gem::Version.new(driver.version) < HOSTONLY_VALIDATE_VERSION ||
|
||||
Vagrant::Util::Platform.windows?
|
||||
(
|
||||
Vagrant::Util::Platform.darwin? &&
|
||||
Gem::Version.new(driver.version) >= DARWIN_IGNORE_HOSTONLY_VALIDATE_VERSION
|
||||
) ||
|
||||
Vagrant::Util::Platform.windows?
|
||||
|
||||
ip = IPAddr.new(ip.to_s) if !ip.is_a?(IPAddr)
|
||||
valid_ranges = load_net_conf
|
||||
|
||||
@ -460,7 +460,9 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
# Append in the options for subprocess
|
||||
command << { notify: [:stdout, :stderr] }
|
||||
# NOTE: We include the LANG env var set to C to prevent command output
|
||||
# from being localized
|
||||
command << { notify: [:stdout, :stderr], env: {LANG: "C"}}
|
||||
|
||||
Vagrant::Util::Busy.busy(int_callback) do
|
||||
Vagrant::Util::Subprocess.execute(@vboxmanage_path, *command, &block)
|
||||
|
||||
@ -65,6 +65,7 @@ module VagrantPlugins
|
||||
"5.2" => Version_5_2,
|
||||
"6.0" => Version_6_0,
|
||||
"6.1" => Version_6_1,
|
||||
"7.0" => Version_7_0,
|
||||
}
|
||||
|
||||
if @@version.start_with?("4.2.14")
|
||||
|
||||
@ -104,15 +104,15 @@ module VagrantPlugins
|
||||
end
|
||||
end
|
||||
|
||||
# Creates a disk. Default format is VDI unless overridden
|
||||
#
|
||||
# @param [String] disk_file
|
||||
# @param [Integer] disk_size - size in bytes
|
||||
# @param [String] disk_format - format of disk, defaults to "VDI"
|
||||
# Creates a disk. Default format is VDI unless overridden
|
||||
#
|
||||
# @param [String] disk_file
|
||||
# @param [Integer] disk_size - size in bytes
|
||||
# @param [String] disk_format - format of disk, defaults to "VDI"
|
||||
# @param [Hash] opts - additional options
|
||||
def create_disk(disk_file, disk_size, disk_format="VDI", **opts)
|
||||
execute("createmedium", '--filename', disk_file, '--sizebyte', disk_size.to_i.to_s, '--format', disk_format)
|
||||
end
|
||||
def create_disk(disk_file, disk_size, disk_format="VDI", **opts)
|
||||
execute("createmedium", '--filename', disk_file, '--sizebyte', disk_size.to_i.to_s, '--format', disk_format)
|
||||
end
|
||||
|
||||
|
||||
def create_host_only_network(options)
|
||||
@ -322,22 +322,22 @@ module VagrantPlugins
|
||||
|
||||
if adapter[:bridge]
|
||||
args.concat(["--bridgeadapter#{adapter[:adapter]}",
|
||||
adapter[:bridge], "--cableconnected#{adapter[:adapter]}", "on"])
|
||||
adapter[:bridge], "--cableconnected#{adapter[:adapter]}", "on"])
|
||||
end
|
||||
|
||||
if adapter[:hostonly]
|
||||
args.concat(["--hostonlyadapter#{adapter[:adapter]}",
|
||||
adapter[:hostonly], "--cableconnected#{adapter[:adapter]}", "on"])
|
||||
adapter[:hostonly], "--cableconnected#{adapter[:adapter]}", "on"])
|
||||
end
|
||||
|
||||
if adapter[:intnet]
|
||||
args.concat(["--intnet#{adapter[:adapter]}",
|
||||
adapter[:intnet], "--cableconnected#{adapter[:adapter]}", "on"])
|
||||
adapter[:intnet], "--cableconnected#{adapter[:adapter]}", "on"])
|
||||
end
|
||||
|
||||
if adapter[:mac_address]
|
||||
args.concat(["--macaddress#{adapter[:adapter]}",
|
||||
adapter[:mac_address]])
|
||||
adapter[:mac_address]])
|
||||
end
|
||||
|
||||
if adapter[:nic_type]
|
||||
@ -361,7 +361,7 @@ module VagrantPlugins
|
||||
|
||||
# If the file already exists we'll throw a custom error
|
||||
raise Vagrant::Errors::VirtualBoxFileExists,
|
||||
stderr: e.extra_data[:stderr]
|
||||
stderr: e.extra_data[:stderr]
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -370,14 +370,14 @@ module VagrantPlugins
|
||||
args = []
|
||||
ports.each do |options|
|
||||
pf_builder = [options[:name],
|
||||
options[:protocol] || "tcp",
|
||||
options[:hostip] || "",
|
||||
options[:hostport],
|
||||
options[:guestip] || "",
|
||||
options[:guestport]]
|
||||
options[:protocol] || "tcp",
|
||||
options[:hostip] || "",
|
||||
options[:hostport],
|
||||
options[:guestip] || "",
|
||||
options[:guestport]]
|
||||
|
||||
args.concat(["--natpf#{options[:adapter] || 1}",
|
||||
pf_builder.join(",")])
|
||||
pf_builder.join(",")])
|
||||
end
|
||||
|
||||
execute("modifyvm", @uuid, *args, retryable: true) if !args.empty?
|
||||
@ -507,11 +507,11 @@ module VagrantPlugins
|
||||
# since this comes first.
|
||||
current_nic = $1.to_i if line =~ /^nic(\d+)=".+?"$/
|
||||
|
||||
# If we care about active VMs only, then we check the state
|
||||
# to verify the VM is running.
|
||||
if active_only && line =~ /^VMState="(.+?)"$/ && $1.to_s != "running"
|
||||
return []
|
||||
end
|
||||
# If we care about active VMs only, then we check the state
|
||||
# to verify the VM is running.
|
||||
if active_only && line =~ /^VMState="(.+?)"$/ && $1.to_s != "running"
|
||||
return []
|
||||
end
|
||||
|
||||
# Parse out the forwarded port information
|
||||
# Forwarding(1)="172.22.8.201tcp32977,tcp,172.22.8.201,32977,,3777"
|
||||
@ -600,7 +600,7 @@ module VagrantPlugins
|
||||
|
||||
if !valid_ip_address?(ip)
|
||||
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound,
|
||||
guest_property: "/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP"
|
||||
guest_property: "/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP"
|
||||
end
|
||||
|
||||
return ip
|
||||
@ -662,13 +662,17 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def read_machine_folder
|
||||
execute("list", "systemproperties", retryable: true).split("\n").each do |line|
|
||||
if line =~ /^Default machine folder:\s+(.+?)$/i
|
||||
return $1.to_s
|
||||
end
|
||||
info = execute("list", "systemproperties", retryable: true)
|
||||
info.each_line do |line|
|
||||
match = line.match(/Default machine folder:\s+(?<folder>.+?)$/i)
|
||||
next if match.nil?
|
||||
return match[:folder]
|
||||
end
|
||||
|
||||
nil
|
||||
@logger.warn("failed to determine machine folder from system properties")
|
||||
@logger.debug("processed output for machine folder lookup:\n#{info}")
|
||||
|
||||
raise Vagrant::Errors::VirtualBoxMachineFolderNotFound
|
||||
end
|
||||
|
||||
def read_network_interfaces
|
||||
@ -771,7 +775,7 @@ module VagrantPlugins
|
||||
# We got VERR_ALREADY_EXISTS. This means that we're renaming to
|
||||
# a VM name that already exists. Raise a custom error.
|
||||
raise Vagrant::Errors::VirtualBoxNameExists,
|
||||
stderr: e.extra_data[:stderr]
|
||||
stderr: e.extra_data[:stderr]
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -791,9 +795,9 @@ module VagrantPlugins
|
||||
hostpath = Vagrant::Util::Platform.windows_path(folder[:hostpath])
|
||||
end
|
||||
args = ["--name",
|
||||
folder[:name],
|
||||
"--hostpath",
|
||||
hostpath]
|
||||
folder[:name],
|
||||
"--hostpath",
|
||||
hostpath]
|
||||
args << "--transient" if folder.key?(:transient) && folder[:transient]
|
||||
|
||||
args << "--automount" if folder.key?(:automount) && folder[:automount]
|
||||
@ -866,8 +870,8 @@ module VagrantPlugins
|
||||
|
||||
# If we reached this point then it didn't work out.
|
||||
raise Vagrant::Errors::VBoxManageError,
|
||||
command: command.inspect,
|
||||
stderr: r.stderr
|
||||
command: command.inspect,
|
||||
stderr: r.stderr
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
302
plugins/providers/virtualbox/driver/version_7_0.rb
Normal file
302
plugins/providers/virtualbox/driver/version_7_0.rb
Normal file
@ -0,0 +1,302 @@
|
||||
require "rexml"
|
||||
require File.expand_path("../version_6_1", __FILE__)
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderVirtualBox
|
||||
module Driver
|
||||
# Driver for VirtualBox 7.0.x
|
||||
class Version_7_0 < Version_6_1
|
||||
# VirtualBox version requirement for using host only networks
|
||||
# instead of host only interfaces
|
||||
HOSTONLY_NET_REQUIREMENT=Gem::Requirement.new(">= 7")
|
||||
# Prefix of name used for host only networks
|
||||
HOSTONLY_NAME_PREFIX="vagrantnet-vbox"
|
||||
DEFAULT_NETMASK="255.255.255.0"
|
||||
|
||||
def initialize(uuid)
|
||||
super
|
||||
|
||||
@logger = Log4r::Logger.new("vagrant::provider::virtualbox_7_0")
|
||||
end
|
||||
|
||||
def read_bridged_interfaces
|
||||
ifaces = super
|
||||
return ifaces if !use_host_only_nets?
|
||||
|
||||
# Get a list of all subnets which are in use for hostonly networks
|
||||
hostonly_ifaces = read_host_only_networks.map do |net|
|
||||
IPAddr.new(net[:lowerip]).mask(net[:networkmask])
|
||||
end
|
||||
|
||||
# Prune any hostonly interfaces in the list
|
||||
ifaces.delete_if { |i|
|
||||
addr = begin
|
||||
IPAddr.new(i[:ip]).mask(i[:netmask])
|
||||
rescue IPAddr::Error => err
|
||||
@logger.warn("skipping bridged interface due to parse error #{err} (#{i}) ")
|
||||
nil
|
||||
end
|
||||
addr.nil? ||
|
||||
hostonly_ifaces.include?(addr)
|
||||
}
|
||||
|
||||
ifaces
|
||||
end
|
||||
|
||||
def delete_unused_host_only_networks
|
||||
return super if !use_host_only_nets?
|
||||
|
||||
# First get the list of existing host only network names
|
||||
network_names = read_host_only_networks.map { |net| net[:name] }
|
||||
# Prune the network names to only include ones we manage
|
||||
network_names.delete_if { |name| !name.start_with?(HOSTONLY_NAME_PREFIX) }
|
||||
|
||||
@logger.debug("managed host only network names: #{network_names}")
|
||||
|
||||
return if network_names.empty?
|
||||
|
||||
# Next get the list of host only networks currently in use
|
||||
inuse_names = []
|
||||
execute("list", "vms", retryable: true).split("\n").each do |line|
|
||||
match = line.match(/^".+?"\s+\{(?<vmid>.+?)\}$/)
|
||||
next if match.nil?
|
||||
begin
|
||||
info = execute("showvminfo", match[:vmid].to_s, "--machinereadable", retryable: true)
|
||||
info.split("\n").each do |vmline|
|
||||
if vmline.start_with?("hostonly-network")
|
||||
net_name = vmline.split("=", 2).last.to_s.gsub('"', "")
|
||||
inuse_names << net_name
|
||||
end
|
||||
end
|
||||
rescue Vagrant::Errors::VBoxManageError => err
|
||||
raise if !err.extra_data[:stderr].include?("VBOX_E_OBJECT_NOT_FOUND")
|
||||
end
|
||||
end
|
||||
|
||||
@logger.debug("currently in use network names: #{inuse_names}")
|
||||
|
||||
# Now remove all the networks not in use
|
||||
(network_names - inuse_names).each do |name|
|
||||
execute("hostonlynet", "remove", "--name", name, retryable: true)
|
||||
end
|
||||
end
|
||||
|
||||
def enable_adapters(adapters)
|
||||
return super if !use_host_only_nets?
|
||||
|
||||
hostonly_adapters = adapters.find_all { |adapter| adapter[:hostonly] }
|
||||
other_adapters = adapters - hostonly_adapters
|
||||
super(other_adapters) if !other_adapters.empty?
|
||||
|
||||
if !hostonly_adapters.empty?
|
||||
args = []
|
||||
hostonly_adapters.each do |adapter|
|
||||
args.concat(["--nic#{adapter[:adapter]}", "hostonlynet"])
|
||||
args.concat(["--host-only-net#{adapter[:adapter]}", adapter[:hostonly],
|
||||
"--cableconnected#{adapter[:adapter]}", "on"])
|
||||
end
|
||||
|
||||
execute("modifyvm", @uuid, *args, retryable: true)
|
||||
end
|
||||
end
|
||||
|
||||
def create_host_only_network(options)
|
||||
# If we are not on macOS, just setup the hostonly interface
|
||||
return super if !use_host_only_nets?
|
||||
|
||||
opts = {
|
||||
netmask: options.fetch(:netmask, DEFAULT_NETMASK),
|
||||
}
|
||||
|
||||
if options[:type] == :dhcp
|
||||
opts[:lower] = options[:dhcp_lower]
|
||||
opts[:upper] = options[:dhcp_upper]
|
||||
else
|
||||
addr = IPAddr.new(options[:adapter_ip])
|
||||
opts[:upper] = opts[:lower] = addr.mask(opts[:netmask]).to_range.first.to_s
|
||||
end
|
||||
|
||||
name_idx = read_host_only_networks.map { |hn|
|
||||
next if !hn[:name].start_with?(HOSTONLY_NAME_PREFIX)
|
||||
hn[:name].sub(HOSTONLY_NAME_PREFIX, "").to_i
|
||||
}.compact.max.to_i + 1
|
||||
opts[:name] = HOSTONLY_NAME_PREFIX + name_idx.to_s
|
||||
|
||||
execute("hostonlynet", "add",
|
||||
"--name", opts[:name],
|
||||
"--netmask", opts[:netmask],
|
||||
"--lower-ip", opts[:lower],
|
||||
"--upper-ip", opts[:upper],
|
||||
retryable: true)
|
||||
|
||||
{
|
||||
name: opts[:name],
|
||||
ip: options[:adapter_ip],
|
||||
netmask: opts[:netmask],
|
||||
}
|
||||
end
|
||||
|
||||
# Disabled when host only nets are in use
|
||||
def reconfig_host_only(options)
|
||||
return super if !use_host_only_nets?
|
||||
end
|
||||
|
||||
# Disabled when host only nets are in use since
|
||||
# the host only nets will provide the dhcp server
|
||||
def remove_dhcp_server(*_, **_)
|
||||
super if !use_host_only_nets?
|
||||
end
|
||||
|
||||
# Disabled when host only nets are in use since
|
||||
# the host only nets will provide the dhcp server
|
||||
def create_dhcp_server(*_, **_)
|
||||
super if !use_host_only_nets?
|
||||
end
|
||||
|
||||
def read_host_only_interfaces
|
||||
return super if !use_host_only_nets?
|
||||
|
||||
# When host only nets are in use, read them and
|
||||
# reformat the information to line up with how
|
||||
# the interfaces is structured
|
||||
read_host_only_networks.map do |net|
|
||||
addr = begin
|
||||
IPAddr.new(net[:lowerip])
|
||||
rescue IPAddr::Error => err
|
||||
@logger.warn("invalid host only network lower IP encountered: #{err} (#{net})")
|
||||
next
|
||||
end
|
||||
# Address of the interface will be the lower bound of the range or
|
||||
# the first available address in the subnet
|
||||
if addr == addr.mask(net[:networkmask])
|
||||
addr = addr.succ
|
||||
end
|
||||
|
||||
net[:netmask] = net[:networkmask]
|
||||
if addr.ipv4?
|
||||
net[:ip] = addr.to_s
|
||||
net[:ipv6] = ""
|
||||
else
|
||||
net[:ip] = ""
|
||||
net[:ipv6] = addr.to_s
|
||||
net[:ipv6_prefix] = net[:netmask]
|
||||
end
|
||||
|
||||
net[:status] = net[:state] == "Enabled" ? "Up" : "Down"
|
||||
|
||||
net
|
||||
end.compact
|
||||
end
|
||||
|
||||
def read_network_interfaces
|
||||
return super if !use_host_only_nets?
|
||||
|
||||
{}.tap do |nics|
|
||||
execute("showvminfo", @uuid, "--machinereadable", retryable: true).each_line do |line|
|
||||
if m = line.match(/nic(?<adapter>\d+)="(?<type>.+?)"$/)
|
||||
nics[m[:adapter].to_i] ||= {}
|
||||
if m[:type] == "hostonlynetwork"
|
||||
nics[m[:adapter].to_i][:type] = :hostonly
|
||||
else
|
||||
nics[m[:adapter].to_i][:type] = m[:type].to_sym
|
||||
end
|
||||
elsif m = line.match(/^bridgeadapter(?<adapter>\d+)="(?<network>.+?)"$/)
|
||||
nics[m[:adapter].to_i] ||= {}
|
||||
nics[m[:adapter].to_i][:bridge] = m[:network]
|
||||
elsif m = line.match(/^hostonly-network(?<adapter>\d+)="(?<network>.+?)"$/)
|
||||
nics[m[:adapter].to_i] ||= {}
|
||||
nics[m[:adapter].to_i][:hostonly] = m[:network]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Generate list of host only networks
|
||||
def read_host_only_networks
|
||||
networks = []
|
||||
current = nil
|
||||
execute("list", "hostonlynets", retryable: true).split("\n").each do |line|
|
||||
line.chomp!
|
||||
next if line.empty?
|
||||
key, value = line.split(":", 2).map(&:strip)
|
||||
key = key.downcase
|
||||
if key == "name"
|
||||
networks.push(current) if !current.nil?
|
||||
current = Vagrant::Util::HashWithIndifferentAccess.new
|
||||
end
|
||||
current[key] = value
|
||||
end
|
||||
networks.push(current) if !current.nil?
|
||||
|
||||
networks
|
||||
end
|
||||
|
||||
# The initial VirtualBox 7.0 release has an issue with displaying port
|
||||
# forward information. When a single port forward is defined, the forwarding
|
||||
# information can be found in the `showvminfo` output. Once more than a
|
||||
# single port forward is defined, no forwarding information is provided
|
||||
# in the `showvminfo` output. To work around this we grab the VM configuration
|
||||
# file from the `showvminfo` output and extract the port forward information
|
||||
# from there instead.
|
||||
def read_forwarded_ports(uuid=nil, active_only=false)
|
||||
# Only use this override for the 7.0.0 release.
|
||||
return super if get_version.to_s != "7.0.0"
|
||||
|
||||
uuid ||= @uuid
|
||||
|
||||
@logger.debug("read_forward_ports: uuid=#{uuid} active_only=#{active_only}")
|
||||
|
||||
results = []
|
||||
|
||||
info = execute("showvminfo", uuid, "--machinereadable", retryable: true)
|
||||
result = info.match(/CfgFile="(?<path>.+?)"/)
|
||||
if result.nil?
|
||||
raise Vagrant::Errors::VirtualBoxConfigNotFound,
|
||||
uuid: uuid
|
||||
end
|
||||
|
||||
File.open(result[:path], "r") do |f|
|
||||
doc = REXML::Document.new(f)
|
||||
networks = REXML::XPath.each(doc.root, "//Adapter")
|
||||
networks.each do |net|
|
||||
REXML::XPath.each(doc.root, net.xpath + "/NAT/Forwarding") do |fwd|
|
||||
# Result Array values:
|
||||
# [NIC Slot, Name, Host Port, Guest Port, Host IP]
|
||||
result = [
|
||||
net.attribute("slot").value.to_i + 1,
|
||||
fwd.attribute("name")&.value.to_s,
|
||||
fwd.attribute("hostport")&.value.to_i,
|
||||
fwd.attribute("guestport")&.value.to_i,
|
||||
fwd.attribute("hostip")&.value.to_s
|
||||
]
|
||||
@logger.debug(" - #{result.inspect}")
|
||||
results << result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
results
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns if hostonlynets are enabled on the current
|
||||
# host platform
|
||||
#
|
||||
# @return [Boolean]
|
||||
def use_host_only_nets?
|
||||
Vagrant::Util::Platform.darwin? &&
|
||||
HOSTONLY_NET_REQUIREMENT.satisfied_by?(get_version)
|
||||
end
|
||||
|
||||
# VirtualBox version in use
|
||||
#
|
||||
# @return [Gem::Version]
|
||||
def get_version
|
||||
return @version if @version
|
||||
@version = Gem::Version.new(Meta.new.version)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -100,6 +100,7 @@ module VagrantPlugins
|
||||
autoload :Version_5_2, File.expand_path("../driver/version_5_2", __FILE__)
|
||||
autoload :Version_6_0, File.expand_path("../driver/version_6_0", __FILE__)
|
||||
autoload :Version_6_1, File.expand_path("../driver/version_6_1", __FILE__)
|
||||
autoload :Version_7_0, File.expand_path("../driver/version_7_0", __FILE__)
|
||||
end
|
||||
|
||||
module Model
|
||||
|
||||
@ -37,7 +37,11 @@ INLINE_CRIPT
|
||||
|
||||
def self.pip_setup(machine, pip_install_cmd = "")
|
||||
machine.communicate.sudo "apt-get update -y -qq"
|
||||
machine.communicate.sudo "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --option \"Dpkg::Options::=--force-confold\" build-essential curl git libssl-dev libffi-dev python-dev"
|
||||
python_dev_pkg = "python-dev"
|
||||
if machine.communicate.test "apt-cache show python-dev-is-python3"
|
||||
python_dev_pkg = "python-dev-is-python3"
|
||||
end
|
||||
machine.communicate.sudo "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --option \"Dpkg::Options::=--force-confold\" build-essential curl git libssl-dev libffi-dev #{python_dev_pkg}"
|
||||
Pip::get_pip machine, pip_install_cmd
|
||||
end
|
||||
|
||||
|
||||
@ -185,7 +185,7 @@ module VagrantPlugins
|
||||
|
||||
inventory_file = Pathname.new(File.join(inventory_path, 'vagrant_ansible_inventory'))
|
||||
@@lock.synchronize do
|
||||
if !File.exists?(inventory_file) or inventory_content != File.read(inventory_file)
|
||||
if !File.exist?(inventory_file) or inventory_content != File.read(inventory_file)
|
||||
begin
|
||||
# ansible dir inventory will ignore files starting with '.'
|
||||
inventory_tmpfile = Tempfile.new('.vagrant_ansible_inventory', inventory_path)
|
||||
|
||||
@ -81,7 +81,7 @@ module VagrantPlugins
|
||||
errors << I18n.t("vagrant.config.chef.nodes_path_empty")
|
||||
else
|
||||
missing_paths = Array.new
|
||||
nodes_path.each { |dir| missing_paths << dir[1] if !File.exists? dir[1] }
|
||||
nodes_path.each { |dir| missing_paths << dir[1] if !File.exist? dir[1] }
|
||||
# If it exists at least one path on disk it's ok for Chef provisioning
|
||||
if missing_paths.size == nodes_path.size
|
||||
errors << I18n.t("vagrant.config.chef.nodes_path_missing", path: missing_paths.to_s)
|
||||
|
||||
@ -108,6 +108,7 @@ module VagrantPlugins
|
||||
ssh_config_file,
|
||||
control_options,
|
||||
]
|
||||
rsh += ssh_info[:extra_args] if ssh_info[:extra_args]
|
||||
|
||||
# Solaris/OpenSolaris/Illumos uses SunSSH which doesn't support the
|
||||
# IdentitiesOnly option. Also, we don't enable it if keys_only is false
|
||||
|
||||
@ -1743,6 +1743,11 @@ en:
|
||||
4.2.14 contains a critical bug which prevents it from working with
|
||||
Vagrant. VirtualBox 4.2.16+ fixes this problem. Please upgrade
|
||||
VirtualBox.
|
||||
virtualbox_config_not_found: |-
|
||||
Vagrant was unable to locate the configuration file for the requested
|
||||
VirtualBox VM. Verify the requested VM exists and try again.
|
||||
|
||||
UUID provided: %{uuid}
|
||||
virtualbox_disks_controller_not_found: |-
|
||||
Vagrant expected to find a storage controller called '%{name}',
|
||||
but there is no controller with this name attached to the current VM.
|
||||
@ -1789,6 +1794,10 @@ en:
|
||||
VirtualBox is complaining that the installation is incomplete. Please
|
||||
run `VBoxManage --version` to see the error message which should contain
|
||||
instructions on how to fix this error.
|
||||
virtualbox_machine_folder_not_found: |-
|
||||
Vagrant failed to determine the machine folder on this host from
|
||||
the VirtualBox system information. Try running the command again.
|
||||
If this error persists, please report this error as a bug.
|
||||
virtualbox_mount_failed: |-
|
||||
Vagrant was unable to mount VirtualBox shared folders. This is usually
|
||||
because the filesystem "vboxsf" is not available. This filesystem is
|
||||
|
||||
@ -231,10 +231,10 @@ describe VagrantPlugins::ProviderVirtualBox::Action::Network do
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(driver).to have_received(:create_host_only_network).with({
|
||||
expect(driver).to have_received(:create_host_only_network).with(hash_including({
|
||||
adapter_ip: interface_ip,
|
||||
netmask: 64,
|
||||
})
|
||||
}))
|
||||
|
||||
expect(guest).to have_received(:capability).with(:configure_networks, [{
|
||||
type: :static6,
|
||||
@ -308,10 +308,10 @@ describe VagrantPlugins::ProviderVirtualBox::Action::Network do
|
||||
|
||||
subject.call(env)
|
||||
|
||||
expect(driver).to have_received(:create_host_only_network).with({
|
||||
expect(driver).to have_received(:create_host_only_network).with(hash_including({
|
||||
adapter_ip: '192.168.56.1',
|
||||
netmask: '255.255.255.0',
|
||||
})
|
||||
}))
|
||||
|
||||
expect(driver).to have_received(:create_dhcp_server).with('vboxnet0', {
|
||||
adapter_ip: "192.168.56.1",
|
||||
@ -402,6 +402,33 @@ describe VagrantPlugins::ProviderVirtualBox::Action::Network do
|
||||
end
|
||||
end
|
||||
|
||||
context "without type set" do
|
||||
before { allow(subject).to receive(:hostonly_adapter).and_return({}) }
|
||||
|
||||
[
|
||||
{ ip: "192.168.63.5" },
|
||||
{ ip: "192.168.63.5", netmask: "255.255.255.0" },
|
||||
{ ip: "dead:beef::100" },
|
||||
{ ip: "dead:beef::100", netmask: 96 },
|
||||
].each do |args|
|
||||
it "sets the type automatically" do
|
||||
machine.config.vm.network "private_network", **args
|
||||
expect(subject).to receive(:hostonly_config) do |config|
|
||||
expect(config).to have_key(:type)
|
||||
addr = IPAddr.new(args[:ip])
|
||||
if addr.ipv4?
|
||||
expect(config[:type]).to eq(:static)
|
||||
else
|
||||
expect(config[:type]).to eq(:static6)
|
||||
end
|
||||
config
|
||||
end
|
||||
subject.call(env)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#hostonly_find_matching_network" do
|
||||
let(:ip){ "192.168.55.2" }
|
||||
let(:config){ {ip: ip, netmask: "255.255.255.0"} }
|
||||
|
||||
@ -186,4 +186,91 @@ OUTPUT
|
||||
expect(storage_controllers.first.attachments).to eq(attachments_result)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#read_machine_folder" do
|
||||
let(:system_properties) { VBOX_SYSTEM_PROPERTIES }
|
||||
let(:machine_folder) { "/home/username/VirtualBox VMs"}
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:execute).
|
||||
with("list", "systemproperties", any_args).
|
||||
and_return(system_properties)
|
||||
end
|
||||
|
||||
it "should read the default folder" do
|
||||
expect(subject.read_machine_folder).to eq(machine_folder)
|
||||
end
|
||||
|
||||
context "when default folder value is missing" do
|
||||
let(:system_properties) { VBOX_SYSTEM_PROPERTIES.sub(/^Default machine folder:.+$/, "")}
|
||||
|
||||
it "should raise a custom error" do
|
||||
expect {
|
||||
subject.read_machine_folder
|
||||
}.to raise_error(Vagrant::Errors::VirtualBoxMachineFolderNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
VBOX_SYSTEM_PROPERTIES=%(
|
||||
API version: 7_0
|
||||
Minimum guest RAM size: 4 Megabytes
|
||||
Maximum guest RAM size: 2097152 Megabytes
|
||||
Minimum video RAM size: 0 Megabytes
|
||||
Maximum video RAM size: 256 Megabytes
|
||||
Maximum guest monitor count: 64
|
||||
Minimum guest CPU count: 1
|
||||
Maximum guest CPU count: 64
|
||||
Virtual disk limit (info): 2199022206976 Bytes
|
||||
Maximum Serial Port count: 4
|
||||
Maximum Parallel Port count: 2
|
||||
Maximum Boot Position: 4
|
||||
Maximum PIIX3 Network Adapter count: 8
|
||||
Maximum ICH9 Network Adapter count: 36
|
||||
Maximum PIIX3 IDE Controllers: 1
|
||||
Maximum ICH9 IDE Controllers: 1
|
||||
Maximum IDE Port count: 2
|
||||
Maximum Devices per IDE Port: 2
|
||||
Maximum PIIX3 SATA Controllers: 1
|
||||
Maximum ICH9 SATA Controllers: 8
|
||||
Maximum SATA Port count: 30
|
||||
Maximum Devices per SATA Port: 1
|
||||
Maximum PIIX3 SCSI Controllers: 1
|
||||
Maximum ICH9 SCSI Controllers: 8
|
||||
Maximum SCSI Port count: 16
|
||||
Maximum Devices per SCSI Port: 1
|
||||
Maximum SAS PIIX3 Controllers: 1
|
||||
Maximum SAS ICH9 Controllers: 8
|
||||
Maximum SAS Port count: 255
|
||||
Maximum Devices per SAS Port: 1
|
||||
Maximum NVMe PIIX3 Controllers: 1
|
||||
Maximum NVMe ICH9 Controllers: 8
|
||||
Maximum NVMe Port count: 255
|
||||
Maximum Devices per NVMe Port: 1
|
||||
Maximum virtio-scsi PIIX3 Controllers: 1
|
||||
Maximum virtio-scsi ICH9 Controllers: 8
|
||||
Maximum virtio-scsi Port count: 256
|
||||
Maximum Devices per virtio-scsi Port: 1
|
||||
Maximum PIIX3 Floppy Controllers:1
|
||||
Maximum ICH9 Floppy Controllers: 1
|
||||
Maximum Floppy Port count: 1
|
||||
Maximum Devices per Floppy Port: 2
|
||||
Default machine folder: /home/username/VirtualBox VMs
|
||||
Raw-mode Supported: no
|
||||
Exclusive HW virtualization use: on
|
||||
Default hard disk format: VDI
|
||||
VRDE auth library: VBoxAuth
|
||||
Webservice auth. library: VBoxAuth
|
||||
Remote desktop ExtPack:
|
||||
VM encryption ExtPack:
|
||||
Log history count: 3
|
||||
Default frontend:
|
||||
Default audio driver: ALSA
|
||||
Autostart database path:
|
||||
Default Guest Additions ISO: /usr/share/virtualbox/VBoxGuestAdditions.iso
|
||||
Logging Level: all
|
||||
Proxy Mode: System
|
||||
Proxy URL:
|
||||
User language: en_US
|
||||
)
|
||||
|
||||
@ -0,0 +1,852 @@
|
||||
require "stringio"
|
||||
require_relative "../base"
|
||||
|
||||
describe VagrantPlugins::ProviderVirtualBox::Driver::Version_7_0 do
|
||||
include_context "virtualbox"
|
||||
|
||||
let(:vbox_version) { "7.0.0" }
|
||||
|
||||
subject { VagrantPlugins::ProviderVirtualBox::Driver::Version_7_0.new(uuid) }
|
||||
|
||||
it_behaves_like "a version 5.x virtualbox driver"
|
||||
it_behaves_like "a version 6.x virtualbox driver"
|
||||
|
||||
describe "#read_forwarded_ports" do
|
||||
let(:uuid) { "MACHINE-UUID" }
|
||||
let(:cfg_path) { "MACHINE_CONFIG_PATH" }
|
||||
let(:vm_info) {
|
||||
%(name="vagrant-test_default_1665781960041_56631"
|
||||
Encryption: disabled
|
||||
groups="/"
|
||||
ostype="Ubuntu (64-bit)"
|
||||
UUID="#{uuid}"
|
||||
CfgFile="#{cfg_path}"
|
||||
SnapFldr="/VirtualBox VMs/vagrant-test_default_1665781960041_56631/Snapshots"
|
||||
LogFldr="/VirtualBox VMs/vagrant-test_default_1665781960041_56631/Logs"
|
||||
memory=1024)
|
||||
}
|
||||
let(:config_file) {
|
||||
StringIO.new(VBOX_VMCONFIG_FILE)
|
||||
}
|
||||
|
||||
before do
|
||||
allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).to receive(:version).and_return(vbox_version)
|
||||
end
|
||||
|
||||
describe "VirtualBox version 7.0.0" do
|
||||
let(:vbox_version) { "7.0.0" }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:execute).with("showvminfo", uuid, any_args).and_return(vm_info)
|
||||
allow(File).to receive(:open).with(cfg_path, "r").and_yield(config_file)
|
||||
end
|
||||
|
||||
it "should return two port forward values" do
|
||||
expect(subject.read_forwarded_ports.size).to eq(2)
|
||||
end
|
||||
|
||||
it "should have port forwards on slot one" do
|
||||
subject.read_forwarded_ports.each do |fwd|
|
||||
expect(fwd.first).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
it "should include host ip for ssh forward" do
|
||||
fwd = subject.read_forwarded_ports.detect { |f| f[1] == "ssh" }
|
||||
expect(fwd).not_to be_nil
|
||||
expect(fwd.last).to eq("127.0.0.1")
|
||||
end
|
||||
|
||||
describe "when config file cannot be determine" do
|
||||
let(:vm_info) { %(name="vagrant-test_default_1665781960041_56631") }
|
||||
|
||||
it "should raise a custom error" do
|
||||
expect(File).not_to receive(:open).with(cfg_path, "r")
|
||||
|
||||
expect { subject.read_forwarded_ports }.to raise_error(Vagrant::Errors::VirtualBoxConfigNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "VirtualBox version greater than 7.0.0" do
|
||||
let(:vbox_version) { "7.0.1" }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:execute).with("showvminfo", uuid, any_args).and_return(vm_info)
|
||||
end
|
||||
|
||||
it "should not read configuration file" do
|
||||
expect(File).not_to receive(:open).with(cfg_path, "r")
|
||||
subject.read_forwarded_ports
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "#use_host_only_nets?" do
|
||||
context "when platform is darwin" do
|
||||
before do
|
||||
allow(Vagrant::Util::Platform).to receive(:darwin?).and_return(true)
|
||||
end
|
||||
|
||||
context "when virtualbox version is less than 7" do
|
||||
before do
|
||||
allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).
|
||||
to receive(:version).and_return("6.0.28")
|
||||
end
|
||||
|
||||
it "should return false" do
|
||||
expect(subject.send(:use_host_only_nets?)).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "when virtualbox version is greater than 7" do
|
||||
before do
|
||||
allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).
|
||||
to receive(:version).and_return("7.0.2")
|
||||
end
|
||||
|
||||
it "should return true" do
|
||||
expect(subject.send(:use_host_only_nets?)).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "when virtualbox version is equal to 7" do
|
||||
before do
|
||||
allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).
|
||||
to receive(:version).and_return("7.0.0")
|
||||
end
|
||||
|
||||
it "should return true" do
|
||||
expect(subject.send(:use_host_only_nets?)).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when platform is not darwin" do
|
||||
before do
|
||||
allow(Vagrant::Util::Platform).to receive(:darwin?).and_return(false)
|
||||
end
|
||||
|
||||
context "when virtualbox version is less than 7" do
|
||||
before do
|
||||
allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).
|
||||
to receive(:version).and_return("6.0.28")
|
||||
end
|
||||
|
||||
it "should return false" do
|
||||
expect(subject.send(:use_host_only_nets?)).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "when virtualbox version is greater than 7" do
|
||||
before do
|
||||
allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).
|
||||
to receive(:version).and_return("7.0.2")
|
||||
end
|
||||
|
||||
it "should return false" do
|
||||
expect(subject.send(:use_host_only_nets?)).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "when virtualbox version is equal to 7" do
|
||||
before do
|
||||
allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).
|
||||
to receive(:version).and_return("7.0.0")
|
||||
end
|
||||
|
||||
it "should return false" do
|
||||
expect(subject.send(:use_host_only_nets?)).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#read_bridged_interfaces" do
|
||||
let(:bridgedifs) { VBOX_BRIDGEDIFS }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:execute).and_call_original
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("list", "bridgedifs").
|
||||
and_return(bridgedifs)
|
||||
end
|
||||
|
||||
context "when hostonlynets are not enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should return all interfaces in list" do
|
||||
expect(subject.read_bridged_interfaces.size).to eq(5)
|
||||
end
|
||||
|
||||
it "should not read host only networks" do
|
||||
expect(subject).not_to receive(:read_host_only_networks)
|
||||
subject.read_bridged_interfaces
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets are enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
end
|
||||
|
||||
it "should return all interfaces in list" do
|
||||
expect(subject).to receive(:read_host_only_networks).and_return([])
|
||||
expect(subject.read_bridged_interfaces.size).to eq(5)
|
||||
end
|
||||
|
||||
context "when hostonly networks are defined" do
|
||||
before do
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("list", "hostonlynets", any_args).
|
||||
and_return(VBOX_HOSTONLYNETS)
|
||||
end
|
||||
|
||||
it "should not return all interfaces in list" do
|
||||
expect(subject.read_bridged_interfaces.size).to_not eq(5)
|
||||
end
|
||||
|
||||
it "should not include hostonly network devices" do
|
||||
expect(
|
||||
subject.read_bridged_interfaces.any? { |int|
|
||||
int[:name].start_with?("bridge")
|
||||
}
|
||||
).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when address is empty" do
|
||||
let(:bridgedifs) { VBOX_BRIDGEDIFS.sub("0.0.0.0", "") }
|
||||
|
||||
it "should not raise an error" do
|
||||
expect { subject.read_bridged_interfaces }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#delete_unused_host_only_networks" do
|
||||
context "when hostonlynets are not enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should remove host only interfaces" do
|
||||
expect(subject).to receive(:execute).with("list", "hostonlyifs", any_args).and_return("")
|
||||
expect(subject).to receive(:execute).with("list", "vms", any_args).and_return("")
|
||||
subject.delete_unused_host_only_networks
|
||||
end
|
||||
|
||||
it "should not read host only networks" do
|
||||
expect(subject).to receive(:execute).with("list", "hostonlyifs", any_args).and_return("")
|
||||
expect(subject).to receive(:execute).with("list", "vms", any_args).and_return("")
|
||||
expect(subject).not_to receive(:read_host_only_networks)
|
||||
subject.delete_unused_host_only_networks
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets are enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
allow(subject).to receive(:read_host_only_networks).and_return([])
|
||||
allow(subject).to receive(:execute).with("list", "vms", any_args).and_return("")
|
||||
end
|
||||
|
||||
it "should not read host only interfaces" do
|
||||
expect(subject).not_to receive(:execute).with("list", "hostonlyifs", any_args)
|
||||
subject.delete_unused_host_only_networks
|
||||
end
|
||||
|
||||
context "when no host only networks are defined" do
|
||||
before do
|
||||
expect(subject).to receive(:read_host_only_networks).and_return([])
|
||||
end
|
||||
|
||||
it "should not list vms" do
|
||||
expect(subject).not_to receive(:execute).with("list", "vms", any_args)
|
||||
subject.delete_unused_host_only_networks
|
||||
end
|
||||
end
|
||||
|
||||
context "when host only networks are defined" do
|
||||
before do
|
||||
expect(subject).
|
||||
to receive(:read_host_only_networks).
|
||||
and_return([{name: "vagrantnet-vbox-1"}])
|
||||
|
||||
end
|
||||
|
||||
context "when no vms are using the network" do
|
||||
before do
|
||||
expect(subject).to receive(:execute).with("list", "vms", any_args).and_return("")
|
||||
end
|
||||
|
||||
it "should delete the network" do
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("hostonlynet", "remove", "--name", "vagrantnet-vbox-1", any_args)
|
||||
subject.delete_unused_host_only_networks
|
||||
end
|
||||
end
|
||||
|
||||
context "when vms are using the network" do
|
||||
before do
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("list", "vms", any_args).
|
||||
and_return(%("VM_NAME" {VM_ID}))
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("showvminfo", "VM_ID", any_args).
|
||||
and_return(%(hostonly-network="vagrantnet-vbox-1"))
|
||||
end
|
||||
|
||||
it "should not delete the network" do
|
||||
expect(subject).not_to receive(:execute).with("hostonlynet", "remove", any_args)
|
||||
subject.delete_unused_host_only_networks
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#enable_adapters" do
|
||||
let(:adapters) {
|
||||
[{hostonly: "hostonlynetwork", adapter: 1},
|
||||
{bridge: "eth0", adapter: 2}]
|
||||
}
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:execute).with("modifyvm", any_args)
|
||||
end
|
||||
|
||||
context "when hostonlynets are not enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should only call modifyvm once" do
|
||||
expect(subject).to receive(:execute).with("modifyvm", any_args).once
|
||||
subject.enable_adapters(adapters)
|
||||
end
|
||||
|
||||
it "should configure host only network using hostonlyadapter" do
|
||||
expect(subject).to receive(:execute) { |*args|
|
||||
expect(args.first).to eq("modifyvm")
|
||||
expect(args).to include("--hostonlyadapter1")
|
||||
true
|
||||
}
|
||||
subject.enable_adapters(adapters)
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets are enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
end
|
||||
|
||||
it "should call modifyvm twice" do
|
||||
expect(subject).to receive(:execute).with("modifyvm", any_args).twice
|
||||
subject.enable_adapters(adapters)
|
||||
end
|
||||
|
||||
it "should configure host only network using hostonlynet" do
|
||||
expect(subject).to receive(:execute).once
|
||||
expect(subject).to receive(:execute) { |*args|
|
||||
expect(args.first).to eq("modifyvm")
|
||||
expect(args).to include("--host-only-net1")
|
||||
true
|
||||
}
|
||||
subject.enable_adapters(adapters)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create_host_only_network" do
|
||||
let(:options) {
|
||||
{
|
||||
adapter_ip: "127.0.0.1",
|
||||
netmask: "255.255.255.0"
|
||||
}
|
||||
}
|
||||
|
||||
context "when hostonlynets are disabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should create using hostonlyif" do
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("hostonlyif", "create", any_args).
|
||||
and_return("Interface 'host_only' was successfully created")
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("hostonlyif", "ipconfig", "host_only", any_args)
|
||||
subject.create_host_only_network(options)
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets are enabled" do
|
||||
let(:prefix) { described_class.const_get(:HOSTONLY_NAME_PREFIX) }
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
allow(subject).to receive(:read_host_only_networks).and_return([])
|
||||
end
|
||||
|
||||
it "should create using hostonlynet" do
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("hostonlynet", "add", "--name", prefix + "1",
|
||||
"--netmask", options[:netmask], "--lower-ip",
|
||||
"127.0.0.0", "--upper-ip", "127.0.0.0", any_args)
|
||||
subject.create_host_only_network(options)
|
||||
end
|
||||
|
||||
context "when other host only networks exist" do
|
||||
before do
|
||||
expect(subject).
|
||||
to receive(:read_host_only_networks).
|
||||
and_return(["custom", prefix + "1", prefix + "20"].map { |n| {name: n} })
|
||||
end
|
||||
|
||||
it "should create network with incremented name" do
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("hostonlynet", "add", "--name", prefix + "21", any_args)
|
||||
subject.create_host_only_network(options)
|
||||
end
|
||||
end
|
||||
|
||||
context "when dhcp information is included" do
|
||||
let(:options) {
|
||||
{
|
||||
type: :dhcp,
|
||||
dhcp_lower: "127.0.0.1",
|
||||
dhcp_upper: "127.0.1.200",
|
||||
netmask: "255.255.240.0"
|
||||
}
|
||||
}
|
||||
|
||||
it "should set DHCP range" do
|
||||
expect(subject).
|
||||
to receive(:execute).
|
||||
with("hostonlynet", "add", "--name", anything, "--netmask", options[:netmask],
|
||||
"--lower-ip", options[:dhcp_lower], "--upper-ip", options[:dhcp_upper],
|
||||
any_args)
|
||||
subject.create_host_only_network(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#reconfig_host_only" do
|
||||
let(:interface) { {name: "iname", ipv6: "VALUE"} }
|
||||
|
||||
context "when hostonlynets are disabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should apply ipv6 update" do
|
||||
expect(subject).to receive(:execute).with("hostonlyif", "ipconfig", interface[:name],
|
||||
"--ipv6", interface[:ipv6], any_args)
|
||||
subject.reconfig_host_only(interface)
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets are enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
end
|
||||
|
||||
it "should do nothing" do
|
||||
expect(subject).not_to receive(:execute)
|
||||
subject.reconfig_host_only(interface)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#remove_dhcp_server" do
|
||||
let(:dhcp_name) { double(:dhcp_name) }
|
||||
|
||||
context "when hostonlynets are disabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should remove the dhcp server" do
|
||||
expect(subject).to receive(:execute).with("dhcpserver", "remove", "--netname",
|
||||
dhcp_name, any_args)
|
||||
subject.remove_dhcp_server(dhcp_name)
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets are enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
end
|
||||
|
||||
it "should do nothing" do
|
||||
expect(subject).not_to receive(:execute)
|
||||
subject.remove_dhcp_server(dhcp_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create_dhcp_server" do
|
||||
let(:network) { double("network") }
|
||||
let(:options) {
|
||||
{
|
||||
dhcp_ip: "127.0.0.1",
|
||||
netmask: "255.255.255.0",
|
||||
dhcp_lower: "127.0.0.2",
|
||||
dhcp_upper: "127.0.0.200"
|
||||
}
|
||||
}
|
||||
|
||||
context "when hostonlynets is diabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should create a dhcp server" do
|
||||
expect(subject).to receive(:execute).with("dhcpserver", "add", "--ifname", network,
|
||||
"--ip", options[:dhcp_ip], any_args)
|
||||
subject.create_dhcp_server(network, options)
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets is enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
end
|
||||
|
||||
it "should do nothing" do
|
||||
expect(subject).not_to receive(:execute)
|
||||
subject.create_dhcp_server(network, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#read_host_only_interfaces" do
|
||||
context "when hostonlynets is diabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
allow(subject).to receive(:execute).and_return("")
|
||||
end
|
||||
|
||||
it "should list hostonlyifs" do
|
||||
expect(subject).to receive(:execute).with("list", "hostonlyifs", any_args).and_return("")
|
||||
subject.read_host_only_interfaces
|
||||
end
|
||||
|
||||
it "should not call read_host_only_networks" do
|
||||
expect(subject).not_to receive(:read_host_only_networks)
|
||||
subject.read_host_only_interfaces
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets is enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
allow(subject).to receive(:execute).with("list", "hostonlynets", any_args).
|
||||
and_return(VBOX_HOSTONLYNETS)
|
||||
end
|
||||
|
||||
it "should call read_host_only_networks" do
|
||||
expect(subject).to receive(:read_host_only_networks).and_return([])
|
||||
subject.read_host_only_interfaces
|
||||
end
|
||||
|
||||
it "should return defined networks" do
|
||||
expect(subject.read_host_only_interfaces.size).to eq(2)
|
||||
end
|
||||
|
||||
it "should add compat information to network entries" do
|
||||
result = subject.read_host_only_interfaces
|
||||
expect(result.first[:netmask]).to eq(result.first[:networkmask])
|
||||
expect(result.first[:status]).to eq("Up")
|
||||
end
|
||||
|
||||
it "should assign the address as the first in the subnet" do
|
||||
result = subject.read_host_only_interfaces
|
||||
expect(result.first[:ip]).to eq(IPAddr.new(result.first[:lowerip]).succ.to_s)
|
||||
end
|
||||
|
||||
context "when dhcp range is set" do
|
||||
before do
|
||||
allow(subject).to receive(:execute).with("list", "hostonlynets", any_args).
|
||||
and_return(VBOX_RANGE_HOSTONLYNETS)
|
||||
end
|
||||
|
||||
it "should assign the address as the first in the dhcp range" do
|
||||
result = subject.read_host_only_interfaces
|
||||
expect(result.first[:ip]).to eq(result.first[:lowerip])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#read_host_only_networks" do
|
||||
before do
|
||||
allow(subject).to receive(:execute).with("list", "hostonlynets", any_args).
|
||||
and_return(VBOX_HOSTONLYNETS)
|
||||
end
|
||||
|
||||
it "should return defined networks" do
|
||||
expect(subject.read_host_only_networks.size).to eq(2)
|
||||
end
|
||||
|
||||
it "should return expected network information" do
|
||||
result = subject.read_host_only_networks
|
||||
expect(result.first[:name]).to eq("vagrantnet-vbox1")
|
||||
expect(result.first[:lowerip]).to eq("192.168.61.0")
|
||||
expect(result.first[:networkmask]).to eq("255.255.255.0")
|
||||
expect(result.last[:name]).to eq("vagrantnet-vbox2")
|
||||
expect(result.last[:lowerip]).to eq("192.168.22.0")
|
||||
expect(result.last[:networkmask]).to eq("255.255.255.0")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#read_network_interfaces" do
|
||||
before do
|
||||
allow(subject)
|
||||
.to receive(:execute).
|
||||
with("showvminfo", any_args).
|
||||
and_return(VBOX_GUEST_HOSTONLYVNETS_INFO)
|
||||
end
|
||||
|
||||
context "when hostonlynets is disabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(false)
|
||||
end
|
||||
|
||||
it "should return two interfaces" do
|
||||
valid_interfaces = subject.read_network_interfaces.find_all { |k, v|
|
||||
v[:type] != :none
|
||||
}
|
||||
expect(valid_interfaces.size).to eq(2)
|
||||
end
|
||||
|
||||
it "should include a nat type" do
|
||||
expect(subject.read_network_interfaces.detect { |_, v| v[:type] == :nat }).to be
|
||||
end
|
||||
|
||||
it "should include a hostonlynetwork type with no information" do
|
||||
expect(subject.read_network_interfaces[2]).to eq({type: :hostonlynetwork})
|
||||
end
|
||||
end
|
||||
|
||||
context "when hostonlynets is enabled" do
|
||||
before do
|
||||
allow(subject).to receive(:use_host_only_nets?).and_return(true)
|
||||
end
|
||||
|
||||
it "should return two interfaces" do
|
||||
valid_interfaces = subject.read_network_interfaces.find_all { |k, v|
|
||||
v[:type] != :none
|
||||
}
|
||||
expect(valid_interfaces.size).to eq(2)
|
||||
end
|
||||
|
||||
it "should include a nat type" do
|
||||
expect(subject.read_network_interfaces.detect { |_, v| v[:type] == :nat }).to be
|
||||
end
|
||||
|
||||
it "should include a hostonly type" do
|
||||
expect(subject.read_network_interfaces.detect { |_, v| v[:type] == :hostonly }).to be
|
||||
end
|
||||
|
||||
it "should not include a hostonlynetwork type" do
|
||||
expect(subject.read_network_interfaces.detect { |_, v|
|
||||
v[:type] == :hostonlynetwork
|
||||
}).to_not be
|
||||
end
|
||||
|
||||
it "should include the hostonly network name" do
|
||||
hostonly = subject.read_network_interfaces.values.detect { |v|
|
||||
v[:type] == :hostonly
|
||||
}
|
||||
expect(hostonly).to be
|
||||
expect(hostonly[:hostonly]).to eq("vagrantnet-vbox1")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
VBOX_VMCONFIG_FILE=%(<?xml version="1.0"?>
|
||||
<VirtualBox xmlns="http://www.virtualbox.org/" version="1.19-linux">
|
||||
<Machine uuid="{623842dc-0947-4143-aa4e-7d180c5eb348}" name="vagrant-test_default_1665781960041_56631" OSType="Ubuntu_64" snapshotFolder="Snapshots">
|
||||
<Hardware>
|
||||
<Network>
|
||||
<Adapter slot="0" enabled="true" MACAddress="080027BB1475" type="82540EM">
|
||||
<NAT localhost-reachable="true">
|
||||
<DNS use-proxy="true"/>
|
||||
<Forwarding name="ssh" proto="1" hostip="127.0.0.1" hostport="2222" guestport="22"/>
|
||||
<Forwarding name="tcp7700" proto="1" hostport="7700" guestport="80"/>
|
||||
</NAT>
|
||||
</Adapter>
|
||||
<Adapter slot="1" enabled="true" MACAddress="080027DD5ADF" type="82540EM">
|
||||
<DisabledModes>
|
||||
<InternalNetwork name="intnet"/>
|
||||
<NATNetwork name="NatNetwork"/>
|
||||
</DisabledModes>
|
||||
<HostOnlyInterface name="vboxnet0"/>
|
||||
</Adapter>
|
||||
</Network>
|
||||
</Hardware>
|
||||
</Machine>
|
||||
</VirtualBox>)
|
||||
|
||||
|
||||
VBOX_BRIDGEDIFS=%(Name: en1: Wi-Fi (AirPort)
|
||||
GUID: 00000000-0000-0000-0000-000000000001
|
||||
DHCP: Disabled
|
||||
IPAddress: 10.0.0.49
|
||||
NetworkMask: 255.255.255.0
|
||||
IPV6Address:
|
||||
IPV6NetworkMaskPrefixLength: 0
|
||||
HardwareAddress: xx:xx:xx:xx:xx:01
|
||||
MediumType: Ethernet
|
||||
Wireless: Yes
|
||||
Status: Up
|
||||
VBoxNetworkName: HostInterfaceNetworking-en1
|
||||
|
||||
Name: en0: Ethernet
|
||||
GUID: 00000000-0000-0000-0000-000000000002
|
||||
DHCP: Disabled
|
||||
IPAddress: 0.0.0.0
|
||||
NetworkMask: 0.0.0.0
|
||||
IPV6Address:
|
||||
IPV6NetworkMaskPrefixLength: 0
|
||||
HardwareAddress: xx:xx:xx:xx:xx:02
|
||||
MediumType: Ethernet
|
||||
Wireless: No
|
||||
Status: Up
|
||||
VBoxNetworkName: HostInterfaceNetworking-en0
|
||||
|
||||
Name: bridge100
|
||||
GUID: 00000000-0000-0000-0000-000000000003
|
||||
DHCP: Disabled
|
||||
IPAddress: 192.168.61.1
|
||||
NetworkMask: 255.255.255.0
|
||||
IPV6Address:
|
||||
IPV6NetworkMaskPrefixLength: 0
|
||||
HardwareAddress: xx:xx:xx:xx:xx:03
|
||||
MediumType: Ethernet
|
||||
Wireless: No
|
||||
Status: Up
|
||||
VBoxNetworkName: HostInterfaceNetworking-bridge100
|
||||
|
||||
Name: en2: Thunderbolt 1
|
||||
GUID: 00000000-0000-0000-0000-000000000004
|
||||
DHCP: Disabled
|
||||
IPAddress: 0.0.0.0
|
||||
NetworkMask: 0.0.0.0
|
||||
IPV6Address:
|
||||
IPV6NetworkMaskPrefixLength: 0
|
||||
HardwareAddress: xx:xx:xx:xx:xx:04
|
||||
MediumType: Ethernet
|
||||
Wireless: No
|
||||
Status: Up
|
||||
VBoxNetworkName: HostInterfaceNetworking-en2
|
||||
|
||||
Name: bridge101
|
||||
GUID: 00000000-0000-0000-0000-000000000005
|
||||
DHCP: Disabled
|
||||
IPAddress: 192.168.22.1
|
||||
NetworkMask: 255.255.255.0
|
||||
IPV6Address:
|
||||
IPV6NetworkMaskPrefixLength: 0
|
||||
HardwareAddress: xx:xx:xx:xx:xx:05
|
||||
MediumType: Ethernet
|
||||
Wireless: No
|
||||
Status: Up
|
||||
VBoxNetworkName: HostInterfaceNetworking-bridge101)
|
||||
|
||||
VBOX_HOSTONLYNETS=%(Name: vagrantnet-vbox1
|
||||
GUID: 10000000-0000-0000-0000-000000000000
|
||||
|
||||
State: Enabled
|
||||
NetworkMask: 255.255.255.0
|
||||
LowerIP: 192.168.61.0
|
||||
UpperIP: 192.168.61.0
|
||||
VBoxNetworkName: hostonly-vagrantnet-vbox1
|
||||
|
||||
Name: vagrantnet-vbox2
|
||||
GUID: 20000000-0000-0000-0000-000000000000
|
||||
|
||||
State: Enabled
|
||||
NetworkMask: 255.255.255.0
|
||||
LowerIP: 192.168.22.0
|
||||
UpperIP: 192.168.22.0
|
||||
VBoxNetworkName: hostonly-vagrantnet-vbox2)
|
||||
|
||||
VBOX_HOSTONLYNETS=%(Name: vagrantnet-vbox1
|
||||
GUID: 10000000-0000-0000-0000-000000000000
|
||||
|
||||
State: Enabled
|
||||
NetworkMask: 255.255.255.0
|
||||
LowerIP: 192.168.61.0
|
||||
UpperIP: 192.168.61.0
|
||||
VBoxNetworkName: hostonly-vagrantnet-vbox1
|
||||
|
||||
Name: vagrantnet-vbox2
|
||||
GUID: 20000000-0000-0000-0000-000000000000
|
||||
|
||||
State: Enabled
|
||||
NetworkMask: 255.255.255.0
|
||||
LowerIP: 192.168.22.0
|
||||
UpperIP: 192.168.22.0
|
||||
VBoxNetworkName: hostonly-vagrantnet-vbox2)
|
||||
|
||||
VBOX_RANGE_HOSTONLYNETS=%(Name: vagrantnet-vbox1
|
||||
GUID: 10000000-0000-0000-0000-000000000000
|
||||
|
||||
State: Enabled
|
||||
NetworkMask: 255.255.255.0
|
||||
LowerIP: 192.168.61.10
|
||||
UpperIP: 192.168.61.100
|
||||
VBoxNetworkName: hostonly-vagrantnet-vbox1
|
||||
|
||||
Name: vagrantnet-vbox2
|
||||
GUID: 20000000-0000-0000-0000-000000000000
|
||||
|
||||
State: Enabled
|
||||
NetworkMask: 255.255.255.0
|
||||
LowerIP: 192.168.22.0
|
||||
UpperIP: 192.168.22.0
|
||||
VBoxNetworkName: hostonly-vagrantnet-vbox2)
|
||||
|
||||
VBOX_GUEST_HOSTONLYVNETS_INFO=%(
|
||||
natnet1="nat"
|
||||
macaddress1="080027BB1475"
|
||||
cableconnected1="on"
|
||||
nic1="nat"
|
||||
nictype1="82540EM"
|
||||
nicspeed1="0"
|
||||
mtu="0"
|
||||
sockSnd="64"
|
||||
sockRcv="64"
|
||||
tcpWndSnd="64"
|
||||
tcpWndRcv="64"
|
||||
Forwarding(0)="ssh,tcp,127.0.0.1,2222,,22"
|
||||
hostonly-network2="vagrantnet-vbox1"
|
||||
macaddress2="080027FBC15B"
|
||||
cableconnected2="on"
|
||||
nic2="hostonlynetwork"
|
||||
nictype2="82540EM"
|
||||
nicspeed2="0"
|
||||
nic3="none"
|
||||
nic4="none"
|
||||
nic5="none"
|
||||
nic6="none"
|
||||
nic7="none"
|
||||
nic8="none"
|
||||
)
|
||||
@ -22,11 +22,11 @@ shared_examples "a version 5.x virtualbox driver" do |options|
|
||||
|
||||
it "enables SharedFoldersEnableSymlinksCreate if true" do
|
||||
expect(subprocess).to receive(:execute).
|
||||
with("VBoxManage", "setextradata", anything, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/folder", "1", {:notify=>[:stdout, :stderr]}).
|
||||
with("VBoxManage", "setextradata", anything, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/folder", "1", {:env => {:LANG => "C"}, :notify=>[:stdout, :stderr]}).
|
||||
and_return(subprocess_result(exit_code: 0))
|
||||
|
||||
expect(subprocess).to receive(:execute).
|
||||
with("VBoxManage", "sharedfolder", "add", anything, "--name", "folder", "--hostpath", "/Users/brian/vagrant-folder", {:notify=>[:stdout, :stderr]}).
|
||||
with("VBoxManage", "sharedfolder", "add", anything, "--name", "folder", "--hostpath", "/Users/brian/vagrant-folder", {:env => {:LANG => "C"}, :notify=>[:stdout, :stderr]}).
|
||||
and_return(subprocess_result(exit_code: 0))
|
||||
subject.share_folders(folders)
|
||||
|
||||
@ -34,11 +34,11 @@ shared_examples "a version 5.x virtualbox driver" do |options|
|
||||
|
||||
it "enables automount if option is true" do
|
||||
expect(subprocess).to receive(:execute).
|
||||
with("VBoxManage", "setextradata", anything, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/folder", "1", {:notify=>[:stdout, :stderr]}).
|
||||
with("VBoxManage", "setextradata", anything, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/folder", "1", {:env => {:LANG => "C"}, :notify=>[:stdout, :stderr]}).
|
||||
and_return(subprocess_result(exit_code: 0))
|
||||
|
||||
expect(subprocess).to receive(:execute).
|
||||
with("VBoxManage", "sharedfolder", "add", anything, "--name", "folder", "--hostpath", "/Users/brian/vagrant-folder", "--automount", {:notify=>[:stdout, :stderr]}).
|
||||
with("VBoxManage", "sharedfolder", "add", anything, "--name", "folder", "--hostpath", "/Users/brian/vagrant-folder", "--automount", {:env => {:LANG => "C"}, :notify=>[:stdout, :stderr]}).
|
||||
and_return(subprocess_result(exit_code: 0))
|
||||
subject.share_folders(folders_automount)
|
||||
|
||||
@ -46,7 +46,7 @@ shared_examples "a version 5.x virtualbox driver" do |options|
|
||||
|
||||
it "disables SharedFoldersEnableSymlinksCreate if false" do
|
||||
expect(subprocess).to receive(:execute).
|
||||
with("VBoxManage", "sharedfolder", "add", anything, "--name", "folder", "--hostpath", "/Users/brian/vagrant-folder", {:notify=>[:stdout, :stderr]}).
|
||||
with("VBoxManage", "sharedfolder", "add", anything, "--name", "folder", "--hostpath", "/Users/brian/vagrant-folder", {:env => {:LANG => "C"}, :notify=>[:stdout, :stderr]}).
|
||||
and_return(subprocess_result(exit_code: 0))
|
||||
subject.share_folders(folders_disabled)
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ describe VagrantPlugins::Ansible::Cap::Guest::Debian::AnsibleInstall do
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(communicator)
|
||||
allow(communicator).to receive(:execute).and_return(true)
|
||||
allow(communicator).to receive(:test).and_return(false)
|
||||
end
|
||||
|
||||
describe "#ansible_install" do
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
shared_examples_for "Ansible setup via pip" do
|
||||
|
||||
describe "when install_mode is :pip" do
|
||||
before { allow(communicator).to receive(:test) }
|
||||
|
||||
it "installs pip and calls Cap::Guest::Pip::pip_install" do
|
||||
expect(communicator).to receive(:sudo).at_least(1).times.ordered
|
||||
expect(VagrantPlugins::Ansible::Cap::Guest::Pip).to receive(:pip_install).once.ordered.
|
||||
@ -12,6 +14,8 @@ shared_examples_for "Ansible setup via pip" do
|
||||
end
|
||||
|
||||
describe "when install_mode is :pip_args_only" do
|
||||
before { allow(communicator).to receive(:test) }
|
||||
|
||||
it "installs pip and calls Cap::Guest::Pip::pip_install with 'pip_args' parameter" do
|
||||
pip_args = "-r /vagrant/requirements.txt"
|
||||
|
||||
@ -27,30 +31,57 @@ end
|
||||
shared_examples_for "Ansible setup via pip on Debian-based systems" do
|
||||
|
||||
describe "installs required Debian packages and..." do
|
||||
before { allow(communicator).to receive(:test) }
|
||||
pip_install_cmd = "foo"
|
||||
|
||||
it "calls Cap::Guest::Pip::get_pip with 'pip' install_mode" do
|
||||
expect(communicator).to receive(:sudo).once.ordered.
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("apt-get update -y -qq")
|
||||
expect(communicator).to receive(:sudo).once.ordered.
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --option \"Dpkg::Options::=--force-confold\" build-essential curl git libssl-dev libffi-dev python-dev")
|
||||
expect(communicator).to receive(:sudo).once.ordered.
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("pip install --upgrade ansible")
|
||||
|
||||
subject.ansible_install(machine, :pip, "", "", pip_install_cmd)
|
||||
end
|
||||
|
||||
it "calls Cap::Guest::Pip::get_pip with 'pip_args_only' install_mode" do
|
||||
expect(communicator).to receive(:sudo).once.ordered.
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("apt-get update -y -qq")
|
||||
expect(communicator).to receive(:sudo).once.ordered.
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --option \"Dpkg::Options::=--force-confold\" build-essential curl git libssl-dev libffi-dev python-dev")
|
||||
expect(communicator).to receive(:sudo).once.ordered.
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("pip install")
|
||||
|
||||
subject.ansible_install(machine, :pip_args_only, "", "", pip_install_cmd)
|
||||
end
|
||||
|
||||
context "when python-dev-is-python3 package is available" do
|
||||
before { allow(communicator).to receive(:test).with("apt-cache show python-dev-is-python3").and_return(true) }
|
||||
|
||||
it "calls Cap::Guest::Pip::get_pip with 'pip' install_mode" do
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("apt-get update -y -qq")
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --option \"Dpkg::Options::=--force-confold\" build-essential curl git libssl-dev libffi-dev python-dev-is-python3")
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("pip install --upgrade ansible")
|
||||
|
||||
subject.ansible_install(machine, :pip, "", "", pip_install_cmd)
|
||||
end
|
||||
|
||||
it "calls Cap::Guest::Pip::get_pip with 'pip_args_only' install_mode" do
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("apt-get update -y -qq")
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --option \"Dpkg::Options::=--force-confold\" build-essential curl git libssl-dev libffi-dev python-dev-is-python3")
|
||||
expect(communicator).to receive(:sudo).
|
||||
with("pip install")
|
||||
|
||||
subject.ansible_install(machine, :pip_args_only, "", "", pip_install_cmd)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it_behaves_like "Ansible setup via pip"
|
||||
|
||||
@ -91,7 +91,7 @@ VF
|
||||
expect(args[1]).to eq("--connection=ssh")
|
||||
expect(args[2]).to eq("--timeout=30")
|
||||
|
||||
inventory_count = args.count { |x| x =~ /^--inventory-file=.+$/ }
|
||||
inventory_count = args.count { |x| x.match(/^--inventory-file=.+$/) if x.is_a?(String) }
|
||||
expect(inventory_count).to be > 0
|
||||
|
||||
expect(args[args.length-2]).to eq("playbook.yml")
|
||||
@ -100,9 +100,9 @@ VF
|
||||
|
||||
it "sets --limit argument" do
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
|
||||
all_limits = args.select { |x| x =~ /^(--limit=|-l)/ }
|
||||
all_limits = args.select { |x| x.match(/^(--limit=|-l)/) if x.is_a?(String) }
|
||||
if config.raw_arguments
|
||||
raw_limits = config.raw_arguments.select { |x| x =~ /^(--limit=|-l)/ }
|
||||
raw_limits = config.raw_arguments.select { |x| x.match(/^(--limit=|-l)/) if x.is_a?(String) }
|
||||
expect(all_limits.length - raw_limits.length).to eq(1)
|
||||
expect(all_limits.last).to eq(raw_limits.last)
|
||||
else
|
||||
@ -181,7 +181,7 @@ VF
|
||||
it "generates an inventory with all active machines" do
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
|
||||
expect(config.inventory_path).to be_nil
|
||||
expect(File.exists?(generated_inventory_file)).to be(true)
|
||||
expect(File.exist?(generated_inventory_file)).to be(true)
|
||||
inventory_content = File.read(generated_inventory_file)
|
||||
_ssh = config.compatibility_mode == VagrantPlugins::Ansible::COMPATIBILITY_MODE_V2_0 ? "" : "_ssh"
|
||||
if with_user
|
||||
@ -697,7 +697,7 @@ VF
|
||||
it "generates an inventory with winrm connection settings" do
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
|
||||
expect(config.inventory_path).to be_nil
|
||||
expect(File.exists?(generated_inventory_file)).to be(true)
|
||||
expect(File.exist?(generated_inventory_file)).to be(true)
|
||||
inventory_content = File.read(generated_inventory_file)
|
||||
|
||||
expect(inventory_content).to include("machine1 ansible_connection=winrm ansible_ssh_host=127.0.0.1 ansible_ssh_port=55986 ansible_ssh_user='winner' ansible_ssh_pass='winword'\n")
|
||||
@ -731,7 +731,7 @@ VF
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
|
||||
expect(args).to include("--inventory-file=#{existing_file}")
|
||||
expect(args).not_to include("--inventory-file=#{generated_inventory_file}")
|
||||
expect(File.exists?(generated_inventory_file)).to be(false)
|
||||
expect(File.exist?(generated_inventory_file)).to be(false)
|
||||
}.and_return(default_execute_result)
|
||||
end
|
||||
|
||||
|
||||
@ -343,6 +343,19 @@ describe VagrantPlugins::SyncedFolderRSync::RsyncHelper do
|
||||
allow(guest).to receive(:capability?){ false }
|
||||
end
|
||||
|
||||
context "with extra args defined" do
|
||||
before { ssh_info[:extra_args] = ["-o", "Compression=yes"] }
|
||||
|
||||
it "appends the extra arguments from ssh_info" do
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute) { |*args|
|
||||
cmd = args.detect { |a| a.is_a?(String) && a.start_with?("ssh") }
|
||||
expect(cmd).to be
|
||||
expect(cmd).to include("-o Compression=yes")
|
||||
}.and_return(result)
|
||||
subject.rsync_single(machine, ssh_info, opts)
|
||||
end
|
||||
end
|
||||
|
||||
context "with an IPv6 address" do
|
||||
before { ssh_info[:host] = "fe00::0" }
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ require File.expand_path("../../base", __FILE__)
|
||||
require "pathname"
|
||||
require 'tempfile'
|
||||
|
||||
describe Vagrant::BoxCollection, :skip_windows do
|
||||
describe Vagrant::BoxCollection, :skip_windows, :bsdtar do
|
||||
include_context "unit"
|
||||
|
||||
let(:box_class) { Vagrant::Box }
|
||||
|
||||
@ -12,7 +12,7 @@ describe Vagrant::Util::InstallZSHShellConfig do
|
||||
|
||||
describe "#shell_installed" do
|
||||
it "should return path to config file if exists" do
|
||||
allow(File).to receive(:exists?).with(target_file).and_return(true)
|
||||
allow(File).to receive(:exist?).with(target_file).and_return(true)
|
||||
expect(subject.shell_installed(home)).to eq(target_file)
|
||||
end
|
||||
|
||||
@ -36,7 +36,7 @@ describe Vagrant::Util::InstallZSHShellConfig do
|
||||
|
||||
describe "#install" do
|
||||
it "installs autocomplete" do
|
||||
allow(File).to receive(:exists?).with(target_file).and_return(true)
|
||||
allow(File).to receive(:exist?).with(target_file).and_return(true)
|
||||
allow(File).to receive(:foreach).with(target_file).and_yield("nothing")
|
||||
expect(File).to receive(:open).with(target_file, "a")
|
||||
subject.install(home)
|
||||
@ -67,4 +67,4 @@ describe Vagrant::Util::InstallCLIAutocomplete do
|
||||
expect{ subject.install(["oops"]) }.to raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
||||
s.summary = "Build and distribute virtualized development environments."
|
||||
s.description = "Vagrant is a tool for building and distributing virtualized development environments."
|
||||
|
||||
s.required_ruby_version = ">= 2.6", "< 3.2"
|
||||
s.required_ruby_version = ">= 3.0", "< 3.3"
|
||||
s.required_rubygems_version = ">= 1.3.6"
|
||||
|
||||
s.add_dependency "bcrypt_pbkdf", "~> 1.1"
|
||||
@ -22,23 +22,23 @@ Gem::Specification.new do |s|
|
||||
s.add_dependency 'googleapis-common-protos-types', '~> 1.3'
|
||||
s.add_dependency "grpc"
|
||||
s.add_dependency "hashicorp-checkpoint", "~> 0.1.5"
|
||||
s.add_dependency "i18n", "~> 1.8"
|
||||
s.add_dependency "listen", "~> 3.6"
|
||||
s.add_dependency "i18n", "~> 1.12"
|
||||
s.add_dependency "listen", "~> 3.7"
|
||||
s.add_dependency "log4r", "~> 1.1.9", "< 1.1.11"
|
||||
s.add_dependency "mime-types", "~> 3.3"
|
||||
s.add_dependency "net-ftp", "~> 0.1"
|
||||
s.add_dependency "net-ssh", ">= 6.1.0", "< 6.2"
|
||||
s.add_dependency "net-sftp", "~> 3.0"
|
||||
s.add_dependency "net-scp", "~> 3.0.0"
|
||||
s.add_dependency "net-ftp", "~> 0.2"
|
||||
s.add_dependency "net-ssh", "~> 7.0"
|
||||
s.add_dependency "net-sftp", "~> 4.0"
|
||||
s.add_dependency "net-scp", "~> 4.0"
|
||||
s.add_dependency "rb-kqueue", "~> 0.2.0"
|
||||
s.add_dependency "rexml", "~> 3.2"
|
||||
s.add_dependency "rgl", "~> 0.5.7"
|
||||
s.add_dependency "rubyzip", "~> 2.0"
|
||||
s.add_dependency "rgl", "~> 0.5.10"
|
||||
s.add_dependency "rubyzip", "~> 2.3.2"
|
||||
s.add_dependency "vagrant_cloud", "~> 3.0.5"
|
||||
s.add_dependency "wdm", "~> 0.1.0"
|
||||
s.add_dependency "winrm", ">= 2.3.4", "< 3.0"
|
||||
s.add_dependency "winrm-elevated", ">= 1.2.1", "< 2.0"
|
||||
s.add_dependency "winrm-fs", ">= 1.3.4", "< 2.0"
|
||||
s.add_dependency "wdm", "~> 0.1.1"
|
||||
s.add_dependency "winrm", ">= 2.3.6", "< 3.0"
|
||||
s.add_dependency "winrm-elevated", ">= 1.2.3", "< 2.0"
|
||||
s.add_dependency "winrm-fs", ">= 1.3.5", "< 2.0"
|
||||
|
||||
# Needed for go generate to use grpc_tools_ruby_protoc
|
||||
s.add_development_dependency "grpc-tools", "~> 1.41"
|
||||
@ -49,7 +49,7 @@ Gem::Specification.new do |s|
|
||||
# Constraint rake to properly handle deprecated method usage
|
||||
# from within rspec
|
||||
s.add_development_dependency "rake", "~> 13.0"
|
||||
s.add_development_dependency "rspec", "~> 3.11.0"
|
||||
s.add_development_dependency "rspec", "~> 3.11"
|
||||
s.add_development_dependency "rspec-its", "~> 1.3.0"
|
||||
s.add_development_dependency "fake_ftp", "~> 0.3.0"
|
||||
s.add_development_dependency "webrick", "~> 1.7.0"
|
||||
|
||||
@ -1 +1 @@
|
||||
2.3.2.dev
|
||||
2.3.5.dev
|
||||
|
||||
@ -1,6 +1,21 @@
|
||||
######################################################
|
||||
# NOTE: This file is managed by the Digital Team's #
|
||||
# Terraform configuration @ hashicorp/mktg-terraform #
|
||||
######################################################
|
||||
|
||||
.DEFAULT_GOAL := website
|
||||
|
||||
# Set the preview mode for the website shell to "developer" or "io"
|
||||
PREVIEW_MODE ?= developer
|
||||
REPO ?= vagrant
|
||||
|
||||
# Enable setting alternate docker tool, e.g. 'make DOCKER_CMD=podman'
|
||||
DOCKER_CMD ?= docker
|
||||
|
||||
CURRENT_GIT_BRANCH=$$(git rev-parse --abbrev-ref HEAD)
|
||||
LOCAL_CONTENT_DIR=
|
||||
PWD=$$(pwd)
|
||||
|
||||
DOCKER_IMAGE="hashicorp/dev-portal"
|
||||
DOCKER_IMAGE_LOCAL="dev-portal-local"
|
||||
DOCKER_RUN_FLAGS=-it \
|
||||
@ -13,22 +28,31 @@ DOCKER_RUN_FLAGS=-it \
|
||||
--volume "$(PWD)/redirects.js:/app/redirects.js" \
|
||||
--volume "next-dir:/app/website-preview/.next" \
|
||||
--volume "$(PWD)/.env:/app/.env" \
|
||||
-e "REPO=vagrant"
|
||||
-e "REPO=$(REPO)" \
|
||||
-e "PREVIEW_FROM_REPO=$(REPO)" \
|
||||
-e "IS_CONTENT_PREVIEW=true" \
|
||||
-e "LOCAL_CONTENT_DIR=$(LOCAL_CONTENT_DIR)" \
|
||||
-e "CURRENT_GIT_BRANCH=$(CURRENT_GIT_BRANCH)" \
|
||||
-e "PREVIEW_MODE=$(PREVIEW_MODE)"
|
||||
|
||||
# Default: run this if working on the website locally to run in watch mode.
|
||||
.PHONY: website
|
||||
website:
|
||||
@echo "==> Downloading latest Docker image..."
|
||||
@docker pull $(DOCKER_IMAGE)
|
||||
@$(DOCKER_CMD) pull $(DOCKER_IMAGE)
|
||||
@echo "==> Starting website..."
|
||||
@docker run $(DOCKER_RUN_FLAGS) $(DOCKER_IMAGE)
|
||||
@$(DOCKER_CMD) run $(DOCKER_RUN_FLAGS) $(DOCKER_IMAGE)
|
||||
|
||||
# Use this if you have run `website/build-local` to use the locally built image.
|
||||
.PHONY: website/local
|
||||
website/local:
|
||||
@echo "==> Starting website from local image..."
|
||||
@docker run $(DOCKER_RUN_FLAGS) $(DOCKER_IMAGE_LOCAL)
|
||||
@$(DOCKER_CMD) run $(DOCKER_RUN_FLAGS) $(DOCKER_IMAGE_LOCAL)
|
||||
|
||||
# Run this to generate a new local Docker image.
|
||||
.PHONY: website/build-local
|
||||
website/build-local:
|
||||
@echo "==> Building local Docker image"
|
||||
@docker build https://github.com/hashicorp/dev-portal.git\#main \
|
||||
@$(DOCKER_CMD) build https://github.com/hashicorp/dev-portal.git\#main \
|
||||
-t $(DOCKER_IMAGE_LOCAL)
|
||||
|
||||
|
||||
@ -77,7 +77,6 @@ This file can be standard Markdown and also supports [YAML frontmatter](https://
|
||||
title: 'My Title'
|
||||
description: "A thorough, yet succinct description of the page's contents"
|
||||
---
|
||||
|
||||
```
|
||||
|
||||
The significant keys in the YAML frontmatter are:
|
||||
@ -95,12 +94,12 @@ There is currently a small bug with new page creation - if you create a new page
|
||||
|
||||
There are several custom markdown plugins that are available by default that enhance [standard markdown](https://commonmark.org/) to fit our use cases. This set of plugins introduces a couple instances of custom syntax, and a couple specific pitfalls that are not present by default with markdown, detailed below:
|
||||
|
||||
- If you see the symbols `~>`, `->`, `=>`, or `!>`, these represent [custom alerts](https://github.com/hashicorp/remark-plugins/tree/master/plugins/paragraph-custom-alerts#paragraph-custom-alerts). These render as colored boxes to draw the user's attention to some type of aside.
|
||||
- > **Warning**: We are deprecating the current [paragraph alerts](https://github.com/hashicorp/remark-plugins/tree/master/plugins/paragraph-custom-alerts#paragraph-custom-alerts), in favor of the newer [MDX Inline Alert](#inline-alerts) components. The legacy paragraph alerts are represented by the symbols `~>`, `->`, `=>`, or `!>`.
|
||||
- If you see `@include '/some/path.mdx'`, this is a [markdown include](https://github.com/hashicorp/remark-plugins/tree/master/plugins/include-markdown#include-markdown-plugin). It's worth noting as well that all includes resolve from `website/content/partials` by default, and that changes to partials will not live-reload the website.
|
||||
- If you see `# Headline ((#slug))`, this is an example of an [anchor link alias](https://github.com/hashicorp/remark-plugins/tree/je.anchor-link-adjustments/plugins/anchor-links#anchor-link-aliases). It adds an extra permalink to a headline for compatibility and is removed from the output.
|
||||
- Due to [automatically generated permalinks](https://github.com/hashicorp/remark-plugins/tree/je.anchor-link-adjustments/plugins/anchor-links#anchor-links), any text changes to _headlines_ or _list items that begin with inline code_ can and will break existing permalinks. Be very cautious when changing either of these two text items.
|
||||
|
||||
Headlines are fairly self-explanitory, but here's an example of how list items that begin with inline code look.
|
||||
Headlines are fairly self-explanatory, but here's an example of how to list items that begin with inline code look.
|
||||
|
||||
```markdown
|
||||
- this is a normal list item
|
||||
@ -120,13 +119,51 @@ There are several custom markdown plugins that are available by default that enh
|
||||
|
||||
A number of custom [mdx components](https://mdxjs.com/) are available for use within any `.mdx` file. Each one is documented below:
|
||||
|
||||
#### Inline Alerts
|
||||
|
||||
There are custom MDX components available to author alert data. [See the full documentation here](https://developer.hashicorp.com/swingset/components/mdxinlinealert). They render as colored boxes to draw the user's attention to some type of aside.
|
||||
|
||||
```mdx
|
||||
## Alert types
|
||||
|
||||
### Tip
|
||||
|
||||
<Tip>
|
||||
To provide general information to the user regarding the current context or
|
||||
relevant actions.
|
||||
</Tip>
|
||||
|
||||
### Highlight
|
||||
|
||||
<Highlight>
|
||||
To provide general or promotional information to the user prominently.
|
||||
</Highlight>
|
||||
|
||||
### Note
|
||||
|
||||
<Note>
|
||||
To help users avoid an issue. Provide guidance and actions if possible.
|
||||
</Note>
|
||||
|
||||
### Warning
|
||||
|
||||
<Warning>
|
||||
To indicate critical issues that need immediate action or help users
|
||||
understand something critical.
|
||||
</Warning>
|
||||
|
||||
## Title override prop
|
||||
|
||||
<Note title="Hashiconf 2027">To provide general information.</Note>
|
||||
```
|
||||
|
||||
#### Tabs
|
||||
|
||||
The `Tabs` component creates tabbed content of any type, but is often used for code examples given in different languages. Here's an example of how it looks from the Vagrant documentation website:
|
||||
|
||||

|
||||
|
||||
> Please refer to the [Swingset](https://react-components.vercel.app/?component=Tabs) documention for the latest examples and API reference.
|
||||
> Please refer to the [Swingset](https://react-components.vercel.app/?component=Tabs) documentation for the latest examples and API reference.
|
||||
|
||||
It can be used as such within a markdown file:
|
||||
|
||||
@ -150,7 +187,7 @@ $ curl ...
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Contined normal markdown content
|
||||
Continued normal markdown content
|
||||
````
|
||||
|
||||
The intentionally skipped line is a limitation of the mdx parser which is being actively worked on. All tabs must have a heading, and there is no limit to the number of tabs, though it is recommended to go for a maximum of three or four.
|
||||
@ -404,7 +441,7 @@ This configuration would display something like the following text on the websit
|
||||
A {{ release candidate }} for <Product> {{ v1.0.0 }} is available! The release can be <a href='https://releases.hashicorp.com/<product>/{{ 1.0.0-rc1 }}'>downloaded here</a>.
|
||||
```
|
||||
|
||||
You may customize the parameters in any way you'd like. To remove a prerelease from the website, simply delete the `prerelease` paremeter from the above component.
|
||||
You may customize the parameters in any way you'd like. To remove a prerelease from the website, simply delete the `prerelease` parameter from the above component.
|
||||
|
||||
<!-- END: releases -->
|
||||
|
||||
@ -448,7 +485,7 @@ One more example - let's say that content is being moved to an external website.
|
||||
}
|
||||
```
|
||||
|
||||
If we no longer want the link to be in the side nav, we can simply remove it. If we do still want the link in the side nav, but pointing to an external destnation, we need to slightly change the structure as such:
|
||||
If we no longer want the link to be in the side nav, we can simply remove it. If we do still want the link in the side nav, but pointing to an external destination, we need to slightly change the structure as such:
|
||||
|
||||
```js
|
||||
{
|
||||
@ -472,9 +509,9 @@ It's also worth noting that it is possible to do glob-based redirects, for examp
|
||||
|
||||
We support the following browsers targeting roughly the versions specified.
|
||||
|
||||
|  |  |  |  |  |
|
||||
| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| **Latest** | **Latest** | **Latest** | **Latest** | **11+** |
|
||||
|  |  |  |  |  |
|
||||
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| **Latest** | **Latest** | **Latest** | **Latest** | **Latest** |
|
||||
|
||||
<!-- END: browser-support -->
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ following:
|
||||
- SSH user so Vagrant can connect
|
||||
- Perhaps Chef, Puppet, etc. but not strictly required.
|
||||
|
||||
In addition to this, each [provider](/docs/providers/) may require
|
||||
In addition to this, each [provider](/vagrant/docs/providers/) may require
|
||||
additional software. For example, if you are making a base box for VirtualBox,
|
||||
you will want to include the VirtualBox guest additions so that shared folders
|
||||
work properly. But if you are making an AWS base box, this is not required.
|
||||
@ -58,16 +58,16 @@ boxes.
|
||||
|
||||
Provider-specific guides for creating base boxes are linked below:
|
||||
|
||||
- [Docker Base Boxes](/docs/providers/docker/boxes)
|
||||
- [Hyper-V Base Boxes](/docs/providers/hyperv/boxes)
|
||||
- [VMware Base Boxes](/docs/providers/vmware/boxes)
|
||||
- [VirtualBox Base Boxes](/docs/providers/virtualbox/boxes)
|
||||
- [Docker Base Boxes](/vagrant/docs/providers/docker/boxes)
|
||||
- [Hyper-V Base Boxes](/vagrant/docs/providers/hyperv/boxes)
|
||||
- [VMware Base Boxes](/vagrant/docs/providers/vmware/boxes)
|
||||
- [VirtualBox Base Boxes](/vagrant/docs/providers/virtualbox/boxes)
|
||||
|
||||
### Packer and Vagrant Cloud
|
||||
|
||||
We strongly recommend using [Packer](https://www.packer.io) to create reproducible
|
||||
We strongly recommend using [Packer](https://www.packer.io/) to create reproducible
|
||||
builds for your base boxes, as well as automating the builds. Read more about
|
||||
[automating Vagrant box creation with Packer](https://www.packer.io/guides/packer-on-cicd/build-image-in-cicd)
|
||||
[automating Vagrant box creation with Packer](/packer/guides/packer-on-cicd/build-image-in-cicd)
|
||||
in the Packer documentation.
|
||||
|
||||
### Disk Space
|
||||
@ -282,7 +282,7 @@ provider-specific guides are linked to towards the top of this page.
|
||||
You can distribute the box file however you would like. However, if you want
|
||||
to support versioning, putting multiple providers at a single URL, pushing
|
||||
updates, analytics, and more, we recommend you add the box to
|
||||
[HashiCorp's Vagrant Cloud](/vagrant-cloud).
|
||||
[HashiCorp's Vagrant Cloud](/vagrant/vagrant-cloud).
|
||||
|
||||
You can upload both public and private boxes to this service.
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ description: |-
|
||||
|
||||
In the past, boxes were just [tar files](<https://en.wikipedia.org/wiki/Tar_(computing)>)
|
||||
of VirtualBox exports. With Vagrant supporting multiple
|
||||
[providers](/docs/providers/) and [versioning](/docs/boxes/versioning)
|
||||
[providers](/vagrant/docs/providers/) and [versioning](/vagrant/docs/boxes/versioning)
|
||||
now, box files are slightly more complicated.
|
||||
|
||||
Box files made for Vagrant 1.0.x (the VirtualBox export `tar` files) continue
|
||||
@ -26,7 +26,7 @@ Today, there are three different components:
|
||||
box file and so on.
|
||||
|
||||
- Box Catalog Metadata - This is a JSON document (typically exchanged
|
||||
during interactions with [HashiCorp's Vagrant Cloud](/vagrant-cloud))
|
||||
during interactions with [HashiCorp's Vagrant Cloud](/vagrant/vagrant-cloud))
|
||||
that specifies the name of the box, a description, available
|
||||
versions, available providers, and URLs to the actual box files
|
||||
(next component) for each provider and version. If this catalog
|
||||
@ -35,7 +35,7 @@ Today, there are three different components:
|
||||
|
||||
- Box Information - This is a JSON document that can provide additional
|
||||
information about the box that displays when a user runs
|
||||
`vagrant box list -i`. More information is provided [here](/docs/boxes/info).
|
||||
`vagrant box list -i`. More information is provided [here](/vagrant/docs/boxes/info).
|
||||
|
||||
The first two components are covered in more detail below.
|
||||
|
||||
@ -47,7 +47,7 @@ are supported for legacy reasons in Vagrant.
|
||||
|
||||
Box files are compressed using `tar`, `tar.gz`, or `zip`. The contents of the
|
||||
archive can be anything, and is specific to each
|
||||
[provider](/docs/providers/). Vagrant core itself only unpacks
|
||||
[provider](/vagrant/docs/providers/). Vagrant core itself only unpacks
|
||||
the boxes for use later.
|
||||
|
||||
Within the archive, Vagrant does expect a single file:
|
||||
@ -80,11 +80,11 @@ file.
|
||||
## Box Metadata
|
||||
|
||||
The metadata is an optional component for a box (but highly recommended)
|
||||
that enables [versioning](/docs/boxes/versioning), updating, multiple
|
||||
that enables [versioning](/vagrant/docs/boxes/versioning), updating, multiple
|
||||
providers from a single file, and more.
|
||||
|
||||
-> **You do not need to manually make the metadata.** If you
|
||||
have an account with [HashiCorp's Vagrant Cloud](/vagrant-cloud), you
|
||||
have an account with [HashiCorp's Vagrant Cloud](/vagrant/vagrant-cloud), you
|
||||
can create boxes there, and HashiCorp's Vagrant Cloud automatically creates
|
||||
the metadata for you. The format is still documented here.
|
||||
|
||||
|
||||
@ -1,71 +1,62 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: Boxes
|
||||
page_title: Vagrant Boxes
|
||||
description: |-
|
||||
Boxes are the package format for Vagrant environments. A box can be used by
|
||||
anyone on any platform that Vagrant supports to bring up an identical
|
||||
working environment.
|
||||
---
|
||||
|
||||
# Boxes
|
||||
# Vagrant boxes
|
||||
|
||||
Boxes are the package format for Vagrant environments. A box can be used by
|
||||
anyone on any platform that Vagrant supports to bring up an identical
|
||||
working environment.
|
||||
Boxes are the package format for Vagrant environments. You specify a box environment and operating configurations in your [Vagrantfile](/vagrant/docs/vagrantfile). You can use a box on any [supported platform](/vagrant/downloads) to bring up identical working environments. To enable teams to use and manage the same boxes, [versions are supported](/vagrant/docs/boxes/versioning).
|
||||
|
||||
The `vagrant box` utility provides all the functionality for managing
|
||||
boxes. You can read the documentation on the [vagrant box](/docs/cli/box)
|
||||
~> **Note**: Boxes require a provider, a virtualization product, to operate. Before you can use a box,
|
||||
ensure that you have properly installed a supported [provider](/vagrant/docs/providers).
|
||||
|
||||
The quickest way to get started is to select a pre-defined box environment from the
|
||||
[publicly available catalog on Vagrant Cloud](https://vagrantcloud.com/boxes/search).
|
||||
You can also add and share your own customized boxes on Vagrant Cloud.
|
||||
|
||||
The `vagrant box` CLI utility provides all the functionality for box management. You can read the documentation on the [vagrant box](/vagrant/docs/cli/box)
|
||||
command for more information.
|
||||
|
||||
The easiest way to use a box is to add a box from the
|
||||
[publicly available catalog of Vagrant boxes](https://vagrantcloud.com/boxes/search).
|
||||
You can also add and share your own customized boxes on this website.
|
||||
## Discover boxes
|
||||
|
||||
Boxes also support versioning so that members of your team using Vagrant
|
||||
can update the underlying box easily, and the people who create boxes
|
||||
can push fixes and communicate these fixes efficiently.
|
||||
|
||||
You can learn all about boxes by reading this page as well as the
|
||||
sub-pages in the navigation to the left.
|
||||
|
||||
## Discovering Boxes
|
||||
|
||||
The easiest way to find boxes is to look on the
|
||||
To find boxes, explore the
|
||||
[public Vagrant box catalog](https://vagrantcloud.com/boxes/search)
|
||||
for a box matching your use case. The catalog contains most major operating
|
||||
systems as bases, as well as specialized boxes to get you up and running
|
||||
quickly with LAMP stacks, Ruby, Python, etc.
|
||||
for a box that matches your use case. The catalog contains most major operating
|
||||
systems as bases, as well as specialized boxes to get you started with common
|
||||
configurations such as LAMP stacks, Ruby, and Python.
|
||||
|
||||
The boxes on the public catalog work with many different
|
||||
[providers](/docs/providers/). Whether you are using Vagrant with
|
||||
VirtualBox, VMware, AWS, etc. you should be able to find a box you need.
|
||||
[providers](/vagrant/docs/providers/). The list of supported providers is located in the box descriptions.
|
||||
|
||||
Adding a box from the catalog is very easy. Each box shows you instructions
|
||||
with how to add it, but they all follow the same format:
|
||||
### Add a box
|
||||
|
||||
```shell-session
|
||||
$ vagrant box add USER/BOX
|
||||
```
|
||||
You can add a box from the public catalog at any time. The box's description includes instructions
|
||||
on how to add it to an existing Vagrantfile or initiate it as a new environment on the command-line.
|
||||
|
||||
For example: `vagrant box add hashicorp/bionic64`. You can also quickly
|
||||
initialize a Vagrant environment with `vagrant init hashicorp/bionic64`.
|
||||
|
||||
~> **Namespaces do not guarantee canonical boxes!** A common misconception is
|
||||
that a namespace like "ubuntu" represents the canonical space for Ubuntu boxes.
|
||||
A common misconception is
|
||||
that a namespace like "ubuntu" represents the official space for Ubuntu boxes.
|
||||
This is untrue. Namespaces on Vagrant Cloud behave very similarly to namespaces on
|
||||
GitHub, for example. Just as GitHub's support team is unable to assist with
|
||||
GitHub. Just as GitHub's support team is unable to assist with
|
||||
issues in someone's repository, HashiCorp's support team is unable to assist
|
||||
with third-party published boxes.
|
||||
|
||||
## Official Boxes
|
||||
## Official boxes
|
||||
|
||||
HashiCorp (the makers of Vagrant) publish a basic Ubuntu 18.04 64-bit box that is available for minimal use cases. It is highly optimized, small in size, and includes support for VirtualBox, Hyper-V, and VMware. You can use it like this:
|
||||
There are only two officially-recommended box sets.
|
||||
|
||||
HashiCorp publishes a basic Ubuntu 18.04 64-bit box that is available for minimal use cases. It is highly optimized, small in size, and includes support for VirtualBox, Hyper-V, and VMware.
|
||||
|
||||
To get started, use the `init` command to initialize your environment.
|
||||
|
||||
```shell-session
|
||||
$ vagrant init hashicorp/bionic64
|
||||
```
|
||||
|
||||
or you can update your `Vagrantfile` as follows:
|
||||
If you have an existing Vagrantfile, add `hashicorp/bionic64`.
|
||||
|
||||
```ruby
|
||||
Vagrant.configure("2") do |config|
|
||||
@ -73,10 +64,15 @@ Vagrant.configure("2") do |config|
|
||||
end
|
||||
```
|
||||
|
||||
For other users, we recommend the [Bento boxes](https://vagrantcloud.com/bento). The Bento boxes are [open source](https://github.com/chef/bento) and built for a number of providers including VMware, VirtualBox, and Parallels. There are a variety of operating systems and versions available.
|
||||
|
||||
These are the only two officially-recommended box sets.
|
||||
For other base operating system environments, we recommend the [Bento boxes](https://vagrantcloud.com/bento). The Bento boxes are [open source](https://github.com/chef/bento) and built for a number of providers including VMware, VirtualBox, and Parallels. There are a variety of operating systems and versions available.
|
||||
|
||||
Special thanks to the Bento project for providing a solid base template for the `hashicorp/bionic64` box.
|
||||
|
||||
~> **It is often a point of confusion**, but Canonical (the company that makes the Ubuntu operating system) publishes boxes under the "ubuntu" namespace on Vagrant Cloud. These boxes only support VirtualBox and do not provide an ideal experience for most users. If you encounter issues with these boxes, please try the Bento boxes instead.
|
||||
It is often a point of confusion but Canonical, the company that makes the Ubuntu operating system, publishes boxes under the "ubuntu" namespace on Vagrant Cloud. These boxes only support VirtualBox.
|
||||
|
||||
## Create a box
|
||||
|
||||
If you are unable to find a box that meets your specific use case, you can create one. We recommend that you first create a [base box](/vagrant/docs/boxes/base) to have a clean slate to start from when you build future development environments.
|
||||
|
||||
Learn more about [box formats](/vagrant/docs/boxes/format) to get started.
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ hashicorp/bionic64 (virtualbox, 1.0.0)
|
||||
## Box Info
|
||||
|
||||
To accomplish this, you simply need to include a file named `info.json` when
|
||||
creating a [base box](/docs/boxes/base) which is a JSON document containing
|
||||
creating a [base box](/vagrant/docs/boxes/base) which is a JSON document containing
|
||||
any and all relevant information that will be displayed to the user when the
|
||||
`-i` option is used with `vagrant box list`.
|
||||
|
||||
@ -37,5 +37,5 @@ any and all relevant information that will be displayed to the user when the
|
||||
There are no special keys or values in `info.json`, and Vagrant will print each
|
||||
key and value on its own line.
|
||||
|
||||
The [Box File Format](/docs/boxes/format) provides more information about what
|
||||
The [Box File Format](/vagrant/docs/boxes/format) provides more information about what
|
||||
else goes into a Vagrant box.
|
||||
|
||||
@ -23,13 +23,13 @@ to Vagrant makes it easy to use and fit nicely into the Vagrant workflow.
|
||||
|
||||
This page will cover how to use versioned boxes. It does _not_ cover how
|
||||
to update your own custom boxes with versions. That is covered in
|
||||
[creating a base box](/docs/boxes/base).
|
||||
[creating a base box](/vagrant/docs/boxes/base).
|
||||
|
||||
## Viewing Versions and Updating
|
||||
|
||||
`vagrant box list` only shows _installed_ versions of boxes. If you want
|
||||
to see all available versions of a box, you will have to find the box
|
||||
on [HashiCorp's Vagrant Cloud](/vagrant-cloud). An easy way to find a box
|
||||
on [HashiCorp's Vagrant Cloud](/vagrant/vagrant-cloud). An easy way to find a box
|
||||
is to use the url `https://vagrantcloud.com/$USER/$BOX`. For example, for
|
||||
the `hashicorp/bionic64` box, you can find information about it at
|
||||
`https://vagrantcloud.com/hashicorp/bionic64`.
|
||||
@ -47,7 +47,7 @@ command just downloads these updates locally.
|
||||
## Version Constraints
|
||||
|
||||
You can constrain a Vagrant environment to a specific version or versions
|
||||
of a box using the [Vagrantfile](/docs/vagrantfile/) by specifying
|
||||
of a box using the [Vagrantfile](/vagrant/docs/vagrantfile/) by specifying
|
||||
the `config.vm.box_version` option.
|
||||
|
||||
If this option is not specified, the latest version is always used. This is
|
||||
@ -76,7 +76,7 @@ of the format `X.Y.Z` where `X`, `Y`, and `Z` are all positive integers.
|
||||
|
||||
## Automatic Update Checking
|
||||
|
||||
Using the [Vagrantfile](/docs/vagrantfile/), you can also configure
|
||||
Using the [Vagrantfile](/vagrant/docs/vagrantfile/), you can also configure
|
||||
Vagrant to automatically check for updates during any `vagrant up`. This is
|
||||
enabled by default, but can easily be disabled with
|
||||
`config.vm.box_check_update = false` in your Vagrantfile.
|
||||
|
||||
@ -11,7 +11,7 @@ description: |-
|
||||
|
||||
**Command: `vagrant box`**
|
||||
|
||||
This is the command used to manage (add, remove, etc.) [boxes](/docs/boxes).
|
||||
This is the command used to manage (add, remove, etc.) [boxes](/vagrant/docs/boxes).
|
||||
|
||||
The main functionality of this command is exposed via even more subcommands:
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ Vagrant Cloud.
|
||||
|
||||
**Command: `vagrant cloud auth login`**
|
||||
|
||||
The login command is used to authenticate with [HashiCorp's Vagrant Cloud](/vagrant-cloud)
|
||||
The login command is used to authenticate with [HashiCorp's Vagrant Cloud](/vagrant/vagrant-cloud)
|
||||
server. Logging in is only necessary if you are accessing protected boxes.
|
||||
|
||||
**Logging in is not a requirement to use Vagrant.** The vast majority
|
||||
@ -171,7 +171,7 @@ The provider create command is used to create a new provider entry on Vagrant Cl
|
||||
The `url` argument is expected to be a remote URL that Vagrant Cloud can use
|
||||
to download the provider. If no `url` is specified, the provider entry can be updated
|
||||
later with a url or the [upload](#cloud-provider-upload) command can be used to
|
||||
upload a Vagrant [box file](/docs/boxes).
|
||||
upload a Vagrant [box file](/vagrant/docs/boxes).
|
||||
|
||||
## Cloud Provider Delete
|
||||
|
||||
@ -191,7 +191,7 @@ Vagrant Cloud with the given options.
|
||||
|
||||
**Command: `vagrant cloud provider upload ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION BOX-FILE`**
|
||||
|
||||
The provider upload command will upload a Vagrant [box file](/docs/boxes) to Vagrant Cloud for
|
||||
The provider upload command will upload a Vagrant [box file](/vagrant/docs/boxes) to Vagrant Cloud for
|
||||
the specified version and provider.
|
||||
|
||||
# Cloud Publish
|
||||
|
||||
@ -11,9 +11,9 @@ description: |-
|
||||
**Command: `vagrant connect NAME`**
|
||||
|
||||
The connect command complements the
|
||||
[share command](/docs/cli/share) by enabling access to shared
|
||||
[share command](/vagrant/docs/cli/share) by enabling access to shared
|
||||
environments. You can learn about all the details of Vagrant Share in the
|
||||
[Vagrant Share section](/docs/share/).
|
||||
[Vagrant Share section](/vagrant/docs/share/).
|
||||
|
||||
The reference of available command-line flags to this command
|
||||
is available below.
|
||||
|
||||
@ -35,4 +35,4 @@ the box installed in the system will still be present on the hard drive. To
|
||||
return your computer to the state as it was before `vagrant up` command, you
|
||||
need to use `vagrant box remove`.
|
||||
|
||||
For more information, read about the [`vagrant box remove`](/docs/cli/box) command.
|
||||
For more information, read about the [`vagrant box remove`](/vagrant/docs/cli/box) command.
|
||||
|
||||
@ -25,7 +25,7 @@ available by reading the appropriate sub-section available in the left
|
||||
navigational area of this site.
|
||||
|
||||
You may also wish to consult the
|
||||
[documentation](/docs/other/environmental-variables) regarding the
|
||||
[documentation](/vagrant/docs/other/environmental-variables) regarding the
|
||||
environmental variables that can be used to configure and control
|
||||
Vagrant in a global way.
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ description: |-
|
||||
**Command: `vagrant init [name [url]]`**
|
||||
|
||||
This initializes the current directory to be a Vagrant environment
|
||||
by creating an initial [Vagrantfile](/docs/vagrantfile/) if
|
||||
by creating an initial [Vagrantfile](/vagrant/docs/vagrantfile/) if
|
||||
one does not already exist.
|
||||
|
||||
If a first argument is given, it will prepopulate the `config.vm.box`
|
||||
|
||||
@ -11,13 +11,13 @@ description: |-
|
||||
**Command: `vagrant login`**
|
||||
|
||||
The login command is used to authenticate with the
|
||||
[HashiCorp's Vagrant Cloud](/vagrant-cloud) server. Logging in is only
|
||||
[HashiCorp's Vagrant Cloud](/vagrant/vagrant-cloud) server. Logging in is only
|
||||
necessary if you are accessing protected boxes or using
|
||||
[Vagrant Share](/docs/share/).
|
||||
[Vagrant Share](/vagrant/docs/share/).
|
||||
|
||||
**Logging in is not a requirement to use Vagrant.** The vast majority
|
||||
of Vagrant does _not_ require a login. Only certain features such as protected
|
||||
boxes or [Vagrant Share](/docs/share/) require a login.
|
||||
boxes or [Vagrant Share](/vagrant/docs/share/) require a login.
|
||||
|
||||
The reference of available command-line flags to this command
|
||||
is available below.
|
||||
|
||||
@ -14,7 +14,7 @@ is replaced with machine-friendly output.
|
||||
|
||||
This mode makes it easy to programmatically execute Vagrant and read data
|
||||
out of it. This output format is protected by our
|
||||
[backwards compatibility](/docs/installation/backwards-compatibility)
|
||||
[backwards compatibility](/vagrant/docs/installation/backwards-compatibility)
|
||||
policy. Until Vagrant 2.0 is released, however, the machine readable output
|
||||
may change as we determine more use cases for it. But the backwards
|
||||
compatibility promise should make it safe to write client libraries to
|
||||
|
||||
@ -26,8 +26,8 @@ non-primary subcommands. They're executed just like any other subcommand:
|
||||
The list of non-primary commands is below. Click on any command to learn
|
||||
more about it.
|
||||
|
||||
- [docker-exec](/docs/providers/docker/commands)
|
||||
- [docker-logs](/docs/providers/docker/commands)
|
||||
- [docker-run](/docs/providers/docker/commands)
|
||||
- [rsync](/docs/cli/rsync)
|
||||
- [rsync-auto](/docs/cli/rsync-auto)
|
||||
- [docker-exec](/vagrant/docs/providers/docker/commands)
|
||||
- [docker-logs](/vagrant/docs/providers/docker/commands)
|
||||
- [docker-run](/vagrant/docs/providers/docker/commands)
|
||||
- [rsync](/vagrant/docs/cli/rsync)
|
||||
- [rsync-auto](/vagrant/docs/cli/rsync-auto)
|
||||
|
||||
@ -11,8 +11,8 @@ description: |-
|
||||
**Command: `vagrant package [name|id]`**
|
||||
|
||||
This packages a currently running _VirtualBox_ or _Hyper-V_ environment into a
|
||||
re-usable [box](/docs/boxes). This command can only be used with
|
||||
other [providers](/docs/providers/) based on the provider implementation
|
||||
re-usable [box](/vagrant/docs/boxes). This command can only be used with
|
||||
other [providers](/vagrant/docs/providers/) based on the provider implementation
|
||||
and if the provider supports it.
|
||||
|
||||
## Options
|
||||
@ -30,15 +30,15 @@ and if the provider supports it.
|
||||
tasks.
|
||||
|
||||
- `--info path/to/info.json` - The package will include a custom JSON file containing
|
||||
information to be displayed by the [list](/docs/cli/box#box-list) command when invoked
|
||||
information to be displayed by the [list](/vagrant/docs/cli/box#box-list) command when invoked
|
||||
with the `-i` flag
|
||||
|
||||
- `--vagrantfile FILE` - Packages a Vagrantfile with the box, that is loaded
|
||||
as part of the [Vagrantfile load order](/docs/vagrantfile/#load-order)
|
||||
as part of the [Vagrantfile load order](/vagrant/docs/vagrantfile/#load-order)
|
||||
when the resulting box is used.
|
||||
|
||||
-> **A common misconception** is that the `--vagrantfile`
|
||||
option will package a Vagrantfile that is used when `vagrant init`
|
||||
is used with this box. This is not the case. Instead, a Vagrantfile
|
||||
is loaded and read as part of the Vagrant load process when the box is
|
||||
used. For more information, read about the [Vagrantfile load order](/docs/vagrantfile/#load-order).
|
||||
used. For more information, read about the [Vagrantfile load order](/vagrant/docs/vagrantfile/#load-order).
|
||||
|
||||
@ -10,7 +10,7 @@ description: |-
|
||||
|
||||
**Command: `vagrant plugin`**
|
||||
|
||||
This is the command used to manage [plugins](/docs/plugins/).
|
||||
This is the command used to manage [plugins](/vagrant/docs/plugins/).
|
||||
|
||||
The main functionality of this command is exposed via another level
|
||||
of subcommands:
|
||||
@ -104,7 +104,7 @@ This command accepts optional command-line flags:
|
||||
**Command: `vagrant plugin license <name> <license-file>`**
|
||||
|
||||
This command installs a license for a proprietary Vagrant plugin,
|
||||
such as the [VMware Fusion provider](/docs/providers/vmware).
|
||||
such as the [VMware Fusion provider](/vagrant/docs/providers/vmware).
|
||||
|
||||
# Plugin List
|
||||
|
||||
|
||||
@ -37,4 +37,4 @@ $ vagrant port my-machine
|
||||
|
||||
- `--machine-readable` - This tells Vagrant to display machine-readable output
|
||||
instead of the human-friendly output. More information is available in the
|
||||
[machine-readable output](/docs/cli/machine-readable) documentation.
|
||||
[machine-readable output](/vagrant/docs/cli/machine-readable) documentation.
|
||||
|
||||
@ -10,7 +10,7 @@ description: |-
|
||||
|
||||
**Command: `vagrant provision [vm-name]`**
|
||||
|
||||
Runs any configured [provisioners](/docs/provisioning/)
|
||||
Runs any configured [provisioners](/vagrant/docs/provisioning/)
|
||||
against the running Vagrant managed machine.
|
||||
|
||||
This command is a great way to quickly test any provisioners, and is especially
|
||||
|
||||
@ -10,8 +10,8 @@ description: |-
|
||||
|
||||
**Command: `vagrant reload [name|id]`**
|
||||
|
||||
The equivalent of running a [halt](/docs/cli/halt) followed by an
|
||||
[up](/docs/cli/up).
|
||||
The equivalent of running a [halt](/vagrant/docs/cli/halt) followed by an
|
||||
[up](/vagrant/docs/cli/up).
|
||||
|
||||
This command is usually required for changes made in the Vagrantfile to
|
||||
take effect. After making any modifications to the Vagrantfile, a `reload`
|
||||
|
||||
@ -12,7 +12,7 @@ description: |-
|
||||
**Command: `vagrant resume [name|id]`**
|
||||
|
||||
This resumes a Vagrant managed machine that was previously suspended,
|
||||
perhaps with the [suspend command](/docs/cli/suspend).
|
||||
perhaps with the [suspend command](/vagrant/docs/cli/suspend).
|
||||
|
||||
The configured provisioners will not run again, by default. You can force
|
||||
the provisioners to re-run by specifying the `--provision` flag.
|
||||
|
||||
@ -12,7 +12,7 @@ description: |-
|
||||
**Command: `vagrant rsync-auto`**
|
||||
|
||||
This command watches all local directories of any
|
||||
[rsync synced folders](/docs/synced-folders/rsync) and automatically
|
||||
[rsync synced folders](/vagrant/docs/synced-folders/rsync) and automatically
|
||||
initiates an rsync transfer when changes are detected. This command does
|
||||
not exit until an interrupt is received.
|
||||
|
||||
@ -41,7 +41,7 @@ To ensure that the command works properly, you should start `rsync-auto`
|
||||
only when the machine is running, and shut it down before any machine
|
||||
state changes.
|
||||
|
||||
You can always force a resync with the [rsync](/docs/cli/rsync) command.
|
||||
You can always force a resync with the [rsync](/vagrant/docs/cli/rsync) command.
|
||||
|
||||
## Vagrantfile Changes
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ description: The "vagrant rsync" command forces a re-sync of any rsync synced fo
|
||||
**Command: `vagrant rsync`**
|
||||
|
||||
This command forces a re-sync of any
|
||||
[rsync synced folders](/docs/synced-folders/rsync).
|
||||
[rsync synced folders](/vagrant/docs/synced-folders/rsync).
|
||||
|
||||
Note that if you change any settings within the rsync synced folders such
|
||||
as exclude paths, you will need to `vagrant reload` before this command will
|
||||
|
||||
@ -15,7 +15,7 @@ share your Vagrant environment with anyone in the world, enabling collaboration
|
||||
directly in your Vagrant environment in almost any network environment.
|
||||
|
||||
You can learn about all the details of Vagrant Share in the
|
||||
[Vagrant Share section](/docs/share/).
|
||||
[Vagrant Share section](/vagrant/docs/share/).
|
||||
|
||||
The reference of available command-line flags to this command
|
||||
is available below.
|
||||
|
||||
@ -11,10 +11,10 @@ description: |-
|
||||
**Command: `vagrant suspend [name|id]`**
|
||||
|
||||
This suspends the guest machine Vagrant is managing, rather than fully
|
||||
[shutting it down](/docs/cli/halt) or [destroying it](/docs/cli/destroy).
|
||||
[shutting it down](/vagrant/docs/cli/halt) or [destroying it](/vagrant/docs/cli/destroy).
|
||||
|
||||
A suspend effectively saves the _exact point-in-time state_ of the machine,
|
||||
so that when you [resume](/docs/cli/resume) it later, it begins running
|
||||
so that when you [resume](/vagrant/docs/cli/resume) it later, it begins running
|
||||
immediately from that point, rather than doing a full boot.
|
||||
|
||||
This generally requires extra disk space to store all the contents of the
|
||||
|
||||
@ -11,15 +11,16 @@ description: |-
|
||||
**Command: `vagrant up [name|id]`**
|
||||
|
||||
This command creates and configures guest machines according to your
|
||||
[Vagrantfile](/docs/vagrantfile/).
|
||||
[Vagrantfile](/vagrant/docs/vagrantfile/).
|
||||
|
||||
This is the single most important command in Vagrant, since it is how
|
||||
any Vagrant machine is created. Anyone using Vagrant must use this command
|
||||
on a day-to-day basis.
|
||||
any Vagrant machine is created.
|
||||
|
||||
## Options
|
||||
|
||||
- `name` - Name of machine defined in [Vagrantfile](/docs/vagrantfile/)
|
||||
- `name` - Name of machine defined in [Vagrantfile](/vagrant/docs/vagrantfile/). Using
|
||||
`name` to specify the Vagrant machine to act on must be done from within a
|
||||
Vagrant project (directory where the Vagrantfile exists).
|
||||
|
||||
- `id` - Machine id found with `vagrant global-status`. Using `id` allows
|
||||
you to call `vagrant up id` from any directory.
|
||||
@ -37,7 +38,7 @@ on a day-to-day basis.
|
||||
is supported.
|
||||
|
||||
- `--provider x` - Bring the machine up with the given
|
||||
[provider](/docs/providers/). By default this is "virtualbox".
|
||||
[provider](/vagrant/docs/providers/). By default this is "virtualbox".
|
||||
|
||||
- `--[no-]provision` - Force, or prevent, the provisioners to run.
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ description: The "vagrant validate" command is used to validate your Vagrantfile
|
||||
|
||||
**Command: `vagrant validate`**
|
||||
|
||||
This command validates your [Vagrantfile](/docs/vagrantfile/).
|
||||
This command validates your [Vagrantfile](/vagrant/docs/vagrantfile/).
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ or directly `inline` in a Vagrantfile.
|
||||
option.
|
||||
|
||||
Examples of how to define these options can be found in the
|
||||
[usage documentation](/docs/cloud-init/configuration).
|
||||
[usage documentation](/vagrant/docs/cloud-init/configuration).
|
||||
|
||||
### cloud_init Type
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@ description: Introduction to using cloud-init with Vagrant
|
||||
change in between releases. Use at your own risk. It currently is not officially
|
||||
supported or functional.
|
||||
|
||||
For examples on how to achieve this, among other use cases, please refer to the [usage](/docs/cloud-init/usage)
|
||||
For examples on how to achieve this, among other use cases, please refer to the [usage](/vagrant/docs/cloud-init/usage)
|
||||
guide for more information!
|
||||
|
||||
For more information about what options are available for configuring cloud-init, see the
|
||||
[configuration section](/docs/cloud-init/configuration).
|
||||
[configuration section](/vagrant/docs/cloud-init/configuration).
|
||||
|
||||
@ -17,7 +17,7 @@ VAGRANT_EXPERIMENTAL="cloud_init,disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental)
|
||||
for more info. Without this flag enabled, any cloud-init configs defined will
|
||||
not be configured.
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ VAGRANT_EXPERIMENTAL="disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental/)
|
||||
for more info. Without this flag enabled, any disks defined will not be configured.
|
||||
|
||||
Because of how Hyper-V handles disk management, a Vagrant guest _must_ be powered
|
||||
@ -28,5 +28,5 @@ with a guests disk, you will need to `vagrant reload` the guest for any changes
|
||||
to be applied.
|
||||
|
||||
For more information on how to use Hyper-V to configure disks for a guest, refer
|
||||
to the [general usage](/docs/disks/usage) and [configuration](/docs/disks/configuration)
|
||||
to the [general usage](/vagrant/docs/disks/usage) and [configuration](/vagrant/docs/disks/configuration)
|
||||
guide for more information.
|
||||
|
||||
@ -19,11 +19,11 @@ VAGRANT_EXPERIMENTAL="disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental/)
|
||||
for more info. Without this flag enabled, any disks defined will not be configured.
|
||||
|
||||
For examples of how to use the disk feature with Hyper-V, please refer to the
|
||||
[general disk usage guide](/docs/disks/usage) for more examples.
|
||||
[general disk usage guide](/vagrant/docs/disks/usage) for more examples.
|
||||
|
||||
## provider_config options
|
||||
|
||||
@ -32,7 +32,7 @@ Vagrant supports most options for these operations. You should be able to define
|
||||
the PowerShell specific argument to a given Hyper-V command in the provider_config
|
||||
hash, and Vagrant should properly pass it along to the command.
|
||||
|
||||
To define a provider specific option, please refer to the [Disk Options documentation page](/docs/disks/configuration) for more info.
|
||||
To define a provider specific option, please refer to the [Disk Options documentation page](/vagrant/docs/disks/configuration) for more info.
|
||||
|
||||
### Note about options defined below
|
||||
|
||||
|
||||
@ -14,12 +14,12 @@ for more information on how to use and enable this feature.
|
||||
Vagrant Disks is a feature that allows users to define what mediums should be attached
|
||||
to their guests, as well as allowing users to resize their primary disk.
|
||||
|
||||
For examples on how to achieve this, among other use cases, please refer to the [usage](/docs/disks/usage)
|
||||
For examples on how to achieve this, among other use cases, please refer to the [usage](/vagrant/docs/disks/usage)
|
||||
guide for more information!
|
||||
|
||||
For more information about what options are available for configuring disks, see the
|
||||
[configuration section](/docs/disks/configuration).
|
||||
[configuration section](/vagrant/docs/disks/configuration).
|
||||
|
||||
## Supported Providers
|
||||
|
||||
Currently, only VirtualBox is supported. Please refer to the [VirtualBox documentation](/docs/disks/virtualbox) for more information on using disks with the VirtualBox provider!
|
||||
Currently, only VirtualBox is supported. Please refer to the [VirtualBox documentation](/vagrant/docs/disks/virtualbox) for more information on using disks with the VirtualBox provider!
|
||||
|
||||
@ -17,7 +17,7 @@ VAGRANT_EXPERIMENTAL="disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental/)
|
||||
for more info. Without this flag enabled, any disks defined will not be configured.
|
||||
|
||||
Below are some very simple examples of how to use Vagrant Disks with the VirtualBox provider.
|
||||
|
||||
@ -19,7 +19,7 @@ VAGRANT_EXPERIMENTAL="disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental/)
|
||||
for more info. Without this flag enabled, any disks defined will not be configured.
|
||||
|
||||
**Vagrant currently only supports VirtualBox version 5.x and newer for configuring and
|
||||
@ -42,7 +42,7 @@ disks to a particular storage controller based on the type of disk configured:
|
||||
|
||||
Vagrant will not be able to configure disks of a given type if the associated
|
||||
storage controller does not exist. In this case, you may use
|
||||
[provider-specific customizations](/docs/providers/virtualbox/configuration#vboxmanage-customizations)
|
||||
[provider-specific customizations](/vagrant/docs/providers/virtualbox/configuration#vboxmanage-customizations)
|
||||
to add a required storage controller.
|
||||
|
||||
It should also be noted that storage controllers have different limits for the
|
||||
@ -51,5 +51,5 @@ maximum number of disks for a storage controller type will result in a Vagrant
|
||||
error.
|
||||
|
||||
For more information on how to use VirtualBox to configure disks for a guest, refer
|
||||
to the [general usage](/docs/disks/usage) and [configuration](/docs/disks/configuration)
|
||||
to the [general usage](/vagrant/docs/disks/usage) and [configuration](/vagrant/docs/disks/configuration)
|
||||
guide for more information.
|
||||
|
||||
@ -19,11 +19,11 @@ VAGRANT_EXPERIMENTAL="disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental/)
|
||||
for more info. Without this flag enabled, any disks defined will not be configured.
|
||||
|
||||
For examples of how to use the disk feature with VirtualBox, please refer to the
|
||||
[general disk usage guide](/docs/disks/usage) for more examples.
|
||||
[general disk usage guide](/vagrant/docs/disks/usage) for more examples.
|
||||
|
||||
## provider_config options
|
||||
|
||||
|
||||
@ -36,6 +36,6 @@ Vagrant will not decrease the size of a disk.
|
||||
If snapshots exist for a VM, disk functionality will be limited. Vagrant will return
|
||||
an error for any actions that are limited due to the existence of snapshots. In order
|
||||
to restore functionality the snapshots must be removed. This can be done using the
|
||||
[`vagrant snapshot delete`](/docs/cli/snapshot) command. To delete all snapshots
|
||||
[`vagrant snapshot delete`](/vagrant/docs/cli/snapshot) command. To delete all snapshots
|
||||
for a VMware backed VM try `vagrant cap provider delete_all_snapshots --target <target vm name>`.
|
||||
Note once a snapshot is deleted, it can not be restored.
|
||||
|
||||
@ -21,7 +21,7 @@ VAGRANT_EXPERIMENTAL="disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental/)
|
||||
for more info. Without this flag enabled, any disks defined will not be configured.
|
||||
|
||||
Because of how VMware handles disk management, a Vagrant guest _must_ be powered
|
||||
@ -30,5 +30,5 @@ with a guests disk, you will need to `vagrant reload` the guest for any changes
|
||||
to be applied.
|
||||
|
||||
For more information on how to use VMware to configure disks for a guest, refer
|
||||
to the [general usage](/docs/disks/usage) and [configuration](/docs/disks/configuration)
|
||||
to the [general usage](/vagrant/docs/disks/usage) and [configuration](/vagrant/docs/disks/configuration)
|
||||
guide for more information.
|
||||
|
||||
@ -21,17 +21,17 @@ VAGRANT_EXPERIMENTAL="disks"
|
||||
```
|
||||
|
||||
Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more
|
||||
information about this flag visit the [Experimental docs page](/docs/experimental/)
|
||||
information about this flag visit the [Experimental docs page](/vagrant/docs/experimental/)
|
||||
for more info. Without this flag enabled, any disks defined will not be configured.
|
||||
|
||||
For examples of how to use the disk feature with VMWware, please refer to the
|
||||
[general disk usage guide](/docs/disks/usage) for more examples.
|
||||
[general disk usage guide](/vagrant/docs/disks/usage) for more examples.
|
||||
|
||||
## provider_config options
|
||||
|
||||
Vagrant supports some additional VMWware specific options for specifying disk.
|
||||
|
||||
To define a provider specific option, please refer to the [Disk Options documentation page](/docs/disks/configuration) for more info.
|
||||
To define a provider specific option, please refer to the [Disk Options documentation page](/vagrant/docs/disks/configuration) for more info.
|
||||
|
||||
### Note about options defined below
|
||||
|
||||
|
||||
@ -42,22 +42,22 @@ This is a list of all the valid experimental features that Vagrant recognizes:
|
||||
### `cloud_init`
|
||||
|
||||
Enabling this feature allows Vagrant to use the `cloud-init` feature. More
|
||||
information about these options can be found on the [cloud-init documentation page](/docs/cloud-init/usage)
|
||||
information about these options can be found on the [cloud-init documentation page](/vagrant/docs/cloud-init/usage)
|
||||
|
||||
### `dependency_provisioners`
|
||||
|
||||
Enabling this feature allows all provisioners to specify `before` and `after`
|
||||
options. These options allow provisioners to be configured to run before or after
|
||||
any given "root" provisioner. More information about these options can be found
|
||||
on the [base provisioner documentation page](/docs/provisioning/basic_usage)
|
||||
on the [base provisioner documentation page](/vagrant/docs/provisioning/basic_usage)
|
||||
|
||||
### `disks`
|
||||
|
||||
Enabling this feature will allow Vagrant to manage and configure virtual hard disks
|
||||
for certain providers. More information about supported providers and how to
|
||||
configure disks can be found on the [disk documentation page](/docs/disks)
|
||||
configure disks can be found on the [disk documentation page](/vagrant/docs/disks)
|
||||
|
||||
### `typed_triggers`
|
||||
|
||||
Enabling this feature allows triggers to recognize and execute `:type` triggers.
|
||||
More information about how these should be used can be found on the [trigger documentation page](/docs/triggers/configuration#trigger-types)
|
||||
More information about how these should be used can be found on the [trigger documentation page](/vagrant/docs/triggers/configuration#trigger-types)
|
||||
|
||||
@ -105,7 +105,7 @@ The form of these directories is as follows:
|
||||
|
||||
Vagrant-go does not have knowledge of the Vagrant-ruby data directories so does not
|
||||
have access to that data and vice versa. Both Vagrant-go and Vagrant-ruby
|
||||
respect the [Vagrant environment variables](/docs/other/environmental-variables/) for
|
||||
respect the [Vagrant environment variables](/vagrant/docs/other/environmental-variables/) for
|
||||
setting data directory paths. However, the layout and content of these directories
|
||||
are different for Vagrant-go and Vagrant-ruby.
|
||||
|
||||
|
||||
@ -14,10 +14,10 @@ Welcome to the documentation for Vagrant - the command line utility for managing
|
||||
the lifecycle of virtual machines. This website aims to document every feature
|
||||
of Vagrant from top-to-bottom, covering as much detail as possible. If you are
|
||||
just getting started with Vagrant, we highly recommended starting with
|
||||
the [getting started tutorial](https://learn.hashicorp.com/vagrant) on
|
||||
the [getting started tutorial](/vagrant/tutorials) on
|
||||
HashiCorp's Learn platform first, and then returning to this page.
|
||||
|
||||
The navigation will take you through each component of Vagrant. Click on a
|
||||
navigation item to get started, or read more about
|
||||
[why developers, designers, and operators choose Vagrant](/intro)
|
||||
[why developers, designers, and operators choose Vagrant](/vagrant/intro)
|
||||
for their needs.
|
||||
|
||||
@ -1,45 +1,45 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: Installing Vagrant
|
||||
page_title: Install Vagrant
|
||||
description: |-
|
||||
Installing Vagrant is extremely easy. Head over to the Vagrant downloads page
|
||||
and get the appropriate installer or package for your platform. Install the
|
||||
Vagrant is available for most platforms. Install the Vagrant
|
||||
package using standard procedures for your operating system.
|
||||
---
|
||||
|
||||
# Installing Vagrant
|
||||
# Install Vagrant
|
||||
|
||||
Installing Vagrant is extremely easy. Head over to the
|
||||
[Vagrant downloads page](/downloads) and get the appropriate installer or
|
||||
package for your platform. Install the package using standard procedures for
|
||||
To get started with Vagrant, download the appropriate installer or
|
||||
package for your platform from our
|
||||
[Vagrant downloads page](/vagrant/downloads). Install the package with the standard procedures for
|
||||
your operating system.
|
||||
|
||||
The installer will automatically add `vagrant` to your system path
|
||||
so that it is available in terminals. If it is not found, please try
|
||||
logging out and logging back in to your system (this is particularly
|
||||
necessary sometimes for Windows).
|
||||
The installer automatically adds `vagrant` to your system path
|
||||
so that it is available in terminals. If it is not found,
|
||||
log out and back into your system; this is a common issue for Windows.
|
||||
|
||||
~> **Looking for the gem install?** Vagrant 1.0.x had the option to
|
||||
~> **Rubygem installation is unsupported** Vagrant 1.0.x has the option to
|
||||
be installed as a [RubyGem](https://en.wikipedia.org/wiki/RubyGems).
|
||||
This installation method is no longer supported. If you have an old version
|
||||
of Vagrant installed via Rubygems, please remove it prior to installing newer
|
||||
However, this installation method is no longer supported. If you have an old version
|
||||
of Vagrant installed via Rubygems, remove it prior to installing newer
|
||||
versions of Vagrant.
|
||||
|
||||
~> **Beware of system package managers!** Some operating system
|
||||
distributions include a vagrant package in their upstream package repos.
|
||||
Please do not install Vagrant in this manner. Typically these packages are
|
||||
missing dependencies or include very outdated versions of Vagrant. If you
|
||||
install via your system's package manager, it is very likely that you will
|
||||
experience issues. Please use the official installers on the downloads page.
|
||||
## First development environment
|
||||
|
||||
## Running Multiple Hypervisors
|
||||
If you are new to Vagrant, the next step to set up a development environment is to install
|
||||
a [box](/vagrant/tutorials/getting-started/getting-started-boxes).
|
||||
|
||||
Sometimes, certain hypervisors do not allow you to bring up virtual machines
|
||||
if more than one hypervisor is in use. If you are lucky, you might see the following
|
||||
error message come up when trying to bring up a virtual machine with Vagrant and
|
||||
VirtualBox:
|
||||
## How to use multiple hypervisors
|
||||
|
||||
```text
|
||||
Hypervisors often do not allow you to bring up virtual machines if you have more than one hypervisor in use.
|
||||
|
||||
Below are a couple of examples to allow you
|
||||
to use Vagrant and VirtualBox if another hypervisor is present.
|
||||
|
||||
### Linux, VirtualBox, and KVM
|
||||
|
||||
If you encounter the following error message, it is because another hypervisor, like KVM, is in use.
|
||||
|
||||
```shell-session
|
||||
There was an error while executing `VBoxManage`, a CLI used by Vagrant for controlling VirtualBox. The command and stderr is shown below.
|
||||
|
||||
Command: ["startvm", <ID of the VM>, "--type", "headless"]
|
||||
@ -50,16 +50,9 @@ VBoxManage: error: VirtualBox can't operate in VMX root mode. Please disable the
|
||||
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component ConsoleWrap, interface IConsole
|
||||
```
|
||||
|
||||
Other operating systems like Windows will blue screen if you attempt to bring up
|
||||
a VirtualBox VM with Hyper-V enabled. Below are a couple of ways to ensure you
|
||||
can use Vagrant and VirtualBox if another hypervisor is present.
|
||||
You must add the additional hypervisors to the deny list in order for VirtualBox to run correctly.
|
||||
|
||||
### Linux, VirtualBox, and KVM
|
||||
|
||||
The above error message is because another hypervisor (like KVM) is in use.
|
||||
We must blacklist these in order for VirtualBox to run correctly.
|
||||
|
||||
First find out the name of the hypervisor:
|
||||
First, find out the name of the hypervisor.
|
||||
|
||||
```shell-session
|
||||
$ lsmod | grep kvm
|
||||
@ -68,31 +61,33 @@ kvm 593920 1 kvm_intel
|
||||
irqbypass 16384 1 kvm
|
||||
```
|
||||
|
||||
The one we're interested in is `kvm_intel`. You might have another.
|
||||
|
||||
Blacklist the hypervisor (run the following as root):
|
||||
Use the `blacklist` command to add the hypervisor to your denylist.
|
||||
|
||||
```shell-session
|
||||
$ echo 'blacklist kvm-intel' >> /etc/modprobe.d/blacklist.conf
|
||||
```
|
||||
|
||||
Restart your machine and try running vagrant again.
|
||||
Restart your machine and try the `vagrant` command again.
|
||||
|
||||
### Windows, VirtualBox, and Hyper-V
|
||||
|
||||
If you encounter an issue with Windows, you will get a blue screen if you attempt to bring up
|
||||
a VirtualBox VM with Hyper-V enabled.
|
||||
|
||||
If you wish to use VirtualBox on Windows, you must ensure that Hyper-V is not enabled
|
||||
on Windows. You can turn off the feature by running this Powershell command for Windows 10:
|
||||
on Windows. You can turn off the feature with the following Powershell command for Windows 10.
|
||||
|
||||
```powershell
|
||||
Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All
|
||||
```
|
||||
For Windows 11, you can run on an elevated Powershell:
|
||||
|
||||
For Windows 11, you can use an elevated Powershell.
|
||||
|
||||
```powershell
|
||||
bcdedit /set hypervisorlaunchtype off
|
||||
```
|
||||
|
||||
You can also disable it by going through the Windows system settings:
|
||||
You can also disable Hyper-V in the Windows system settings.
|
||||
|
||||
- Right click on the Windows button and select ‘Apps and Features’.
|
||||
- Select Turn Windows Features on or off.
|
||||
@ -100,3 +95,5 @@ You can also disable it by going through the Windows system settings:
|
||||
|
||||
You might have to reboot your machine for the changes to take effect. More information
|
||||
about Hyper-V can be read [here](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v).
|
||||
|
||||
|
||||
|
||||
@ -42,8 +42,8 @@ rm -f /usr/bin/vagrant
|
||||
|
||||
## Remove user data
|
||||
|
||||
The removal of user data will remove all [boxes](/docs/boxes),
|
||||
[plugins](/docs/plugins/), license files, and any stored state that may be used
|
||||
The removal of user data will remove all [boxes](/vagrant/docs/boxes),
|
||||
[plugins](/vagrant/docs/plugins), license files, and any stored state that may be used
|
||||
by Vagrant. Removing the user data effectively makes Vagrant think it
|
||||
is a fresh install.
|
||||
|
||||
|
||||
@ -10,13 +10,13 @@ description: |-
|
||||
|
||||
# Upgrade from Vagrant 1.0.x
|
||||
|
||||
The upgrade process from 1.0.x to 1.x is straightforward, Vagrant is
|
||||
[backwards compatible](/docs/installation/backwards-compatibility)
|
||||
with Vagrant 1.0.x. To reinstall Vagrant
|
||||
over your previous installation, download the latest package and
|
||||
install it with standard procedures for your operating system.
|
||||
The upgrade process from 1.0.x to 1.x is straightforward. Vagrant is quite
|
||||
[backwards compatible](/vagrant/docs/installation/backwards-compatibility)
|
||||
with Vagrant 1.0.x, so you can simply reinstall Vagrant
|
||||
over your previous installation by downloading the latest package and
|
||||
installing it using standard procedures for your operating system.
|
||||
|
||||
As the [backwards compatibility](/docs/installation/backwards-compatibility)
|
||||
As the [backwards compatibility](/vagrant/docs/installation/backwards-compatibility)
|
||||
page says, **Vagrant 1.0.x plugins will not work with Vagrant 1.1+**. Many
|
||||
of these plugins have been updated to work with newer versions of Vagrant,
|
||||
so you will need to verify if they've been updated. If not however, you will have
|
||||
|
||||
@ -1,31 +1,34 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: Upgrading Vagrant
|
||||
page_title: Upgrade Vagrant
|
||||
description: |-
|
||||
If you are upgrading from Vagrant 1.0.x, please read the specific page
|
||||
dedicated to that. This page covers upgrading Vagrant in general during the
|
||||
1.x series.
|
||||
This page details the general process to upgrade Vagrant for the
|
||||
1.x.x series. If you need to upgrade from Vagrant 1.0.x, read the specific page
|
||||
dedicated to that.
|
||||
---
|
||||
|
||||
# Upgrading Vagrant
|
||||
# Upgrade Vagrant
|
||||
|
||||
If you are upgrading from Vagrant 1.0.x, please read the
|
||||
[specific page dedicated to that](/docs/installation/upgrading-from-1-0).
|
||||
This page covers upgrading Vagrant in general during the 1.x series.
|
||||
This page details how to upgrade Vagrant in the 1.x.x series.
|
||||
|
||||
Vagrant upgrades during the 1.x release series are straightforward:
|
||||
~> If you need to upgrade from Vagrant 1.0.x, read the
|
||||
[specific page dedicated to that](/vagrant/docs/installation/upgrading-from-1-0).
|
||||
|
||||
1. [Download](/downloads) the new package
|
||||
Vagrant upgrades during the 1.x.x release series are straightforward:
|
||||
|
||||
1. [Download](/vagrant/downloads) the new package
|
||||
2. Install it over the existing package
|
||||
|
||||
The installers will properly overwrite and remove old files. It is recommended
|
||||
that no other Vagrant processes are running during the upgrade process.
|
||||
|
||||
Note that Vagrantfile stability for the new Vagrantfile syntax is not
|
||||
promised until 2.0 final. So while Vagrantfiles made for 1.0.x will
|
||||
[continue to work](/docs/installation/backwards-compatibility),
|
||||
newer Vagrantfiles may have backwards incompatible changes until 2.0 final.
|
||||
## Vagrantfile compatibility with 3.0
|
||||
|
||||
-> **Run into troubles upgrading?** Please [report an issue](https://github.com/hashicorp/vagrant/issues)
|
||||
if you run into problems upgrading. Upgrades are meant to be a smooth
|
||||
process and we consider it a bug if it was not.
|
||||
Note that Vagrantfile stability for the new Vagrantfile syntax is not
|
||||
guaranteed until Vagrant 3.0. While Vagrantfiles made for 1.0.x will
|
||||
[continue to work](/vagrant/docs/installation/backwards-compatibility),
|
||||
newer Vagrantfiles may have backwards incompatible changes until 3.0.
|
||||
|
||||
## Issue reports
|
||||
|
||||
If you encounter any problems at upgrade time, [report them as an issue in Github](https://github.com/hashicorp/vagrant/issues). Upgrades are meant to be a smooth process and we consider it a bug if it was not.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user