forked from debops/debops
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Vagrantfile
486 lines (418 loc) · 16.8 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
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Set up an Ansible Controller host with DebOps support using Vagrant
#
# Copyright (C) 2017 Maciej Delmanowski <[email protected]>
# Copyright (C) 2017 DebOps project https://debops.org/
# Basic usage:
#
# vagrant up && vagrant ssh
# cd src/controller ; debops
# Configuration variables:
#
# VAGRANT_BOX="debian/stretch64"
# Specify the bos to use.
#
# VAGRANT_HOSTNAME="stretch"
# Set a custom hostname after the box boots up.
#
# CONTROLLER=false
# Set to 'true' to set up a configuration with normal Diffie-Hellman
# parameters (3072, 2048) instead of a smaller one (1024). Initial DH
# parameter generation may take a long time.
#
# APT_HTTP_PROXY="" (http://apt.example.org:3142)
# Set a custom APT cache URL inside the Vagrant box.
$provision_box = <<SCRIPT
set -o nounset -o pipefail -o errexit
export JANE_VAGRANT_INCEPTION="true"
readonly PROVISION_CI="#{ENV['CI']}"
readonly PROVISION_GITLAB_CI="#{ENV['GITLAB_CI']}"
readonly PROVISION_VAGRANT_HOSTNAME="#{ENV['VAGRANT_HOSTNAME']}"
readonly PROVISION_APT_HTTP_PROXY="#{ENV['APT_HTTP_PROXY']}"
readonly PROVISION_APT_HTTPS_PROXY="#{ENV['APT_HTTPS_PROXY']}"
readonly PROVISION_ANSIBLE_FROM="#{ENV['ANSIBLE_FROM'] || 'debian'}"
# Install the Jane script
if ! type jane > /dev/null 2>&1 ; then
export JANE_BOX_INIT="true"
if [ -e "/vagrant/lib/tests/jane" ] ; then
cp /vagrant/lib/tests/jane /usr/local/bin/jane && chmod +x /usr/local/bin/jane
jane notify info "Jane installed"
else
tee "/usr/local/bin/jane" > "/dev/null" <<EOF
#!/bin/sh
# Fake stub Jane script
printf "%s\\n" "JANE: \\${\*}"
EOF
chmod +x /usr/local/bin/jane
fi
else
if [ -e "/vagrant/lib/tests/jane" ] ; then
if ! cmp "/vagrant/lib/tests/jane" "/usr/local/bin/jane" ; then
cp /vagrant/lib/tests/jane /usr/local/bin/jane && chmod +x /usr/local/bin/jane
jane notify info "Jane updated"
else
jane notify ok "Jane up to date"
fi
else
jane notify ok "Jane found at '$(which jane)'"
fi
fi
# Disable automated APT operations as soon as possible. This is only valid for
# testing environments and helps avoid errors due to locked APT/dpkg.
# https://unix.stackexchange.com/questions/315502/
if [ -n "${PROVISION_CI}" ] ; then
jane notify info "Stopping apt-daily.service..."
systemctl stop apt-daily.service || true
systemctl kill --kill-who=all apt-daily.service || true
systemctl stop apt-daily.timer || true
next_wait_time=0
until systemctl list-units --all apt-daily.service | fgrep -q dead || [ $next_wait_time -eq 2 ] ; do
jane notify info "Waiting for apt-daily.service to go down..."
sleep $(( next_wait_time++ ))
done
jane notify info "Stopping apt-daily-upgrade.service..."
systemctl stop apt-daily-upgrade.service || true
systemctl kill --kill-who=all apt-daily-upgrade.service || true
systemctl stop apt-daily-upgrade.timer || true
next_wait_time=1
until systemctl list-units --all apt-daily-upgrade.service | fgrep -q dead || [ $next_wait_time -eq 4 ] ; do
jane notify info "Waiting for apt-daily-upgrade.service to go down..."
sleep $(( next_wait_time++ ))
done
rm -rf /var/lib/systemd/timers/*.timer
fi
# Configure APT proxy
if [ -n "${PROVISION_APT_HTTP_PROXY}" ] ; then
tee "/etc/apt/apt.conf.d/00aptproxy" > "/dev/null" <<EOF
Acquire::http::Proxy "${PROVISION_APT_HTTP_PROXY}";
Acquire::https::Proxy "false";
EOF
if [ -n "${PROVISION_APT_HTTPS_PROXY}" ] ; then
tee -a "/etc/apt/apt.conf.d/00aptproxy" > "/dev/null" <<EOF
Acquire::https::Proxy "${PROVISION_APT_HTTPS_PROXY}";
EOF
else
tee -a "/etc/apt/apt.conf.d/00aptproxy" > "/dev/null" <<EOF
Acquire::https::Proxy "DIRECT";
EOF
fi
fi
# Configure GitLab CI environment
if [ -n "${PROVISION_GITLAB_CI}" ] && [ "${PROVISION_GITLAB_CI}" == "true" ] ; then
tee "/etc/profile.d/vagrant_vars.sh" > "/dev/null" <<EOF
export JANE_INCEPTION="true"
export CI="#{ENV['CI']}"
export GITLAB_CI="#{ENV['GITLAB_CI']}"
export CI_JOB_ID="#{ENV['CI_JOB_ID']}"
export CI_JOB_NAME="#{ENV['CI_JOB_NAME']}"
export CI_JOB_STAGE="#{ENV['CI_JOB_STAGE']}"
export JANE_TEST_PLAY="#{ENV['JANE_TEST_PLAY']}"
export JANE_FORCE_TESTS="#{ENV['JANE_FORCE_TESTS']}"
export JANE_INVENTORY_DIRS="#{ENV['JANE_INVENTORY_DIRS']}"
export JANE_INVENTORY_GROUPS="#{ENV['JANE_INVENTORY_GROUPS']}"
export JANE_INVENTORY_HOSTVARS="#{ENV['JANE_INVENTORY_HOSTVARS']}"
export JANE_KEEP_BOX="#{ENV['JANE_KEEP_BOX']}"
export VAGRANT_BOX="#{ENV['VAGRANT_BOX']}"
export VAGRANT_DOTFILE_PATH="#{ENV['VAGRANT_DOTFILE_PATH']}"
export TERM="#{ENV['TERM']}"
EOF
fi
provision_apt_http_proxy=""
provision_apt_https_proxy=""
eval $(apt-config shell provision_apt_http_proxy Acquire::http::Proxy)
eval $(apt-config shell provision_apt_https_proxy Acquire::https::Proxy)
if [ -n "${provision_apt_http_proxy}" ] ; then
jane notify config "APT HTTP proxy is enabled: '${provision_apt_http_proxy}'"
fi
if [ -n "${provision_apt_https_proxy}" ] ; then
if [ "${provision_apt_https_proxy}" == "DIRECT" ] ; then
jane notify config "APT HTTPS proxy is disabled"
else
jane notify config "APT HTTPS proxy is enabled: '${provision_apt_https_proxy}'"
fi
fi
# Configure hostname and domain
REAL_HOSTNAME=""
if [ -n "${PROVISION_VAGRANT_HOSTNAME}" ] ; then
export REAL_HOSTNAME="${PROVISION_VAGRANT_HOSTNAME}"
elif [ -n "${PROVISION_GITLAB_CI}" ] && [ "${PROVISION_GITLAB_CI}" == "true" ] ; then
export REAL_HOSTNAME="ci-$(cat /proc/sys/kernel/random/uuid)"
fi
if [ -n "${REAL_HOSTNAME}" ] ; then
current_fqdn="$(dnsdomainname -A)"
jane notify info "Changing box hostname to '${REAL_HOSTNAME}'..."
if [ -d /run/systemd/system ] ; then
hostnamectl set-hostname "${REAL_HOSTNAME}"
if [ "$(systemctl is-active systemd-networkd.service)" == "active" ] ; then
jane notify info "Requesting restart of 'systemd-networkd.service'"
systemctl restart systemd-networkd.service
else
jane notify info "Requesting restart of 'networking.service'..."
systemctl restart networking.service
fi
else
hostname "${REAL_HOSTNAME}"
printf "%s\n" "${REAL_HOSTNAME}" > /etc/hostname
jane notify info "Requesting restart of 'networking' service..."
/etc/init.d/networking restart
fi
jane notify info "Waiting for network configuration to settle..."
loop_timeout=5
sleep 2
until [ "$(dnsdomainname -A)" != "${current_fqdn}" ] || [ ${loop_timeout} -eq 7 ] ; do
jane notify info "Waiting for new FQDNs..."
sleep $(( loop_timeout++ ))
done
if [ -z "$(dnsdomainname)" ] ; then
jane notify warning "DNS domain configuration failed, enforcing in /etc/hosts...."
known_fqdns=( $(dnsdomainname -A) )
for item in "${!known_fqdns[@]}" ; do
case "${known_fqdns[${item}]}" in
*.*)
jane notify info "Adding FQDN: '${known_fqdns[${item}]}'..."
ip_index="$(( ${item} + 1 ))"
printf "%s\n" "127.0.1.${ip_index} ${known_fqdns[${item}]} $(hostname)" >> /etc/hosts
;;
esac
done
fi
if [ "${REAL_HOSTNAME}" == "$(hostname)" ] ; then
jane notify ok "Hostname changed successfully"
jane notify info "Hostname: '$(hostname)'"
jane notify info "Domain: '$(dnsdomainname)'"
jane notify info "FQDN: '$(hostname --fqdn)'"
else
jane notify warning "Hostname change to '${REAL_HOSTNAME}' failed"
fi
fi
ansible_from_debian=""
ansible_from_pypi=""
ansible_from_devel=""
if [ "${PROVISION_ANSIBLE_FROM}" == "debian" ] ; then
ansible_from_debian="ansible"
elif [ "${PROVISION_ANSIBLE_FROM}" == "pypi" ] ; then
ansible_from_pypi="ansible"
else
ansible_from_devel="${PROVISION_ANSIBLE_FROM}"
fi
# Configure Ansible
if ! type ansible > /dev/null 2>&1 ; then
jane notify warning "Ansible not found"
tee "/etc/apt/sources.list" > "/dev/null" <<EOF
deb http://deb.debian.org/debian stretch main
deb http://deb.debian.org/debian stretch-updates main
deb http://deb.debian.org/debian stretch-backports main
deb http://security.debian.org/ stretch/updates main
EOF
tee "/etc/apt/preferences.d/provision_ansible.pref" > "/dev/null" <<EOF
Package: ansible
Pin: release a=stretch-backports
Pin-Priority: 500
EOF
jane notify cache "Refreshing APT cache"
apt-get update
if [ -n "${ansible_from_devel}" ] ; then
jane notify install "Installing Ansible from GitHub..."
/vagrant/ansible/roles/debops.ansible/files/script/bootstrap-ansible "${ansible_from_devel}"
fi
jane notify install "Installing Ansible requirements via APT..."
DEBIAN_FRONTEND=noninteractive apt-get -y \
--no-install-recommends install \
acl \
apt-transport-https \
encfs \
git \
haveged \
jo \
jq \
make \
python-apt \
python-dnspython \
python-future \
python-jinja2 \
python-ldap \
python-nose2 \
python-nose2-cov \
python-openssl \
python-passlib \
python-pip \
python-pycodestyle \
python-pytest \
python-pytest-cov \
python-setuptools \
python-sphinx \
python-sphinx-rtd-theme \
python-unittest2 \
python-wheel \
python-yaml \
shellcheck \
yamllint ${ansible_from_debian}
jane notify cache "Cleaning up cache directories..."
find /var/lib/apt/lists -maxdepth 1 -type f ! -name 'lock' -delete
find /var/cache/apt/archives -maxdepth 1 -name '*.deb' -delete
rm -rf /root/.cache/* /tmp/*
else
jane notify ok "Ansible found at '$(which ansible)'"
ansible --version
fi
# Update APT cache on the first boot after provisioning so that APT packages
# can be installed correctly right away.
if [ -z "${JANE_BOX_INIT:-}" ] ; then
jane notify cache "Refreshing APT cache"
apt-get update
# vagrant-libvirt executes virt-sysprep during box packaging.
# virt-sysprep zeroes out files in /usr/local/*, apparently.
# So we need to install PyPI packages on the real box, not the template.
jane notify install "Installing test requirements via PyPI..."
pip install debops testinfra ${ansible_from_pypi}
jane notify cache "Cleaning up cache directories..."
rm -rf /root/.cache/* /tmp/*
fi
jane notify success "Vagrant box provisioning complete"
SCRIPT
$provision_node_box = <<SCRIPT
set -o nounset -o pipefail -o errexit
JANE_VAGRANT_INCEPTION="true"
PROVISION_GITLAB_CI="#{ENV['GITLAB_CI']}"
PROVISION_APT_HTTP_PROXY="#{ENV['APT_HTTP_PROXY']}"
PROVISION_APT_HTTPS_PROXY="#{ENV['APT_HTTPS_PROXY']}"
# Configure GitLab CI environment
if [ -n "${PROVISION_GITLAB_CI}" ] && [ "${PROVISION_GITLAB_CI}" == "true" ] ; then
tee "/etc/profile.d/vagrant_vars.sh" > "/dev/null" <<EOF
export JANE_INCEPTION="true"
export CI="#{ENV['CI']}"
export GITLAB_CI="#{ENV['GITLAB_CI']}"
export CI_JOB_ID="#{ENV['CI_JOB_ID']}"
export TERM="#{ENV['TERM']}"
EOF
fi
# Install the CI supervisor script
if ! type jane > /dev/null 2>&1 ; then
if [ -e "/vagrant/lib/tests/jane" ] ; then
cp /vagrant/lib/tests/jane /usr/local/bin/jane && chmod +x /usr/local/bin/jane
jane notify info "Jane installed"
else
tee "/usr/local/bin/jane" > "/dev/null" <<EOF
#!/bin/sh
# Fake Jane script
printf "%s\\n" "JANE: \\${*}"
EOF
chmod +x /usr/local/bin/jane
fi
else
jane notify ok "Jane found at '$(which jane)'"
jane notify info "Refreshing APT sources"
apt-get -qq update
fi
# Configure hostname and domain
REAL_HOSTNAME="ci-$(cat /proc/sys/kernel/random/uuid)"
if [ -n "${REAL_HOSTNAME}" ] ; then
jane notify info "Changing box hostname to '${REAL_HOSTNAME}'..."
if [ -d /run/systemd/system ] ; then
hostnamectl set-hostname "${REAL_HOSTNAME}"
systemctl restart networking.service
else
hostname "${REAL_HOSTNAME}"
printf "%s\n" "${REAL_HOSTNAME}" > /etc/hostname
/etc/init.d/networking restart
fi
jane notify ok "Hostname changed to '$(hostname)'"
jane notify info "FQDN: '$(hostname --fqdn)'"
jane notify info "DOMAIN: '$(dnsdomainname)'"
fi
# Configure APT cache
if [ -n "${PROVISION_APT_HTTP_PROXY}" ] ; then
jane notify info "Configuring APT cache at '${PROVISION_APT_HTTP_PROXY}'"
cat "/etc/apt/apt.conf.d/00aptproxy" <<EOF
Acquire::http::Proxy "${PROVISION_APT_HTTP_PROXY}";
EOF
fi
jane notify info "Vagrant node provisioning complete"
SCRIPT
$provision_controller = <<SCRIPT
set -o nounset -o pipefail -o errexit
readonly PROVISION_ANSIBLE_FROM="#{ENV['ANSIBLE_FROM'] || 'debian'}"
jane notify info "Configuring Ansible Controller host..."
ansible_from_pypi=""
if [ "${PROVISION_ANSIBLE_FROM}" == "pypi" ] ; then
ansible_from_pypi="ansible"
fi
jane notify install "Installing test requirements via PyPI..."
sudo pip install debops testinfra ${ansible_from_pypi}
jane notify cache "Cleaning up cache directories..."
sudo rm -rf /root/.cache/* /tmp/*
if ! [ -e .local/share/debops/debops ] ; then
mkdir -p src .local/share/debops
if [ -d "/vagrant" ] ; then
jane notify info "Symlinking '/vagrant' to '~vagrant/.local/share/debops/debops'"
ln -s /vagrant .local/share/debops/debops
else
jane notify info "Installing DebOps monorepo to '~vagrant/.local/share/debops/debops'"
debops-update
fi
fi
if ! [ -d src/controller ] ; then
debops-init src/controller
sed -i '/ansible_connection=local$/ s/^#//' src/controller/ansible/inventory/hosts
mkdir -p "src/controller/ansible/inventory/host_vars/$(hostname)"
if [ -z "#{ENV['CONTROLLER']}" ] || [ "#{ENV['CONTROLLER']}" != "true" ] ; then
printf "%s\n" "---\n\n# Use smaller DH parameters to speed up test runs\ndhparam__bits: [ '1024' ]" > "src/controller/ansible/inventory/host_vars/$(hostname)/dhparam.yml"
fi
fi
jane notify info "Ansible Controller provisioning complete"
SCRIPT
VAGRANT_NODES = ENV['VAGRANT_NODES'] || 0
VAGRANT_NODE_BOX = ENV['VAGRANT_NODE_BOX'] || 'debian/stretch64'
# Vagrant removed the atlas.hashicorp.com to vagrantcloud.com
# redirect. The value of DEFAULT_SERVER_URL in Vagrant versions
# less than 1.9.3 is atlas.hashicorp.com. This breaks the fetching
# and updating of boxes as they are now stored in
# vagrantcloud.com instead of atlas.hashicorp.com.
# https://github.com/hashicorp/vagrant/issues/9442
Vagrant::DEFAULT_SERVER_URL.replace('https://vagrantcloud.com')
Vagrant.configure("2") do |config|
config.vm.define "master", primary: true do |subconfig|
subconfig.vm.box = ENV['VAGRANT_BOX'] || 'debian/stretch64'
subconfig.vm.provision "shell", inline: $provision_box, keep_color: true, run: "always"
subconfig.vm.provider "libvirt" do |libvirt, override|
# On a libvirt provider, default sync method is NFS. If we switch
# it to 'rsync', this will drop the dependency on NFS on the host.
override.vm.synced_folder ENV['CI_PROJECT_DIR'] || ".", "/vagrant", type: "rsync"
override.vm.network :public_network, :dev => ENV['VAGRANT_MASTER_PUBLIC_BRIDGE'] || 'br0', :type => 'bridge'
libvirt.random_hostname = true
libvirt.memory = ENV['VAGRANT_MASTER_MEMORY'] || '512'
if ENV['GITLAB_CI'] != "true"
libvirt.memory = ENV['VAGRANT_MASTER_MEMORY'] || '1024'
end
if ENV['VAGRANT_BOX'] || 'debian/stretch64' == 'debian/stretch64'
override.ssh.insert_key = false
end
end
if ENV['GITLAB_CI'] != "true"
subconfig.vm.provision "shell", inline: $provision_controller, keep_color: true, privileged: false
end
if Vagrant::Util::Platform.windows? then
# MS Windows doesn't support symlinks, so disable directory sync under it.
# DebOps will be installed normally, via 'debops-update'
subconfig.vm.synced_folder ".", "/vagrant", disabled: true
elsif ENV['GITLAB_CI'] == "true"
# We are running in a GitLab CI environment
subconfig.vm.synced_folder ENV['CI_PROJECT_DIR'] || ".", "/vagrant"
end
if ENV['CI'] != "true"
subconfig.vm.post_up_message = "Thanks for trying DebOps! After logging in, run:
cd src/controller ; debops"
end
end
if VAGRANT_NODES != 0
(1..VAGRANT_NODES).each do |i|
config.vm.define "node#{i}", autostart: false do |node|
node.vm.box = VAGRANT_NODE_BOX
node.vm.provision "shell", inline: $provision_node_box, keep_color: true, run: "always"
# Don't populate '/vagrant' directory on other nodes
node.vm.synced_folder ".", "/vagrant", disabled: true
end
end
end
end