Docker Provider driver.rb fails with `block in network_defined?': undefined method `size' for nil:NilClass (NoMethodError)
When provisioning VVV using Docker as a provider it fails nearly immediately with the following error:
/opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/driver.rb:352:in `block in network_defined?': undefined method `size' for nil:NilClass (NoMethodError)
if (config.size > 0 &&
^^^^^
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/driver.rb:350:in `each'
Debug output
https://gist.github.com/tomjn/92ed3f0dcbfb47c6c2bd6d24af2b6620
CLI output and command:
❯ vagrant up --provision --provider="docker"
__ __ __ __
\ V\ V\ V / v3.13 Ruby:3.1.4, Path:"/Users/tomjn/vvv-local"
\_/\_/\_/ git::develop(c4250187)
Platform: darwin shell:/bin/zsh shared_db_folder_disabled
Vagrant: v2.4.1, parallels: v19.3.0
Docs: https://varyingvagrantvagrants.org/
Contribute: https://github.com/varying-vagrant-vagrants/vvv
Dashboard: http://vvv.test
Bringing machine 'default' up with 'docker' provider...
==> default: Creating and configuring docker networks...
/opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/driver.rb:352:in `block in network_defined?': undefined method `size' for nil:NilClass (NoMethodError)
if (config.size > 0 &&
^^^^^
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/driver.rb:350:in `each'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/driver.rb:350:in `network_defined?'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:140:in `process_private_network'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:343:in `block (3 levels) in call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:333:in `each'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:333:in `each_with_index'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:333:in `block (2 levels) in call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/environment.rb:649:in `lock'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:331:in `block in call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:330:in `synchronize'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_networks.rb:330:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_nfs_settings.rb:18:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/synced_folders.rb:90:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/delayed.rb:22:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/synced_folder_cleanup.rb:31:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/synced_folders/nfs/action_cleanup.rb:28:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/prepare_nfs_valid_ids.rb:17:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/host_machine_sync_folders.rb:26:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/host_machine_build_dir.rb:22:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/init_state.rb:18:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builder.rb:183:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/util/busy.rb:22:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/call.rb:56:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/provision.rb:83:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builder.rb:183:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/util/busy.rb:22:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/call.rb:56:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builder.rb:183:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/util/busy.rb:22:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/call.rb:56:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/destroy_build_image.rb:46:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/handle_box.rb:28:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builder.rb:183:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/util/busy.rb:22:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/call.rb:56:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/plugins/providers/docker/action/host_machine.rb:21:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/config_validate.rb:28:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/handle_box.rb:28:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:117:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builder.rb:183:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/util/busy.rb:22:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/call.rb:56:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builtin/delayed.rb:22:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/warden.rb:38:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/builder.rb:183:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/util/busy.rb:22:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/action/runner.rb:104:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/machine.rb:247:in `action_raw'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/machine.rb:216:in `block in action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/environment.rb:649:in `lock'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/machine.rb:202:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/machine.rb:202:in `action'
from /opt/vagrant/embedded/gems/gems/vagrant-2.4.1/lib/vagrant/batch_action.rb:89:in `block (2 levels) in run'
Expected behavior
I expected a container and provisioners to run
Actual behavior
A fatal error in the ruby vagrant plugin before the machine could be setup, and no new containers in Docker
Reproduction information
Vagrant version
❯ vagrant -v
Vagrant 2.4.1
Host operating system
MacOS 14.1.1 Arm64
Guest operating system
Ubuntu 20 Arm64
Steps to reproduce
- `vagrant up --provision --provider="docker"
Vagrantfile
# frozen_string_literal: true
# -*- mode: ruby -*-
# vi: set ft=ruby ts=2 sw=2 et:
VAGRANTFILE_API_VERSION = "2"
Vagrant.require_version '>= 2.2.4'
require 'yaml'
require 'fileutils'
require 'pathname'
require 'socket'
def sudo_warnings
red = "\033[38;5;9m" # 124m"
creset = "\033[0m"
puts "#{red}┌-──────────────────────────────────────────────────────────────────────────────┐#{creset}"
puts "#{red}│ │#{creset}"
puts "#{red}│ ⚠ DANGER DO NOT USE SUDO ⚠ │#{creset}"
puts "#{red}│ │#{creset}"
puts "#{red}│ ! ▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄ ! You should never use sudo or root with vagrant. │#{creset}"
puts "#{red}│ !█▒▒░░░░░░░░░▒▒█ It causes lots of problems :( │#{creset}"
puts "#{red}│ █░░█░▄▄░░█░░█ ! │#{creset}"
puts "#{red}│ █░░█░░█░▄▄█ ! We're really sorry but you may need to do painful │#{creset}"
puts "#{red}│ ! ▀▄░█░░██░░█ cleanup commands to fix this. │#{creset}"
puts "#{red}│ │#{creset}"
puts "#{red}│ If vagrant does not work for you without sudo, open a GitHub issue instead │#{creset}"
puts "#{red}│ In the future, this warning will halt provisioning to prevent new users │#{creset}"
puts "#{red}│ making this mistake. │#{creset}"
puts "#{red}│ │#{creset}"
puts "#{red}│ ⚠ DANGER SUDO DETECTED! │#{creset}"
puts "#{red}│ │#{creset}"
puts "#{red}│ In the future the VVV team will be making it harder to use VVV with sudo. │#{creset}"
puts "#{red}│ We will require a config option so that users can do data recovery, and │#{creset}"
puts "#{red}│ disable sites and the dashboard. │#{creset}"
puts "#{red}│ │#{creset}"
puts "#{red}│ DO NOT USE SUDO, use ctrl+c/cmd+c and cancel this command ASAP!!! │#{creset}"
puts "#{red}│ │#{creset}"
puts "#{red}└───────────────────────────────────────────────────────────────────────────────┘#{creset}"
# exit
end
vagrant_dir = __dir__
show_logo = false
branch_c = "\033[38;5;6m" # 111m"
red = "\033[38;5;9m" # 124m"
green = "\033[1;38;5;2m" # 22m"
blue = "\033[38;5;4m" # 33m"
purple = "\033[38;5;5m" # 129m"
docs = "\033[0m"
yellow = "\033[38;5;3m" # 136m"
yellow_underlined = "\033[4;38;5;3m" # 136m"
url = yellow_underlined
creset = "\033[0m"
version = '?'
File.open("#{vagrant_dir}/version", 'r') do |f|
version = f.read
version = version.gsub("\n", '')
end
unless Vagrant::Util::Platform.windows?
if Process.uid == 0
sudo_warnings
end
end
unless Vagrant::Util::Platform.windows?
if Process.uid == 0
puts " "
puts "#{red} ⚠ DANGER VAGRANT IS RUNNING AS ROOT/SUDO, DO NOT USE SUDO ⚠#{creset}"
puts " "
end
end
# whitelist when we show the logo, else it'll show on global Vagrant commands
show_logo = true if %w[up resume status provision reload].include? ARGV[0]
show_logo = false if ENV['VVV_SKIP_LOGO']
# Show the initial splash screen
if show_logo
git_or_zip = 'zip-no-vcs'
branch = ''
commit = ''
if File.directory?("#{vagrant_dir}/.git")
git_or_zip = 'git::'
branch = `git --git-dir="#{vagrant_dir}/.git" --work-tree="#{vagrant_dir}" rev-parse --abbrev-ref HEAD`
branch = branch.chomp("\n"); # remove trailing newline so it doesn't break the ascii art
commit = `git --git-dir="#{vagrant_dir}/.git" --work-tree="#{vagrant_dir}" rev-parse --short HEAD`
commit = '(' + commit.chomp("\n") + ')'; # remove trailing newline so it doesn't break the ascii art
end
splashfirst = <<~HEREDOC
\033[1;38;5;196m#{red}__ #{green}__ #{blue}__ __
#{red}\\ V#{green}\\ V#{blue}\\ V / #{purple}v#{version} #{purple}Ruby:#{RUBY_VERSION}, Path:"#{vagrant_dir}"
#{red} \\_/#{green}\\_/#{blue}\\_/ #{creset}#{branch_c}#{git_or_zip}#{branch}#{commit}#{creset}
HEREDOC
puts splashfirst
end
# Load the config file before the second section of the splash screen
# Perform file migrations from older versions
vvv_config_file = File.join(vagrant_dir, 'config/config.yml')
unless File.file?(vvv_config_file)
old_vvv_config = File.join(vagrant_dir, 'vvv-custom.yml')
if File.file?(old_vvv_config)
puts "#{yellow}Migrating #{red}vvv-custom.yml#{yellow} to #{green}config/config.yml#{yellow}\nIMPORTANT NOTE: Make all modifications to #{green}config/config.yml#{yellow}.#{creset}\n\n"
FileUtils.mv(old_vvv_config, vvv_config_file)
else
puts "#{yellow}Copying #{red}config/default-config.yml#{yellow} to #{green}config/config.yml#{yellow}\nIMPORTANT NOTE: Make all modifications to #{green}config/config.yml#{yellow} in future so that they are not lost when VVV updates.#{creset}\n\n"
FileUtils.cp(File.join(vagrant_dir, 'config/default-config.yml'), vvv_config_file)
end
end
old_db_backup_dir = File.join(vagrant_dir, 'database/backups/')
new_db_backup_dir = File.join(vagrant_dir, 'database/sql/backups/')
if (File.directory?(old_db_backup_dir) == true) && (File.directory?(new_db_backup_dir) == false)
puts 'Moving db backup directory into database/sql/backups'
FileUtils.mv(old_db_backup_dir, new_db_backup_dir)
end
begin
vvv_config = YAML.load_file(vvv_config_file)
unless vvv_config['sites'].is_a? Hash
vvv_config['sites'] = {}
puts "#{red}config/config.yml is missing a sites section.#{creset}\n\n"
end
rescue StandardError => e
puts "#{red}config/config.yml isn't a valid YAML file.#{creset}\n\n"
puts "#{red}VVV cannot be executed!#{creset}\n\n"
warn e.message
exit
end
vvv_config['hosts'] = [] unless vvv_config['hosts'].is_a? Hash
vvv_config['hosts'] += ['vvv.test']
vvv_config['sites'].each do |site, args|
if args.is_a? String
repo = args
args = {}
args['repo'] = repo
end
args = {} unless args.is_a? Hash
defaults = {}
defaults['repo'] = false
defaults['vm_dir'] = "/srv/www/#{site}"
defaults['local_dir'] = File.join(vagrant_dir, 'www', site)
defaults['branch'] = 'master'
defaults['skip_provisioning'] = false
defaults['allow_customfile'] = false
defaults['nginx_upstream'] = 'php'
defaults['hosts'] = []
vvv_config['sites'][site] = defaults.merge(args)
unless vvv_config['sites'][site]['skip_provisioning']
site_host_paths = Dir.glob(Array.new(4) { |i| vvv_config['sites'][site]['local_dir'] + '/*' * (i + 1) + '/vvv-hosts' })
vvv_config['sites'][site]['hosts'] += site_host_paths.map do |path|
lines = File.readlines(path).map(&:chomp)
lines.grep(/\A[^#]/)
end.flatten
if vvv_config['sites'][site]['hosts'].is_a? Array
vvv_config['hosts'] += vvv_config['sites'][site]['hosts']
else
vvv_config['hosts'] += ["#{site}.test"]
end
end
vvv_config['sites'][site].delete('hosts')
end
if vvv_config['extension-sources'].is_a? Hash
vvv_config['extension-sources'].each do |name, args|
next unless args.is_a? String
repo = args
args = {}
args['repo'] = repo
args['branch'] = 'master'
vvv_config['extension-sources'][name] = args
end
else
vvv_config['extension-sources'] = {}
end
vvv_config['dashboard'] = {} unless vvv_config['dashboard']
dashboard_defaults = {}
dashboard_defaults['repo'] = 'https://github.com/Varying-Vagrant-Vagrants/dashboard.git'
dashboard_defaults['branch'] = 'master'
vvv_config['dashboard'] = dashboard_defaults.merge(vvv_config['dashboard'])
unless vvv_config['extension-sources'].key?('core')
vvv_config['extension-sources']['core'] = {}
vvv_config['extension-sources']['core']['repo'] = 'https://github.com/Varying-Vagrant-Vagrants/vvv-utilities.git'
vvv_config['extension-sources']['core']['branch'] = 'master'
end
vvv_config['utilities'] = {} unless vvv_config['utilities'].is_a? Hash
vvv_config['utility-sources'] = {} unless vvv_config['utility-sources'].is_a? Hash
vvv_config['extension-sources'] = {} unless vvv_config['extension-sources'].is_a? Hash
vvv_config['extensions'] = {} unless vvv_config['extensions'].is_a? Hash
vvv_config['vm_config'] = {} unless vvv_config['vm_config'].is_a? Hash
vvv_config['general'] = {} unless vvv_config['general'].is_a? Hash
defaults = {}
defaults['memory'] = 2048
defaults['cores'] = 1
defaults['provider'] = 'virtualbox'
# if Arm default to docker
if Etc.uname[:version].include? 'ARM64'
defaults['provider'] = 'docker'
end
# This should rarely be overridden, so it's not included in the config/default-config.yml file.
defaults['private_network_ip'] = '192.168.56.4'
vvv_config['vm_config'] = defaults.merge(vvv_config['vm_config'])
vvv_config['hosts'] = vvv_config['hosts'].uniq
vvv_config['vagrant-plugins'] = {} unless vvv_config['vagrant-plugins']
# Early mapping of the hosts to be added.
vvv_config['utilities'].each do |name, extensions|
extensions = {} unless extensions.is_a? Array
extensions.each do |extension|
if extension == 'tideways'
vvv_config['hosts'] += ['tideways.vvv.test']
vvv_config['hosts'] += ['xhgui.vvv.test']
end
end
end
vvv_config['extensions'].each do |name, extensions|
extensions = {} unless extensions.is_a? Array
extensions.each do |extension|
if extension == 'tideways'
vvv_config['hosts'] += ['tideways.vvv.test']
vvv_config['hosts'] += ['xhgui.vvv.test']
end
end
end
# Create a global variable to use in functions and classes
$vvv_config = vvv_config
# Show the second splash screen section
if show_logo
platform = [ Vagrant::Util::Platform.platform]
if Vagrant::Util::Platform.windows?
platform << 'windows '
platform << 'wsl ' if Vagrant::Util::Platform.wsl?
platform << 'msys ' if Vagrant::Util::Platform.msys?
platform << 'cygwin ' if Vagrant::Util::Platform.cygwin?
if Vagrant::Util::Platform.windows_hyperv_enabled?
platform << 'HyperV-Enabled '
end
platform << 'HyperV-Admin ' if Vagrant::Util::Platform.windows_hyperv_admin?
if Vagrant::Util::Platform.windows_admin?
platform << 'HasWinAdminPriv '
else
platform << 'missingWinAdminPriv ' unless Vagrant::Util::Platform.windows_admin?
end
else
platform << 'shell:' + ENV['SHELL'] if ENV['SHELL']
platform << 'systemd ' if Vagrant::Util::Platform.systemd?
end
platform << 'vagrant-hostmanager' if Vagrant.has_plugin?('vagrant-hostmanager')
platform << 'vagrant-hostsupdater' if Vagrant.has_plugin?('vagrant-hostsupdater')
platform << 'vagrant-goodhosts' if Vagrant.has_plugin?('vagrant-goodhosts')
platform << 'vagrant-vbguest' if Vagrant.has_plugin?('vagrant-vbguest')
platform << 'vagrant-disksize' if Vagrant.has_plugin?('vagrant-disksize')
platform << 'CaseSensitiveFS' if Vagrant::Util::Platform.fs_case_sensitive?
unless Vagrant::Util::Platform.terminal_supports_colors?
platform << 'monochrome-terminal'
end
if defined? vvv_config['vm_config']['wordcamp_contributor_day_box']
if vvv_config['vm_config']['wordcamp_contributor_day_box'] == true
platform << 'contributor_day_box'
end
end
if defined? vvv_config['vm_config']['box']
unless vvv_config['vm_config']['box'].nil?
puts "Custom Box: Box overridden via config/config.yml , this won't take effect until a destroy + reprovision happens"
platform << 'box_override:' + vvv_config['vm_config']['box']
end
end
if defined? vvv_config['general']['db_share_type']
if vvv_config['general']['db_share_type'] != true
platform << 'shared_db_folder_disabled'
else
platform << 'shared_db_folder_enabled'
end
else
platform << 'shared_db_folder_default'
end
provider_version = '??'
provider_meta = nil
case vvv_config['vm_config']['provider']
when 'virtualbox'
provider_meta = VagrantPlugins::ProviderVirtualBox::Driver::Meta.new()
provider_version = provider_meta.version
when 'parallels'
provider_version = '?'
if defined? VagrantPlugins::Parallels
provider_meta = VagrantPlugins::Parallels::Driver::Meta.new()
provider_version = provider_meta.version
end
when 'vmware'
provider_version = '??'
when 'hyperv'
provider_version = 'n/a'
when 'docker'
provider_version = VagrantPlugins::DockerProvider::Driver.new.execute("docker", "-v").gsub("Docker version ", "")
else
provider_version = '??'
end
splashsecond = <<~HEREDOC
#{yellow}Platform: #{yellow}#{platform.join(' ')}
#{green}Vagrant: #{green}v#{Vagrant::VERSION}, #{blue}#{vvv_config['vm_config']['provider']}: #{blue}v#{provider_version}
#{docs}Docs: #{url}https://varyingvagrantvagrants.org/
#{docs}Contribute: #{url}https://github.com/varying-vagrant-vagrants/vvv
#{docs}Dashboard: #{url}http://vvv.test#{creset}
HEREDOC
puts splashsecond
end
if defined? vvv_config['vm_config']['provider']
# Override or set the vagrant provider.
ENV['VAGRANT_DEFAULT_PROVIDER'] = vvv_config['vm_config']['provider']
end
ENV['LC_ALL'] = 'en_US.UTF-8'
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# VirtualBox
config.vm.provider :virtualbox do |v|
unless Vagrant::Util::Platform.windows?
if Process.uid == 0
machine_id_file=Pathname.new(".vagrant/machines/default/virtualbox/id")
unless machine_id_file.exist?()
puts "#{red} ⚠ DANGER VAGRANT IS RUNNING AS ROOT/SUDO, DO NOT USE SUDO ⚠#{creset}"
puts " ! VVV has detected that the VM has not been created yet, and is running as root/sudo."
puts " ! Do not use sudo with VVV, do not run VVV as a root user. Aborting."
abort( "Aborting Vagrant command to prevent a critical mistake, do not use sudo/root with VVV." )
end
end
end
v.customize ['modifyvm', :id, '--uartmode1', 'file', File.join(vagrant_dir, 'log/ubuntu-cloudimg-console.log')]
v.customize ['modifyvm', :id, '--memory', vvv_config['vm_config']['memory']]
v.customize ['modifyvm', :id, '--cpus', vvv_config['vm_config']['cores']]
v.customize ['modifyvm', :id, '--natdnshostresolver1', 'on']
v.customize ['modifyvm', :id, '--natdnsproxy1', 'on']
# see https://github.com/hashicorp/vagrant/issues/7648
v.customize ['modifyvm', :id, '--cableconnected1', 'on']
v.customize ['modifyvm', :id, '--rtcuseutc', 'on']
v.customize ['modifyvm', :id, '--audio', 'none']
v.customize ['modifyvm', :id, '--paravirtprovider', 'kvm']
# https://github.com/laravel/homestead/pull/63
v.customize ['modifyvm', :id, '--ostype', 'Ubuntu_64']
v.customize ['setextradata', :id, 'VBoxInternal2/SharedFoldersEnableSymlinksCreate//srv/www', '1']
v.customize ['setextradata', :id, 'VBoxInternal2/SharedFoldersEnableSymlinksCreate//srv/config', '1']
# Set the box name in VirtualBox to match the working directory.
v.name = File.basename(vagrant_dir) + '_' + (Digest::SHA256.hexdigest vagrant_dir)[0..10]
end
# Configuration options for the Parallels provider.
config.vm.provider :parallels do |v|
v.customize ['set', :id, '--longer-battery-life', 'off']
v.memory = vvv_config['vm_config']['memory']
v.cpus = vvv_config['vm_config']['cores']
end
# Configuration options for the VMware Desktop provider.
config.vm.provider :vmware_desktop do |v|
v.vmx['memsize'] = vvv_config['vm_config']['memory']
v.vmx['numvcpus'] = vvv_config['vm_config']['cores']
end
# Configuration options for Hyper-V provider.
config.vm.provider :hyperv do |v|
v.memory = vvv_config['vm_config']['memory']
v.cpus = vvv_config['vm_config']['cores']
v.linked_clone = true
end
# Auto Download Vagrant plugins, supported from Vagrant 2.2.0
unless Vagrant.has_plugin?('vagrant-hostsupdater') && Vagrant.has_plugin?('vagrant-goodhosts') && Vagrant.has_plugin?('vagrant-hostsmanager')
if File.file?(File.join(vagrant_dir, 'vagrant-goodhosts.gem'))
system('vagrant plugin install ' + File.join(vagrant_dir, 'vagrant-goodhosts.gem'))
File.delete(File.join(vagrant_dir, 'vagrant-goodhosts.gem'))
puts "#{yellow}VVV needed to install the vagrant-goodhosts plugin which is now installed. Please run the requested command again.#{creset}"
exit
else
config.vagrant.plugins = ['vagrant-goodhosts']
end
end
# The vbguest plugin has issues for some users, so we're going to disable it for now
config.vbguest.auto_update = false if Vagrant.has_plugin?('vagrant-vbguest')
# SSH Agent Forwarding
#
# Enable agent forwarding on vagrant ssh commands. This allows you to use ssh keys
# on your host machine inside the guest. See the manual for `ssh-add`.
config.ssh.forward_agent = true
# SSH Key Insertion
#
# This is disabled, we had several contributors who ran into issues.
# See: https://github.com/Varying-Vagrant-Vagrants/VVV/issues/1551
config.ssh.insert_key = false
config.vm.box_check_update = false
# The Parallels Provider uses a different naming scheme.
config.vm.provider :parallels do |_v, override|
override.vm.box = 'bento/ubuntu-20.04'
# Vagrant currently runs under Rosetta on M1 devices. As a result,
# this seems to be the most reliable way to detect whether or not we're
# running under ARM64.
if Etc.uname[:version].include? 'ARM64'
override.vm.box = 'bento/ubuntu-20.04-arm64'
end
end
# The VMware Desktop Provider uses a different naming scheme.
config.vm.provider :vmware_desktop do |v, override|
override.vm.box = 'bento/ubuntu-20.04'
v.gui = false
end
# Hyper-V uses a different base box.
config.vm.provider :hyperv do |_v, override|
override.vm.box = 'bento/ubuntu-20.04'
end
# Docker use image.
config.vm.provider :docker do |d, override|
d.image = 'pentatonicfunk/vagrant-ubuntu-base-images:20.04'
d.has_ssh = true
d.ports = [ "80:80" ] # HTTP
d.ports += [ "443:443" ] # HTTPS
d.ports += [ "3306:3306" ] # MySQL
d.ports += [ "8025:8025" ] # Mailhog
## Fix goodhosts aliases format for docker
override.goodhosts.aliases = { '127.0.0.1' => vvv_config['hosts'], '::1' => vvv_config['hosts'] }
end
# Virtualbox.
config.vm.provider :virtualbox do |_v, override|
# Default Ubuntu Box
#
# This box is provided by Bento boxes via vagrantcloud.com and is a nicely sized
# box containing the Ubuntu 20.04 Focal 64 bit release. Once this box is downloaded
# to your host computer, it is cached for future use under the specified box name.
override.vm.box = 'bento/ubuntu-20.04'
# If we're at a contributor day, switch the base box to the prebuilt one
if defined? vvv_config['vm_config']['wordcamp_contributor_day_box']
if vvv_config['vm_config']['wordcamp_contributor_day_box'] == true
override.vm.box = 'vvv/contribute'
end
end
end
if defined? vvv_config['vm_config']['box']
unless vvv_config['vm_config']['box'].nil?
config.vm.box = vvv_config['vm_config']['box']
end
end
config.vm.hostname = 'vvv'
# Specify disk size
#
# If the Vagrant plugin disksize (https://github.com/sprotheroe/vagrant-disksize) is
# installed, the following will automatically configure your local machine's disk size
# to be the specified size. This plugin only works on VirtualBox.
#
# Warning: This plugin only resizes up, not down, so don't set this to less than 10GB,
# and if you need to downsize, be sure to destroy and reprovision.
#
if !vvv_config['vagrant-plugins']['disksize'].nil? && defined?(Vagrant::Disksize)
config.vm.provider :virtualbox do |_v, override|
override.disksize.size = vvv_config['vagrant-plugins']['disksize']
end
if Etc.uname[:version].include? 'ARM64'
puts "WARNING: Vagrant disksize requires VirtualBox and is incompatible with Arm devices, uninstall immediatley"
end
end
# Private Network (default)
#
# A private network is created by default. This is the IP address through which your
# host machine will communicate to the guest. In this default configuration, the virtual
# machine will have an IP address of 192.168.56.4 and a virtual network adapter will be
# created on your host machine with the IP of 192.168.50.1 as a gateway.
#
# Access to the guest machine is only available to your local host. To provide access to
# other devices, a public network should be configured or port forwarding enabled.
#
# Note: If your existing network is using the 192.168.56.x subnet, this default IP address
# should be changed. If more than one VM is running through VirtualBox, including other
# Vagrant machines, different subnets should be used for each.
#
config.vm.network :private_network, id: 'vvv_primary', ip: vvv_config['vm_config']['private_network_ip']
config.vm.provider :hyperv do |_v, override|
override.vm.network :private_network, id: 'vvv_primary', ip: nil
end
# Public Network (disabled)
#
# Using a public network rather than the default private network configuration will allow
# access to the guest machine from other devices on the network. By default, enabling this
# line will cause the guest machine to use DHCP to determine its IP address. You will also
# be prompted to choose a network interface to bridge with during `vagrant up`.
#
# Please see VVV and Vagrant documentation for additional details.
#
# config.vm.network :public_network
# Port Forwarding (disabled)
#
# This network configuration works alongside any other network configuration in Vagrantfile
# and forwards any requests to port 8080 on the local host machine to port 80 in the guest.
#
# Port forwarding is a first step to allowing access to outside networks, though additional
# configuration will likely be necessary on our host machine or router so that outside
# requests will be forwarded from 80 -> 8080 -> 80.
#
# Please see VVV and Vagrant documentation for additional details.
#
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Drive mapping
#
# The following config.vm.synced_folder settings will map directories in your Vagrant
# virtual machine to directories on your local machine. Once these are mapped, any
# changes made to the files in these directories will affect both the local and virtual
# machine versions. Think of it as two different ways to access the same file. When the
# virtual machine is destroyed with `vagrant destroy`, your files will remain in your local
# environment.
# Disable the default synced folder to avoid overlapping mounts
config.vm.synced_folder '.', '/vagrant', disabled: true
config.vm.provision 'file', source: "#{vagrant_dir}/version", destination: '/home/vagrant/version'
# /srv/database/
#
# If a database directory exists in the same directory as your Vagrantfile,
# a mapped directory inside the VM will be created that contains these files.
# This directory is used to maintain default database scripts as well as backed
# up MariaDB/MySQL dumps (SQL files) that are to be imported automatically on vagrant up
config.vm.synced_folder 'database/sql/', '/srv/database'
use_db_share = false
if defined? vvv_config['general']['db_share_type']
use_db_share = vvv_config['general']['db_share_type'] == true
end
if use_db_share == true
# Map the MySQL Data folders on to mounted folders so it isn't stored inside the VM
config.vm.synced_folder 'database/data/', '/var/lib/mysql', create: true, owner: 9001, group: 9001, mount_options: ['dmode=775', 'fmode=664']
# The Parallels Provider does not understand "dmode"/"fmode" in the "mount_options" as
# those are specific to Virtualbox. The folder is therefore overridden with one that
# uses corresponding Parallels mount options.
config.vm.provider :parallels do |_v, override|
override.vm.synced_folder 'database/data/', '/var/lib/mysql', create: true, owner: 9001, group: 9001, mount_options: [ 'share' ]
end
# Neither does the HyperV provider
config.vm.provider :hyperv do |_v, override|
override.vm.synced_folder 'database/data/', '/var/lib/mysql', create: true, owner: 9001, group: 9001, mount_options: ['dir_mode=0775', 'file_mode=0664']
end
end
# /srv/config/
#
# If a server-conf directory exists in the same directory as your Vagrantfile,
# a mapped directory inside the VM will be created that contains these files.
# This directory is currently used to maintain various config files for php and
# nginx as well as any pre-existing database files.
config.vm.synced_folder 'config/', '/srv/config'
# /srv/config/
#
# Map the provision folder so that extensions and provisioners can access helper scripts
config.vm.synced_folder 'provision/', '/srv/provision'
# /srv/certificates
#
# This is a location for the TLS certificates to be accessible inside the VM
config.vm.synced_folder 'certificates/', '/srv/certificates', create: true
# /var/log/
#
# If a log directory exists in the same directory as your Vagrantfile, a mapped
# directory inside the VM will be created for some generated log files.
config.vm.synced_folder 'log/memcached', '/var/log/memcached', owner: 'root', create: true, group: 'root', mount_options: ['dmode=777', 'fmode=666']
config.vm.synced_folder 'log/nginx', '/var/log/nginx', owner: 'root', create: true, group: 'root', mount_options: ['dmode=777', 'fmode=666']
config.vm.synced_folder 'log/php', '/var/log/php', create: true, owner: 'root', group: 'root', mount_options: ['dmode=777', 'fmode=666']
config.vm.synced_folder 'log/provisioners', '/var/log/provisioners', create: true, owner: 'root', group: 'root', mount_options: ['dmode=777', 'fmode=666']
# /srv/www/
#
# If a www directory exists in the same directory as your Vagrantfile, a mapped directory
# inside the VM will be created that acts as the default location for nginx sites. Put all
# of your project files here that you want to access through the web server
config.vm.synced_folder 'www/', '/srv/www', owner: 'vagrant', group: 'www-data', mount_options: ['dmode=775', 'fmode=774']
vvv_config['sites'].each do |site, args|
next if args['skip_provisioning']
if args['local_dir'] != File.join(vagrant_dir, 'www', site)
config.vm.synced_folder args['local_dir'], args['vm_dir'], owner: 'vagrant', group: 'www-data', mount_options: ['dmode=775', 'fmode=774']
end
end
# The Parallels Provider does not understand "dmode"/"fmode" in the "mount_options" as
# those are specific to Virtualbox. The folder is therefore overridden with one that
# uses corresponding Parallels mount options.
config.vm.provider :parallels do |_v, override|
override.vm.synced_folder 'www/', '/srv/www', owner: 'vagrant', group: 'www-data', mount_options: [ 'share' ]
override.vm.synced_folder 'log/memcached', '/var/log/memcached', owner: 'root', create: true, group: 'root', mount_options: [ 'share' ]
override.vm.synced_folder 'log/nginx', '/var/log/nginx', owner: 'root', create: true, group: 'root', mount_options: [ 'share' ]
override.vm.synced_folder 'log/php', '/var/log/php', create: true, owner: 'root', group: 'root', mount_options: [ 'share' ]
override.vm.synced_folder 'log/provisioners', '/var/log/provisioners', create: true, owner: 'root', group: 'root', mount_options: [ 'share' ]
if use_db_share == true
# Map the MySQL Data folders on to mounted folders so it isn't stored inside the VM
override.vm.synced_folder 'database/data/', '/var/lib/mysql', create: true, owner: 112, group: 115, mount_options: [ 'share' ]
end
vvv_config['sites'].each do |site, args|
next if args['skip_provisioning']
if args['local_dir'] != File.join(vagrant_dir, 'www', site)
override.vm.synced_folder args['local_dir'], args['vm_dir'], owner: 'vagrant', group: 'www-data', mount_options: [ 'share' ]
end
end
end
# The Hyper-V Provider does not understand "dmode"/"fmode" in the "mount_options" as
# those are specific to Virtualbox. Furthermore, the normal shared folders need to be
# replaced with SMB shares. Here we switch all the shared folders to us SMB and then
# override the www folder with options that make it Hyper-V compatible.
config.vm.provider :hyperv do |v, override|
v.vmname = File.basename(vagrant_dir) + '_' + (Digest::SHA256.hexdigest vagrant_dir)[0..10]
override.vm.synced_folder 'www/', '/srv/www', owner: 'vagrant', group: 'www-data', mount_options: ['dir_mode=0775', 'file_mode=0774']
if use_db_share == true
# Map the MySQL Data folders on to mounted folders so it isn't stored inside the VM
override.vm.synced_folder 'database/data/', '/var/lib/mysql', create: true, owner: 112, group: 115, mount_options: ['dir_mode=0775', 'file_mode=0664']
end
override.vm.synced_folder 'log/memcached', '/var/log/memcached', owner: 'root', create: true, group: 'root', mount_options: ['dir_mode=0777', 'file_mode=0666']
override.vm.synced_folder 'log/nginx', '/var/log/nginx', owner: 'root', create: true, group: 'root', mount_options: ['dir_mode=0777', 'file_mode=0666']
override.vm.synced_folder 'log/php', '/var/log/php', create: true, owner: 'root', group: 'root', mount_options: ['dir_mode=0777', 'file_mode=0666']
override.vm.synced_folder 'log/provisioners', '/var/log/provisioners', create: true, owner: 'root', group: 'root', mount_options: ['dir_mode=0777', 'file_mode=0666']
vvv_config['sites'].each do |site, args|
next if args['skip_provisioning']
if args['local_dir'] != File.join(vagrant_dir, 'www', site)
override.vm.synced_folder args['local_dir'], args['vm_dir'], owner: 'vagrant', group: 'www-data', mount_options: ['dir_mode=0775', 'file_mode=0774']
end
end
end
# The VMware Provider does not understand "dmode"/"fmode" in the "mount_options" as
# those are specific to Virtualbox. The folder is therefore overridden with one that
# uses corresponding VMware mount options.
config.vm.provider :vmware_desktop do |_v, override|
override.vm.synced_folder 'www/', '/srv/www', owner: 'vagrant', group: 'www-data', mount_options: ['umask=002']
override.vm.synced_folder 'log/memcached', '/var/log/memcached', owner: 'root', create: true, group: 'root', mount_options: ['umask=000']
override.vm.synced_folder 'log/nginx', '/var/log/nginx', owner: 'root', create: true, group: 'root', mount_options: ['umask=000']
override.vm.synced_folder 'log/php', '/var/log/php', create: true, owner: 'root', group: 'root', mount_options: ['umask=000']
override.vm.synced_folder 'log/provisioners', '/var/log/provisioners', create: true, owner: 'root', group: 'root', mount_options: ['umask=000']
if use_db_share == true
# Map the MySQL Data folders on to mounted folders so it isn't stored inside the VM
override.vm.synced_folder 'database/data/', '/var/lib/mysql', create: true, owner: 112, group: 115, mount_options: ['umask=000']
end
vvv_config['sites'].each do |site, args|
next if args['skip_provisioning']
if args['local_dir'] != File.join(vagrant_dir, 'www', site)
override.vm.synced_folder args['local_dir'], args['vm_dir'], owner: 'vagrant', group: 'www-data', mount_options: ['umask=002']
end
end
end
# Customfile - POSSIBLY UNSTABLE
#
# Use this to insert your own additional Vagrant config lines. Helpful
# for mapping additional drives. If a file 'Customfile' exists in the same directory
# as this Vagrantfile, it will be evaluated as ruby inline as it loads.
#
# Note that if you find yourself using a Customfile for anything crazy or specifying
# different provisioning, then you may want to consider a new Vagrantfile entirely.
if File.exist?(File.join(vagrant_dir, 'Customfile'))
puts " ⚠ ! Running additional Vagrant code in Customfile located at #{File.join(vagrant_dir, 'Customfile')}\n"
puts " ⚠ ! Official support is not provided for this feature, it is assumed you are proficient with vagrant\n\n"
eval(IO.read(File.join(vagrant_dir, 'Customfile')), binding)
puts " ⚠ ! Finished running Customfile, resuming normal vagrantfile execution\n\n"
end
vvv_config['sites'].each do |site, args|
next unless args['allow_customfile']
paths = Dir[File.join(args['local_dir'], '**', 'Customfile')]
paths.each do |file|
puts " ⚠ ! Running additional site customfile at #{file}\n"
puts " ⚠ ! Official support is not provided for this feature.\n\n"
eval(IO.read(file), binding)
puts " ⚠ ! Finished running Customfile, resuming normal vagrantfile execution\n\n"
end
end
# Provisioning
#
# Process one or more provisioning scripts depending on the existence of custom files.
unless Vagrant::Util::Platform.windows?
if Process.uid == 0
# the VM should know if vagrant was ran by a root user or using sudo
config.vm.provision "flag-root-vagrant-command", type: 'shell', keep_color: true, inline: "mkdir -p /vagrant && touch /vagrant/provisioned_as_root"
end
end
long_provision_bear = <<~HTML
#{blue}#{creset}
#{blue} ▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄ ▄ ▄ #{green}A full provision will take a bit.#{creset}
#{blue} █▒▒░░░░░░░░░▒▒█ █ █ #{green}Sit back, relax, and have some tea.#{creset}
#{blue} █░░█░░░░░█░░█ ▀ ▀ #{creset}
#{blue} ▄▄ █░░░▀█▀░░░█ █▀▀▀▀▀▀█ #{green}If you didn't want to provision you can#{creset}
#{blue} █░░█ ▀▄░░░░░░░▄▀▄▀▀█ █ #{green}turn VVV on with 'vagrant up'.#{creset}
#{blue}───────────────────────────────────────────────────────────────────────#{creset}
HTML
# Changed the message here because it's going to show the first time you do vagrant up, which might be confusing
config.vm.provision "pre-provision-script", type: 'shell', keep_color: true, inline: "echo \"#{long_provision_bear}\""
# provison-pre.sh acts as a pre-hook to our default provisioning script. Anything that
# should run before the shell commands laid out in provision.sh (or your provision-custom.sh
# file) should go in this script. If it does not exist, no extra provisioning will run.
if File.exist?(File.join(vagrant_dir, 'provision', 'provision-pre.sh'))
config.vm.provision 'pre', type: 'shell', keep_color: true, path: File.join('provision', 'provision-pre.sh'), env: { "VVV_LOG" => "pre" }
end
# provision.sh or provision-custom.sh
#
# By default, Vagrantfile is set to use the provision.sh bash script located in the
# provision directory. If it is detected that a provision-custom.sh script has been
# created, that is run as a replacement. This is an opportunity to replace the entirety
# of the provisioning provided by default.
if File.exist?(File.join(vagrant_dir, 'provision', 'provision-custom.sh'))
config.vm.provision 'custom', type: 'shell', keep_color: true, path: File.join('provision', 'provision-custom.sh'), env: { "VVV_LOG" => "main-custom" }
else
config.vm.provision 'default', type: 'shell', keep_color: true, path: File.join('provision', 'provision.sh'), env: { "VVV_LOG" => "main" }
end
config.vm.provision 'tools', type: 'shell', keep_color: true, path: File.join('provision', 'provision-tools.sh'), env: { "VVV_LOG" => "tools" }
# Provision the dashboard that appears when you visit vvv.test
config.vm.provision 'dashboard',
type: 'shell',
keep_color: true,
path: File.join('provision', 'provision-dashboard.sh'),
args: [
vvv_config['dashboard']['repo'],
vvv_config['dashboard']['branch']
],
env: { "VVV_LOG" => "dashboard" }
vvv_config['utility-sources'].each do |name, args|
config.vm.provision "extension-source-#{name}",
type: 'shell',
keep_color: true,
path: File.join('provision', 'provision-extension-source.sh'),
args: [
name,
args['repo'].to_s,
args['branch']
],
env: { "VVV_LOG" => "extension-source-#{name}" }
end
vvv_config['extension-sources'].each do |name, args|
config.vm.provision "extension-source-#{name}",
type: 'shell',
keep_color: true,
path: File.join('provision', 'provision-extension-source.sh'),
args: [
name,
args['repo'].to_s,
args['branch']
],
env: { "VVV_LOG" => "extension-source-#{name}" }
end
vvv_config['utilities'].each do |name, extensions|
extensions = {} unless extensions.is_a? Array
extensions.each do |extension|
config.vm.provision "extension-#{name}-#{extension}",
type: 'shell',
keep_color: true,
path: File.join('provision', 'provision-extension.sh'),
args: [
name,
extension
],
env: { "VVV_LOG" => "extension-#{name}-#{extension}" }
end
end
vvv_config['extensions'].each do |name, extensions|
extensions = {} unless extensions.is_a? Array
extensions.each do |extension|
config.vm.provision "extension-#{name}-#{extension}",
type: 'shell',
keep_color: true,
path: File.join('provision', 'provision-extension.sh'),
args: [
name,
extension
],
env: { "VVV_LOG" => "extension-#{name}-#{extension}" }
end
end
vvv_config['sites'].each do |site, args|
next if args['skip_provisioning']
config.vm.provision "site-#{site}",
type: 'shell',
keep_color: true,
path: File.join('provision', 'provision-site.sh'),
args: [
site,
args['repo'].to_s,
args['branch'],
args['vm_dir'],
args['skip_provisioning'].to_s,
args['nginx_upstream']
],
env: { "VVV_LOG" => "site-#{site}" }
end
# provision-post.sh acts as a post-hook to the default provisioning. Anything that should
# run after the shell commands laid out in provision.sh or provision-custom.sh should be
# put into this file. This provides a good opportunity to install additional packages
# without having to replace the entire default provisioning script.
if File.exist?(File.join(vagrant_dir, 'provision', 'provision-post.sh'))
config.vm.provision 'post', type: 'shell', keep_color: true, path: File.join('provision', 'provision-post.sh'), env: { "VVV_LOG" => "post" }
end
config.vm.provision "post-provision-script", type: 'shell', keep_color: true, path: File.join( 'config/homebin', 'vagrant_provision' ), env: { "VVV_LOG" => "post-provision-script" }
# Local Machine Hosts
#
# If the Vagrant plugin goodhosts (https://github.com/goodhosts/vagrant/) is
# installed, the following will automatically configure your local machine's hosts file to
# be aware of the domains specified below. Watch the provisioning script as you may need to
# enter a password for Vagrant to access your hosts file.
#
# By default, we'll include the domains set up by VVV through the vvv-hosts file
# located in the www/ directory and in config/config.yml.
#
if config.vagrant.plugins.include? 'vagrant-goodhosts'
config.goodhosts.aliases = vvv_config['hosts']
config.goodhosts.remove_on_suspend = true
# goodhosts already disables clean by default, but lets enforce this at both ends
config.goodhosts.disable_clean = true
elsif config.vagrant.plugins.include? 'vagrant-hostsmanager'
config.hostmanager.aliases = vvv_config['hosts']
config.hostmanager.enabled = true
config.hostmanager.manage_host = true
config.hostmanager.manage_guest = true
config.hostmanager.ignore_private_ip = false
config.hostmanager.include_offline = true
elsif config.vagrant.plugins.include? 'vagrant-hostsupdater'
# Pass the found host names to the hostsupdater plugin so it can perform magic.
config.hostsupdater.aliases = vvv_config['hosts']
config.hostsupdater.remove_on_suspend = true
elsif %w[up halt resume suspend status provision reload].include? ARGV[0]
puts ""
puts " X ! There is no hosts file vagrant plugin installed!"
puts " X You need the vagrant-goodhosts plugin (or HostManager/ HostsUpdater ) for domains to work in the browser"
puts " X Run 'vagrant plugin install --local' to fix this."
puts ""
end
# Vagrant Triggers
#
# We run various scripts on Vagrant state changes like `vagrant up`, `vagrant halt`,
# `vagrant suspend`, and `vagrant destroy`
#
# These scripts are run on the host machine, so we use `vagrant ssh` to tunnel back
# into the VM and execute things. By default, each of these scripts calls db_backup
# to create backups of all current databases. This can be overridden with custom
# scripting. See the individual files in config/homebin/ for details.
unless Vagrant::Util::Platform.windows?
if Process.uid == 0
config.trigger.after :all do |trigger|
trigger.name = 'Do not use sudo'
trigger.ruby do |env,machine|
sudo_warnings
end
end
end
end
config.trigger.after :up do |trigger|
trigger.name = 'VVV Post-Up'
trigger.run_remote = { inline: '/srv/config/homebin/vagrant_up' }
trigger.on_error = :continue
end
config.trigger.before :reload do |trigger|
trigger.name = 'VVV Pre-Reload'
trigger.run_remote = { inline: '/srv/config/homebin/vagrant_halt' }
trigger.on_error = :continue
end
config.trigger.after :reload do |trigger|
trigger.name = 'VVV Post-Reload'
trigger.run_remote = { inline: '/srv/config/homebin/vagrant_up' }
trigger.on_error = :continue
end
config.trigger.before :halt do |trigger|
trigger.name = 'VVV Pre-Halt'
trigger.run_remote = { inline: '/srv/config/homebin/vagrant_halt' }
trigger.on_error = :continue
end
config.trigger.before :suspend do |trigger|
trigger.name = 'VVV Pre-Suspend'
trigger.run_remote = { inline: '/srv/config/homebin/vagrant_suspend' }
trigger.on_error = :continue
end
config.trigger.before :destroy do |trigger|
trigger.name = 'VVV Pre-Destroy'
trigger.run_remote = { inline: '/srv/config/homebin/vagrant_destroy' }
trigger.on_error = :continue
end
end
Always start with a minimal Vagrantfile and include only the relevant configuration to reproduce the reported behavior.
WIP
I removed a number of unused unrelated containers, restarted the docker engine, and ran docker network prune, with no improvement.
It looks like there's a network where config = Array(network["IPAM"]["Config"]) is nil though I couldn't identify its name from the debug output
it's the host network, I dumped the network object and saw this:
{"Name"=>"host", "Id"=>"6efa1ee2bb60fd235c4207460328b62568b0c9351b4ebab96597d75e028aadae", "Created"=>"2024-01-04T15:19:23.646989666Z", "Scope"=>"local", "Driver"=>"host", "EnableIPv6"=>false, "IPAM"=>{"Driver"=>"default", "Options"=>nil, "Config"=>nil}, "Internal"=>false, "Attachable"=>false, "Ingress"=>false, "ConfigFrom"=>{"Network"=>""}, "ConfigOnly"=>false, "Containers"=>{}, "Options"=>{}, "Labels"=>{}}
Changing the condition to this allowed the command to continue:
if (config && config.size > 0 &&
It looks like this was found here https://github.com/hashicorp/vagrant/issues/13339 and a similar fix was applied. I've kept my PR open as I believe the code it adds is more comprehensive and in line with the rest of the file, but glad to see 2.4.2 will resolve the issue
It was fixed with https://github.com/hashicorp/vagrant/issues/13339 but there was no stable release for the 3 mounts now. This really frustrates me cuz I'm forced to freeze the docker dependency and deal with internal user support that relies on this fix.