This repository has been archived by the owner on Dec 1, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 41
/
Vagrantfile
354 lines (308 loc) · 14.3 KB
/
Vagrantfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# UI Object for console interactions.
@ui = Vagrant::UI::Colored.new
# Install required plugins if not present.
required_plugins = ["vagrant-triggers", "vagrant-gatling-rsync"]
required_plugins.each do |plugin|
need_restart = false
unless Vagrant.has_plugin? plugin
system "vagrant plugin install #{plugin}"
need_restart = true
end
exec "vagrant #{ARGV.join(' ')}" if need_restart
end
# Determine if we are on Windows host or not.
is_windows = Vagrant::Util::Platform.windows?
# Determine paths.
vagrant_root = File.dirname(__FILE__) # Vagrantfile location
if is_windows
vagrant_mount_point = `cygpath #{vagrant_root}`.strip! # Remove trailing \n
vagrant_mount_point = vagrant_mount_point.gsub(/\/cygdrive/, '') # Remove '/cygdrive' prefix
else
vagrant_mount_point = vagrant_root
end
vagrant_folder_name = File.basename(vagrant_root) # Folder name only. Used as the SMB share name.
# Use vagrant.yml for local VM configuration overrides.
require 'yaml'
if !File.exist?(vagrant_root + '/vagrant.yml')
@ui.error 'Configuration file not found! Please copy vagrant.yml.dist to vagrant.yml and try again.'
exit
end
$vconfig = YAML::load_file(vagrant_root + '/vagrant.yml')
if is_windows
require 'win32ole'
# Determine if Vagrant was launched from the elevated command prompt.
running_as_admin = ((`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil? && is_windows)
# Run command in an elevated shell.
def windows_elevated_shell(args)
command = 'cmd.exe'
args = "/C #{args} || timeout 10"
shell = WIN32OLE.new('Shell.Application')
shell.ShellExecute(command, args, nil, 'runas')
end
# Method to create the user and SMB network share on Windows.
def windows_net_share(share_name, path)
# Add the vagrant user if it does not exist.
smb_username = $vconfig['synced_folders']['smb_username']
smb_password = $vconfig['synced_folders']['smb_password']
command_user = "net user #{smb_username} || ( net user #{smb_username} #{smb_password} /add && WMIC USERACCOUNT WHERE \"Name='vagrant'\" SET PasswordExpires=FALSE )"
@ui.info "Adding vagrant user"
windows_elevated_shell command_user
# Add the SMB share if it does not exist.
command_share = "net share #{share_name} || net share #{share_name}=#{path} /grant:#{smb_username},FULL"
@ui.info "Adding vagrant SMB share"
windows_elevated_shell command_share
# Set folder permissions.
command_permissions = "icacls #{path} /grant #{smb_username}:(OI)(CI)M"
@ui.info "Setting folder permissions"
windows_elevated_shell command_permissions
end
# Method to remove the user and SMB network share on Windows.
def windows_net_share_remove(share_name)
smb_username = $vconfig['synced_folders']['smb_username']
command_user = "net user #{smb_username} /delete || echo 'User #{smb_username} does not exist' && timeout 10"
windows_elevated_shell command_user
command_share = "net share #{share_name} /delete || echo 'Share #{share_name} does not exist' && timeout 10"
windows_elevated_shell command_share
end
else
# Determine if Vagrant was launched with sudo (as root).
running_as_root = (Process.uid == 0)
end
# Vagrant should NOT be run as root/admin.
if running_as_root
# || running_as_admin
@ui.error "Vagrant should be run as a regular user to avoid issues."
exit
end
######################################################################
# Vagrant Box Configuration #
Vagrant.require_version ">= 1.8.5"
Vagrant.configure("2") do |config|
config.vm.define "boot2docker"
config.vm.box = "blinkreaction/boot2docker"
config.vm.box_version = "1.12.1"
config.vm.box_check_update = true
## Network ##
box_ip = $vconfig['ip']['primary'] # e.g. 192.168.10.10
host_ip = box_ip.gsub(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/, '\1.\2.\3.1') # e.g. 192.168.10.1
# Primary private network IP (default: 192.168.10.10)
# Using Intel PRO/1000 MT Desktop [82540EM] network adapter - shows slightly better performance compared to "virtio".
config.vm.network "private_network", ip: box_ip, nic_type: "82540EM"
# Addtional IP addresses (see vagrant.yml)
$vconfig['ip']['additional'].each do |private_ip|
config.vm.network "private_network", ip: private_ip, nic_type: "82540EM"
end unless $vconfig['ip']['additional'].nil?
####################################################################
## Synced folders configuration ##
synced_folders = $vconfig['synced_folders']
# nfs: Better performance on Mac
if synced_folders['type'] == "nfs" && !is_windows
@ui.success "Using nfs synced folder option"
config.vm.synced_folder vagrant_root, vagrant_mount_point,
type: "nfs",
mount_options: ["nolock", "vers=3", "tcp"]
config.nfs.map_uid = Process.uid
config.nfs.map_gid = Process.gid
# nfs2: Optimized NFS settings for even better performance on Mac, experimental
elsif ( synced_folders['type'] == "nfs2" || synced_folders['type'] == "default" ) && !is_windows
@ui.success "Using nfs2 synced folder option"
config.vm.synced_folder vagrant_root, vagrant_mount_point,
type: "nfs",
mount_options: ["nolock", "noacl", "nocto", "noatime", "nodiratime", "vers=3", "tcp", "actimeo=2"]
config.nfs.map_uid = Process.uid
config.nfs.map_gid = Process.gid
# smb: Better performance on Windows. Requires Vagrant to be run with admin privileges.
elsif synced_folders['type'] == "smb" && is_windows
@ui.success "Using smb synced folder option"
config.vm.synced_folder vagrant_root, vagrant_mount_point,
type: "smb",
smb_username: synced_folders['smb_username'],
smb_password: synced_folders['smb_password']
# smb2: Better performance on Windows. Does not require running vagrant as admin.
elsif ( synced_folders['type'] == "smb2" || synced_folders['type'] == "default" ) && is_windows
@ui.success "Using smb2 synced folder option"
if $vconfig['synced_folders']['smb2_auto']
# Create the share before 'up'.
config.trigger.before :up, :stdout => true, :force => true do
info 'Setting up SMB user and share'
windows_net_share vagrant_folder_name, vagrant_root
end
# Remove the share after 'halt'.
config.trigger.after :destroy, :stdout => true, :force => true do
info 'Removing SMB user and share'
windows_net_share_remove vagrant_folder_name
end
end
# Mount the share in boot2docker.
config.vm.provision "shell", run: "always" do |s|
s.inline = <<-SCRIPT
mkdir -p vagrant $2
mount -t cifs -o uid=`id -u docker`,gid=`id -g docker`,noperm,sec=ntlm,username=$3,pass=$4,dir_mode=0777,file_mode=0777 //$5/$1 $2
SCRIPT
s.args = "#{vagrant_folder_name} #{vagrant_mount_point} #{$vconfig['synced_folders']['smb_username']} #{$vconfig['synced_folders']['smb_password']} #{host_ip}"
end
# rsync: the best performance, cross-platform platform, one-way only.
elsif synced_folders['type'] == "rsync"
@ui.success "Using rsync synced folder option"
# Construct and array for rsync_exclude
rsync_exclude = []
unless synced_folders['rsync_exclude'].nil?
for item in synced_folders['rsync_exclude'] do
rsync_exclude.push(item)
end
end
# Only sync explicitly listed folders.
if synced_folders['rsync_folders'].nil?
@ui.error "ERROR: 'folders' list cannot be empty when using 'rsync' sync type. Please check your vagrant.yml file."
exit
else
for synced_folder in synced_folders['rsync_folders'] do
config.vm.synced_folder "#{vagrant_root}/#{synced_folder}", "#{vagrant_mount_point}/#{synced_folder}",
type: "rsync",
rsync__exclude: rsync_exclude,
rsync__args: ["--archive", "--delete", "--compress", "--whole-file"]
end
end
# Configure vagrant-gatling-rsync
config.gatling.rsync_on_startup = false
config.gatling.latency = synced_folders['rsync_latency']
config.gatling.time_format = "%H:%M:%S"
# Launch gatling-rsync-auto in the background
if synced_folders['rsync_auto'] && !is_windows
[:up, :reload, :resume].each do |trigger|
config.trigger.after trigger do
success "Starting background rsync-auto process..."
info "Run 'tail -f #{vagrant_root}/rsync.log' to see rsync-auto logs."
# Kill the old sync process
`kill $(pgrep -f rsync-auto) > /dev/null 2>&1 || true`
# Start a new sync process in background
`vagrant gatling-rsync-auto >> rsync.log &`
end
end
[:halt, :suspend, :destroy].each do |trigger|
config.trigger.before trigger do
# Kill rsync-auto process
success "Stopping background rsync-auto process..."
`kill $(pgrep -f rsync-auto) > /dev/null 2>&1 || true`
`rm -f rsync.log`
end
end
end
# vboxsf: reliable, cross-platform and terribly slow performance
elsif synced_folders['type'] == "vboxsf"
@ui.warn "WARNING: Using the SLOWEST folder sync option (vboxsf)"
config.vm.synced_folder vagrant_root, vagrant_mount_point
# Warn if neither synced_folder not individual_mounts is enabled
elsif synced_folders['individual_mounts'].nil?
@ui.error "ERROR: Synced folders not enabled or misconfigured. The VM will not have access to files on the host."
end
# Individual mounts
unless synced_folders['individual_mounts'].nil?
@ui.success "Using individual_mounts synced folder option"
for synced_folder in synced_folders['individual_mounts'] do
if synced_folder['type'] == 'vboxsf'
config.vm.synced_folder synced_folder['location'], synced_folder['mount'],
mount_options: [synced_folder['options']]
elsif synced_folder['type'] == 'nfs'
config.vm.synced_folder synced_folder['location'], synced_folder['mount'],
type: "nfs",
mount_options: [synced_folder['options']]
end
end
end
# Fix default vagrant share.
# TODO: test and remove once Vagrant v1.8.6 is out.
config.vm.synced_folder ".", "/vagrant", owner: 1000, group: 50
# Make host home directory available to containers in /.home
# TODO: test and remove hardcoded owner and group below once Vagrant v1.8.6 is out.
if File.directory?(File.expand_path("~"))
config.vm.synced_folder "~", "/.home", owner: 1000, group: 50
end
######################################################################
## VirtualBox VM settings.
config.vm.provider "virtualbox" do |v|
v.gui = $vconfig['v.gui'] # Set to true for debugging. Will unhide VM's primary console screen.
v.name = vagrant_folder_name + "_boot2docker" # VirtualBox VM name.
v.cpus = $vconfig['v.cpus'] # CPU settings. VirtualBox works much better with a single CPU.
v.memory = $vconfig['v.memory'] # Memory settings.
# Use VirtualBox DNS proxy mode (but not the resolver mode).
# See https://www.virtualbox.org/manual/ch09.html#nat-adv-dns
# and https://www.virtualbox.org/manual/ch09.html#nat_host_resolver_proxy
# Also see https://github.com/docker/machine/pull/1069 for a different perspective on this.
v.customize ['modifyvm', :id, '--natdnsproxy1', 'on']
v.customize ['modifyvm', :id, '--natdnshostresolver1', 'off']
end
## Provisioning scripts ##
# Pass vagrant_root variable to the VM and cd into the directory upon login.
config.vm.provision "shell", run: "always" do |s|
s.inline = <<-SCRIPT
echo "export VAGRANT_ROOT=$1" >> /home/docker/.profile
echo "cd $1" >> /home/docker/.ashrc
SCRIPT
s.args = "#{vagrant_mount_point}"
end
# Install dsh tool (Drude Shell) into VM's permanent storage.
# https://github.com/blinkreaction/drude
config.vm.provision "shell" do |s|
s.inline = <<-SCRIPT
# echo "Installing dsh (Drude Shell)..."
sudo curl -sSL https://raw.githubusercontent.com/blinkreaction/drude/master/bin/dsh -o /var/lib/boot2docker/bin/dsh
sudo chmod +x /var/lib/boot2docker/bin/dsh
sudo ln -sf /var/lib/boot2docker/bin/dsh /usr/local/bin/dsh
SCRIPT
end
# Let users provide credentials to log in to Docker Hub.
if $vconfig['docker_registry_auth']
config.vm.provision "trigger", :option => "value" do |trigger|
trigger.fire do
info 'Authenticating with the Docker registry...'
system "docker -H localhost:2375 login"
end
end
config.vm.provision "file", source: "~/.docker/config.json", destination: ".docker/config.json"
end
# System-wide dnsmasq service for DNS discovery and name resolution
config.vm.provision "shell", privileged: false do |s|
s.inline = <<-SCRIPT
echo "Setting up system-wide DNS service... "
docker run -d --name dns --label "group=system" --restart=always --privileged --userns=host \
-p 53:53/udp --cap-add=NET_ADMIN --dns 10.0.2.3 \
-v /var/run/docker.sock:/var/run/docker.sock \
blinkreaction/dns-discovery:stable > /dev/null 2>&1
SCRIPT
end
# System-wide ssh-agent service.
config.vm.provision "shell", privileged: false do |s|
s.inline = <<-SCRIPT
echo "Setting up system-wide ssh-agent service..."
docker run -d --name ssh-agent --label "group=system" --restart=always --privileged --userns=host \
-v /var/run/docker.sock:/var/run/docker.sock \
blinkreaction/ssh-agent:stable > /dev/null 2>&1
SCRIPT
end
# System-wide vhost-proxy service.
# Containers must define a "VIRTUAL_HOST" environment variable to be recognized and routed by the vhost-proxy.
if $vconfig['vhost_proxy']
config.vm.provision "shell", privileged: false do |s|
s.inline = <<-SCRIPT
echo "Setting up system-wide HTTP/HTTPS reverse proxy... "
docker run -d --name vhost-proxy --label "group=system" --restart=always --privileged --userns=host \
-p 80:80 -p 443:443 \
-v /var/run/docker.sock:/tmp/docker.sock \
blinkreaction/nginx-proxy:stable > /dev/null 2>&1
SCRIPT
end
end
# Automatically start containers if docker-compose.yml is present in the current directory.
# See "autostart" property in vagrant.yml.
if File.file?('./docker-compose.yml') && $vconfig['compose_autostart']
config.vm.provision "shell", run: "always", privileged: false do |s|
s.inline = <<-SCRIPT
echo "Found docker-compose.yml in the root folder. Starting containers..."
cd $1
docker-compose up -d
SCRIPT
s.args = "#{vagrant_mount_point}"
end
end
end