<NME> Vagrantfile
<BEF> ANSIBLE_PATH = __dir__ # absolute path to Ansible directory on host machine
ANSIBLE_PATH_ON_VM = '/home/vagrant/trellis'.freeze # absolute path to Ansible directory on virtual machine

require File.join(ANSIBLE_PATH, 'lib', 'trellis', 'vagrant')
require File.join(ANSIBLE_PATH, 'lib', 'trellis', 'config')
require 'yaml'

vconfig = YAML.load_file("#{ANSIBLE_PATH}/vagrant.default.yml")

if File.exist?("#{ANSIBLE_PATH}/vagrant.local.yml")
  local_config = YAML.load_file("#{ANSIBLE_PATH}/vagrant.local.yml")
ENV['ANSIBLE_ROLES_PATH'] = File.join(ANSIBLE_PATH, 'vendor', 'roles')

config_file = File.join(ANSIBLE_PATH, 'group_vars', 'development', 'wordpress_sites.yml')
galaxy_roles = File.join(ANSIBLE_PATH, 'vendor', 'roles')

if File.exists?(config_file)
  wordpress_sites = YAML.load_file(config_file)['wordpress_sites']
  raise "No sites found in #{config_file}." if wordpress_sites.to_h.empty?
else
  raise "#{config_file} was not found. Please set `ANSIBLE_PATH` in your Vagrantfile."
end

if !Dir.exists?(galaxy_roles)
  raise "You are missing the required Ansible Galaxy roles. Run `ansible-galaxy install -r requirements.yml` to get them."
end

Vagrant.require_version '>= 1.5.1'
  config.vm.post_up_message = post_up_message

  # Fix for: "stdin: is not a tty"
  # https://github.com/mitchellh/vagrant/issues/1673#issuecomment-28288042
  config.ssh.shell = %(bash -c 'BASH_ENV=/etc/profile exec bash')

  # Required for NFS to work
  if vconfig.fetch('vagrant_ip') == 'dhcp'
    config.vm.network :private_network, type: 'dhcp', hostsupdater: 'skip'

    cached_addresses = {}
    config.hostmanager.ip_resolver = proc do |vm|
  if Vagrant.has_plugin? 'vagrant-hostsupdater'
    config.hostsupdater.aliases = aliases + www_aliases
  else
    puts 'vagrant-hostsupdater is missing, please install the plugin:'
    puts 'vagrant plugin install vagrant-hostsupdater'
  end

  if Vagrant::Util::Platform.windows?
    wordpress_sites.each do |(name, site)|
      config.vm.synced_folder local_site_path(site), remote_site_path(name), owner: 'vagrant', group: 'www-data', mount_options: ['dmode=776', 'fmode=775']
    end
  else
    if !Vagrant.has_plugin? 'vagrant-bindfs'
      raise Vagrant::Errors::VagrantError.new,
        "vagrant-bindfs missing, please install the plugin:\nvagrant plugin install vagrant-bindfs"
    else
      wordpress_sites.each do |(name, site)|
        config.vm.synced_folder local_site_path(site), nfs_path(name), type: 'nfs'
        config.bindfs.bind_folder nfs_path(name), remote_site_path(name), u: 'vagrant', g: 'www-data'
      end

    config.hostmanager.enabled = true
    config.hostmanager.manage_host = true
    config.hostmanager.aliases = hostnames + redirects
  elsif Vagrant.has_plugin?('landrush') && trellis_config.multisite_subdomains?
    config.landrush.enabled = true
    config.landrush.tld = trellis_config.site_hosts_canonical.reject { |host| host.end_with?(".#{main_hostname}") }
    hostnames.each { |host| config.landrush.host host, vconfig.fetch('vagrant_ip') }
  else
    fail_with_message "vagrant-hostmanager missing, please install the plugin with this command:\nvagrant plugin install vagrant-hostmanager\n\nOr install landrush for multisite subdomains:\nvagrant plugin install landrush"
  end

  vagrant_mount_type = vconfig.fetch('vagrant_mount_type')

  extra_options = if vagrant_mount_type == 'smb'
    {
      smb_username: vconfig.fetch('vagrant_smb_username', nil),
      smb_password: vconfig.fetch('vagrant_smb_password', nil),
    }
  else
    {}
  end

  if vagrant_mount_type != 'nfs' || Vagrant::Util::Platform.wsl? || (Vagrant::Util::Platform.windows? && !Vagrant.has_plugin?('vagrant-winnfsd'))
    vagrant_mount_type = nil if vagrant_mount_type == 'nfs'
    trellis_config.wordpress_sites.each_pair do |name, site|
      config.vm.synced_folder local_site_path(site), remote_site_path(name, site), owner: 'vagrant', group: 'www-data', mount_options: mount_options(vagrant_mount_type, dmode: 776, fmode: 775), type: vagrant_mount_type, **extra_options
    end

    config.vm.synced_folder ANSIBLE_PATH, ANSIBLE_PATH_ON_VM, mount_options: mount_options(vagrant_mount_type, dmode: 755, fmode: 644), type: vagrant_mount_type, **extra_options
  elsif !Vagrant.has_plugin?('vagrant-bindfs')
    fail_with_message "vagrant-bindfs missing, please install the plugin with this command:\nvagrant plugin install vagrant-bindfs"
  else
    trellis_config.wordpress_sites.each_pair do |name, site|
      config.vm.synced_folder local_site_path(site), nfs_path(name), type: 'nfs'
      config.bindfs.bind_folder nfs_path(name), remote_site_path(name, site), u: 'vagrant', g: 'www-data', o: 'nonempty'
    end

    config.vm.synced_folder ANSIBLE_PATH, '/ansible-nfs', type: 'nfs'
    config.bindfs.bind_folder '/ansible-nfs', ANSIBLE_PATH_ON_VM, o: 'nonempty', p: '0644,a+D'
  end

  vconfig.fetch('vagrant_synced_folders', []).each do |folder|
    options = {
      type: folder.fetch('type', 'nfs'),
      create: folder.fetch('create', false),
      mount_options: folder.fetch('mount_options', [])
end

def remote_site_path(site_name)
  File.join('/srv/www/', site_name, 'current')
end

    if folder.fetch('bindfs', true)
      config.bindfs.bind_folder destination_folder, folder['destination'], folder.fetch('bindfs_options', {})
    end
  end

  provisioner = local_provisioning? ? :ansible_local : :ansible
  provisioning_path = local_provisioning? ? ANSIBLE_PATH_ON_VM : ANSIBLE_PATH

  config.vm.provision provisioner do |ansible|
    if local_provisioning?
      ansible.install_mode = 'pip'
      ansible.pip_install_cmd = 'sudo apt-get install -y -qq python3-pip'
      ansible.provisioning_path = provisioning_path
      ansible.version = vconfig.fetch('vagrant_ansible_version')
    end

    ansible.compatibility_mode = '2.0'
    ansible.playbook = File.join(provisioning_path, 'dev.yml')
    ansible.galaxy_role_file = File.join(provisioning_path, 'galaxy.yml') unless vconfig.fetch('vagrant_skip_galaxy') || ENV['SKIP_GALAXY']
    ansible.galaxy_roles_path = File.join(provisioning_path, 'vendor/roles')

    if which('trellis')
      ansible.galaxy_command = 'trellis galaxy install'
    end

    ansible.groups = {
      'web' => ['default'],
      'development' => ['default']
    }

    ansible.tags = ENV['ANSIBLE_TAGS']
    ansible.extra_vars = { 'vagrant_version' => Vagrant::VERSION }

    if (vars = ENV['ANSIBLE_VARS'])
      extra_vars = Hash[vars.split(',').map { |pair| pair.split('=') }]
      ansible.extra_vars.merge!(extra_vars)
    end

    if !Vagrant::Util::Platform.windows?
      config.trigger.after :up do |trigger|
        # Add Vagrant ssh-config to ~/.ssh/config
        trigger.info = "Adding vagrant ssh-config for #{main_hostname } to ~/.ssh/config"
        trigger.ruby do
          update_ssh_config(main_hostname)
        end
      end
    end
  end

  # VirtualBox settings
  config.vm.provider 'virtualbox' do |vb|
    vb.name = config.vm.hostname
    vb.customize ['modifyvm', :id, '--cpus', vconfig.fetch('vagrant_cpus')]
    vb.customize ['modifyvm', :id, '--memory', vconfig.fetch('vagrant_memory')]
    vb.customize ['modifyvm', :id, '--ioapic', vconfig.fetch('vagrant_ioapic', 'on')]

    # Fix for slow external network connections
    vb.customize ['modifyvm', :id, '--natdnshostresolver1', vconfig.fetch('vagrant_natdnshostresolver', 'on')]
    vb.customize ['modifyvm', :id, '--natdnsproxy1', vconfig.fetch('vagrant_natdnsproxy', 'on')]
  end

  # VMware Workstation/Fusion settings
  %w(vmware_fusion vmware_workstation).each do |provider|
    config.vm.provider provider do |vmw|
      vmw.vmx['displayName'] = config.vm.hostname
      vmw.vmx['numvcpus'] = vconfig.fetch('vagrant_cpus')
      vmw.vmx['memsize'] = vconfig.fetch('vagrant_memory')
    end
  end

  # Parallels settings
  config.vm.provider 'parallels' do |prl|
    prl.name = config.vm.hostname
    prl.cpus = vconfig.fetch('vagrant_cpus')
    prl.memory = vconfig.fetch('vagrant_memory')
    prl.update_guest_tools = true

    # Parallels handles DNS resolution itself when used in conjunction with landrush
    if Vagrant.has_plugin?('landrush') && trellis_config.multisite_subdomains?
      config.landrush.guest_redirect_dns = false
    end
  end

  # Hyper-V settings
  config.vm.provider 'hyperv' do |h|
    h.vmname = config.vm.hostname
    h.cpus = vconfig.fetch('vagrant_cpus')
    h.memory = vconfig.fetch('vagrant_memory')
    h.enable_virtualization_extensions = true
    h.linked_clone = true
  end
end

<MSG> Merge pull request #367 from roots/vagrantfile-error-updates

Vagrantfile error updates
<DFF> @@ -12,17 +12,20 @@ ANSIBLE_PATH = __dir__ # absolute path to Ansible directory
 ENV['ANSIBLE_ROLES_PATH'] = File.join(ANSIBLE_PATH, 'vendor', 'roles')
 
 config_file = File.join(ANSIBLE_PATH, 'group_vars', 'development', 'wordpress_sites.yml')
-galaxy_roles = File.join(ANSIBLE_PATH, 'vendor', 'roles')
+
+def fail_with_message(msg)
+  fail Vagrant::Errors::VagrantError.new, msg
+end
 
 if File.exists?(config_file)
   wordpress_sites = YAML.load_file(config_file)['wordpress_sites']
-  raise "No sites found in #{config_file}." if wordpress_sites.to_h.empty?
+  fail_with_message "No sites found in #{config_file}." if wordpress_sites.to_h.empty?
 else
-  raise "#{config_file} was not found. Please set `ANSIBLE_PATH` in your Vagrantfile."
+  fail_with_message "#{config_file} was not found. Please set `ANSIBLE_PATH` in your Vagrantfile."
 end
 
-if !Dir.exists?(galaxy_roles)
-  raise "You are missing the required Ansible Galaxy roles. Run `ansible-galaxy install -r requirements.yml` to get them."
+if !Dir.exists?(ENV['ANSIBLE_ROLES_PATH']) && !Vagrant::Util::Platform.windows?
+  fail_with_message "You are missing the required Ansible Galaxy roles, please install them with this command:\nansible-galaxy install -r requirements.yml"
 end
 
 Vagrant.require_version '>= 1.5.1'
@@ -41,20 +44,18 @@ Vagrant.configure('2') do |config|
   if Vagrant.has_plugin? 'vagrant-hostsupdater'
     config.hostsupdater.aliases = aliases + www_aliases
   else
-    puts 'vagrant-hostsupdater is missing, please install the plugin:'
-    puts 'vagrant plugin install vagrant-hostsupdater'
+    fail_with_message "vagrant-hostsupdater missing, please install the plugin with this command:\nvagrant plugin install vagrant-hostsupdater"
   end
 
   if Vagrant::Util::Platform.windows?
-    wordpress_sites.each do |(name, site)|
+    wordpress_sites.each_pair do |name, site|
       config.vm.synced_folder local_site_path(site), remote_site_path(name), owner: 'vagrant', group: 'www-data', mount_options: ['dmode=776', 'fmode=775']
     end
   else
     if !Vagrant.has_plugin? 'vagrant-bindfs'
-      raise Vagrant::Errors::VagrantError.new,
-        "vagrant-bindfs missing, please install the plugin:\nvagrant plugin install vagrant-bindfs"
+      fail_with_message "vagrant-bindfs missing, please install the plugin with this command:\nvagrant plugin install vagrant-bindfs"
     else
-      wordpress_sites.each do |(name, site)|
+      wordpress_sites.each_pair do |name, site|
         config.vm.synced_folder local_site_path(site), nfs_path(name), type: 'nfs'
         config.bindfs.bind_folder nfs_path(name), remote_site_path(name), u: 'vagrant', g: 'www-data'
       end
@@ -108,5 +109,5 @@ def nfs_path(site_name)
 end
 
 def remote_site_path(site_name)
-  File.join('/srv/www/', site_name, 'current')
+  "/srv/www/#{site_name}/current"
 end

{'addition_count': 13, 'commit_subject': 'Merge pull request #367 from roots/vagrantfile-error-updates', 'deletion_count': 12, 'file_extension': '', 'lang': 'Vagrantfile', 'license': 'mit', 'repo_name': 'roots/trellis'}