Skip to content
This repository was archived by the owner on Feb 13, 2023. It is now read-only.

Vagrantfile cleanup #1332

Merged
merged 5 commits into from
Apr 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ script:
- '[[ ! -z "${local_config}" ]] && docker exec ${container_id} bash -c "cp ${DRUPALVM_DIR}/${local_config} ${config_dir:-$DRUPALVM_DIR}/local.config.yml" || true'

# Vagrantfile syntax check.
- 'rubocop ./Vagrantfile --except LineLength,Eval,MutableConstant,BlockLength'
- 'rubocop ./Vagrantfile ./lib/drupalvm --except LineLength,Eval,MutableConstant,BlockLength,ConditionalAssignment,IndentArray,AlignParameters'

# Ansible syntax check.
- 'docker exec --tty ${container_id} env TERM=xterm ansible-playbook ${DRUPALVM_DIR}/provisioning/playbook.yml --syntax-check'
Expand Down
135 changes: 35 additions & 100 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = '2' unless defined? VAGRANTFILE_API_VERSION
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see the point of defining this when it could technically be overridden by an earlier vagrant command.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1


require './lib/drupalvm/vagrant'

# Absolute paths on the host machine.
host_drupalvm_dir = File.dirname(File.expand_path(__FILE__))
Expand All @@ -14,58 +15,19 @@ guest_config_dir = ENV['DRUPALVM_CONFIG_DIR'] ? "/vagrant/#{ENV['DRUPALVM_CONFIG

drupalvm_env = ENV['DRUPALVM_ENV'] || 'vagrant'

# Cross-platform way of finding an executable in the $PATH.
def which(cmd)
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each do |ext|
exe = File.join(path, "#{cmd}#{ext}")
return exe if File.executable?(exe) && !File.directory?(exe)
end
end
nil
end

def get_ansible_version(exe)
/^[^\s]+ (.+)$/.match(`#{exe} --version`) { |match| return match[1] }
end

def walk(obj, &fn)
if obj.is_a?(Array)
obj.map { |value| walk(value, &fn) }
elsif obj.is_a?(Hash)
obj.each_pair { |key, value| obj[key] = walk(value, &fn) }
else
obj = yield(obj)
end
default_config_file = "#{host_drupalvm_dir}/default.config.yml"
unless File.exist?(default_config_file)
raise_message "Configuration file not found! Expected in #{default_config_file}"
end

require 'yaml'
# Load default VM configurations.
vconfig = YAML.load_file("#{host_drupalvm_dir}/default.config.yml")
# Use optional config.yml and local.config.yml for configuration overrides.
['config.yml', 'local.config.yml', "#{drupalvm_env}.config.yml"].each do |config_file|
if File.exist?("#{host_config_dir}/#{config_file}")
optional_config = YAML.load_file("#{host_config_dir}/#{config_file}")
vconfig.merge!(optional_config) if optional_config
end
end

# Replace jinja variables in config.
vconfig = walk(vconfig) do |value|
while value.is_a?(String) && value.match(/{{ .* }}/)
value = value.gsub(/{{ (.*?) }}/) { vconfig[Regexp.last_match(1)] }
end
value
end

Vagrant.require_version ">= #{vconfig['drupalvm_vagrant_version_min']}"

ansible_bin = which('ansible-playbook')
ansible_version = Gem::Version.new(get_ansible_version(ansible_bin)) if ansible_bin
ansible_version_min = Gem::Version.new(vconfig['drupalvm_ansible_version_min'])
vconfig = load_config([
default_config_file,
"#{host_config_dir}/config.yml",
"#{host_config_dir}/local.config.yml",
"#{host_config_dir}/#{drupalvm_env}.config.yml"
])

provisioner = ansible_bin && !vconfig['force_ansible_local'] ? :ansible : :ansible_local
provisioner = vconfig['force_ansible_local'] ? :ansible_local : vagrant_provisioner
if provisioner == :ansible
playbook = "#{host_drupalvm_dir}/provisioning/playbook.yml"
config_dir = host_config_dir
Expand All @@ -74,23 +36,23 @@ else
config_dir = guest_config_dir
end

if provisioner == :ansible && ansible_version < ansible_version_min
raise Vagrant::Errors::VagrantError.new, "You must update Ansible to at least #{ansible_version_min} to use this version of Drupal VM."
end
# Verify version requirements.
require_ansible_version ">= #{vconfig['drupalvm_ansible_version_min']}"
Vagrant.require_version ">= #{vconfig['drupalvm_vagrant_version_min']}"

Vagrant.configure('2') do |config|
# Set the name of the VM. See: http://stackoverflow.com/a/17864388/100134
config.vm.define vconfig['vagrant_machine_name']

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Networking configuration.
config.vm.hostname = vconfig['vagrant_hostname']
if vconfig['vagrant_ip'] == '0.0.0.0' && Vagrant.has_plugin?('vagrant-auto_network')
config.vm.network :private_network, ip: vconfig['vagrant_ip'], auto_network: true
else
config.vm.network :private_network, ip: vconfig['vagrant_ip']
end
config.vm.network :private_network,
ip: vconfig['vagrant_ip'],
auto_network: vconfig['vagrant_ip'] == '0.0.0.0' && Vagrant.has_plugin?('vagrant-auto_network')

if !vconfig['vagrant_public_ip'].empty? && vconfig['vagrant_public_ip'] == '0.0.0.0'
config.vm.network :public_network
elsif !vconfig['vagrant_public_ip'].empty?
config.vm.network :public_network, ip: vconfig['vagrant_public_ip']
unless vconfig['vagrant_public_ip'].empty?
config.vm.network :public_network,
ip: vconfig['vagrant_public_ip'] != '0.0.0.0' ? vconfig['vagrant_public_ip'] : nil
end

# SSH options.
Expand All @@ -100,32 +62,11 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Vagrant box.
config.vm.box = vconfig['vagrant_box']

if vconfig.include?('vagrant_post_up_message')
config.vm.post_up_message = vconfig['vagrant_post_up_message']
else
config.vm.post_up_message = 'Your Drupal VM Vagrant box is ready to use!'\
"\n* Visit the dashboard for an overview of your site: http://dashboard.#{vconfig['vagrant_hostname']} (or http://#{vconfig['vagrant_ip']})"\
"\n* You can SSH into your machine with `vagrant ssh`."\
"\n* Find out more in the Drupal VM documentation at http://docs.drupalvm.com"
end
# Display an introduction message after `vagrant up` and `vagrant provision`.
config.vm.post_up_message = vconfig.fetch('vagrant_post_up_message', get_default_post_up_message(vconfig))

# If a hostsfile manager plugin is installed, add all server names as aliases.
aliases = []
if vconfig['drupalvm_webserver'] == 'apache'
vconfig['apache_vhosts'].each do |host|
aliases.push(host['servername'])
aliases.concat(host['serveralias'].split) if host['serveralias']
end
else
vconfig['nginx_hosts'].each do |host|
aliases.concat(host['server_name'].split)
aliases.concat(host['server_name_redirect'].split) if host['server_name_redirect']
end
end
aliases = aliases.uniq - [config.vm.hostname, vconfig['vagrant_ip']]
# Remove wildcard subdomains.
aliases.delete_if { |vhost| vhost.include?('*') }

aliases = get_vhost_aliases(vconfig) - [config.vm.hostname]
if Vagrant.has_plugin?('vagrant-hostsupdater')
config.hostsupdater.aliases = aliases
elsif Vagrant.has_plugin?('vagrant-hostmanager')
Expand All @@ -137,20 +78,17 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Synced folders.
vconfig['vagrant_synced_folders'].each do |synced_folder|
options = {
type: synced_folder.include?('type') ? synced_folder['type'] : vconfig['vagrant_synced_folder_default_type'],
rsync__auto: 'true',
type: synced_folder.fetch('type', vconfig['vagrant_synced_folder_default_type']),
rsync__exclude: synced_folder['excluded_paths'],
rsync__args: ['--verbose', '--archive', '--delete', '-z', '--chmod=ugo=rwX'],
rsync__args: ['--verbose', '--archive', '--delete', '-z', '--copy-links', '--chmod=ugo=rwX'],
id: synced_folder['id'],
create: synced_folder.include?('create') ? synced_folder['create'] : false,
mount_options: synced_folder.include?('mount_options') ? synced_folder['mount_options'] : []
create: synced_folder.fetch('create', false),
mount_options: synced_folder.fetch('mount_options', [])
}
if synced_folder.include?('options_override')
synced_folder['options_override'].each do |key, value|
options[key.to_sym] = value
end
synced_folder.fetch('options_override', {}).each do |key, value|
options[key.to_sym] = value
end
config.vm.synced_folder synced_folder['local_path'], synced_folder['destination'], options
config.vm.synced_folder synced_folder.fetch('local_path'), synced_folder.fetch('destination'), options
end

# Allow override of the default synced folder type.
Expand Down Expand Up @@ -196,9 +134,6 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
p.update_guest_tools = true
end

# Set the name of the VM. See: http://stackoverflow.com/a/17864388/100134
config.vm.define vconfig['vagrant_machine_name']

# Cache packages and dependencies if vagrant-cachier plugin is present.
if Vagrant.has_plugin?('vagrant-cachier')
config.cache.scope = :box
Expand Down
111 changes: 111 additions & 0 deletions lib/drupalvm/vagrant.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
require 'yaml'

# Cross-platform way of finding an executable in the $PATH.
def which(cmd)
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each do |ext|
exe = File.join(path, "#{cmd}#{ext}")
return exe if File.executable?(exe) && !File.directory?(exe)
end
end
nil
end

# Recursively walk an tree and run provided block on each value found.
def walk(obj, &fn)
if obj.is_a?(Array)
obj.map { |value| walk(value, &fn) }
elsif obj.is_a?(Hash)
obj.each_pair { |key, value| obj[key] = walk(value, &fn) }
else
obj = yield(obj)
end
end

# Resolve jinja variables in hash.
def resolve_jinja_variables(vconfig)
walk(vconfig) do |value|
while value.is_a?(String) && value.match(/{{ .* }}/)
value = value.gsub(/{{ (.*?) }}/) { vconfig[Regexp.last_match(1)] }
end
value
end
end

# Return the combined configuration content all files provided.
def load_config(files)
vconfig = {}
files.each do |config_file|
if File.exist?(config_file)
optional_config = YAML.load_file(config_file)
vconfig.merge!(optional_config) if optional_config
end
end
resolve_jinja_variables(vconfig)
end

# Return the path to the ansible-playbook executable.
def ansible_bin
@ansible_bin ||= which('ansible-playbook')
end

# Return the ansible version parsed from running the executable path provided.
def ansible_version
/^[^\s]+ (.+)$/.match(`#{ansible_bin} --version`) { |match| return match[1] }
end

# Require that if installed, the ansible version meets the requirements.
def require_ansible_version(requirement)
return unless ansible_bin
req = Gem::Requirement.new(requirement)
return if req.satisfied_by?(Gem::Version.new(ansible_version))
raise_message "You must install an Ansible version #{requirement} to use this version of Drupal VM."
end

def raise_message(msg)
raise Vagrant::Errors::VagrantError.new, msg
end

# Return which Vagrant provisioner to use.
def vagrant_provisioner
ansible_bin ? :ansible : :ansible_local
end

def get_apache_vhosts(vhosts)
aliases = []
vhosts.each do |host|
aliases.push(host['servername'])
aliases.concat(host['serveralias'].split) if host['serveralias']
end
aliases
end

def get_nginx_vhosts(vhosts)
aliases = []
vhosts.each do |host|
aliases.push(host['server_name'])
aliases.concat(host['server_name_redirect'].split) if host['server_name_redirect']
end
aliases
end

# Return a list of all virtualhost server names and aliases from a config hash.
def get_vhost_aliases(vconfig)
if vconfig['drupalvm_webserver'] == 'apache'
aliases = get_apache_vhosts(vconfig['apache_vhosts'])
else
aliases = get_nginx_vhosts(vconfig['nginx_hosts'])
end
aliases = aliases.uniq - [vconfig['vagrant_ip']]
# Remove wildcard subdomains.
aliases.delete_if { |vhost| vhost.include?('*') }
end

# Return a default post_up_message.
def get_default_post_up_message(vconfig)
'Your Drupal VM Vagrant box is ready to use!'\
"\n* Visit the dashboard for an overview of your site: http://dashboard.#{vconfig['vagrant_hostname']} (or http://#{vconfig['vagrant_ip']})"\
"\n* You can SSH into your machine with `vagrant ssh`."\
"\n* Find out more in the Drupal VM documentation at http://docs.drupalvm.com"
end