-
Notifications
You must be signed in to change notification settings - Fork 0
/
provision.bash
executable file
·287 lines (241 loc) · 7.42 KB
/
provision.bash
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
#!/bin/bash
#
# Provisioning script for vagrant.
# If there's only one project with requirements and deps in VAGRANT_TOP,
# this is fine, otherwise set VAGRANT_PROJ
: ${VAGRANT_TOP:=/vagrant}
: ${VAGRANT_PROJ:=*}
main() {
if [[ $EUID != 0 ]]; then
msg "--> provision.bash as_user"
as_user
msg "<-- provision.bash as_user"
return
fi
msg "--> provision.bash as_root"
as_root
msg "<-- provision.bash as_root"
su vagrant -c "$(printf '%q ' "$0" "$@")"
}
as_root() {
is_vbox && vbox_preinstall
install_packages
(is_docker || is_lxc) && lxc_postinstall
common_postinstall
}
vbox_preinstall() {
# If the host has moved between networks, sometimes DNS needs to be
# reconnected.
/etc/init.d/networking restart
}
common_postinstall() {
# Set up the locale support files
sed -i '/en_US.UTF-8/s/^# *//' /etc/locale.gen
locale-gen
# Set the timezone
ln -sfn /usr/share/zoneinfo/EST5EDT /etc/localtime
}
lxc_postinstall() {
declare uid gid
# Make the vagrant uid/gid match the host user
# so the bind-mounted source area works properly.
read uid gid <<<"$(stat -c '%u %g' "$VAGRANT_TOP")"
if [[ ! -n $uid ]]; then
die "Couldn't read uid/gid for vagrant user"
fi
if [[ $(id -u vagrant) != $uid || $(id -g vagrant) != $gid ]]; then
# usermod/userdel doesn't work when logged in
sed -i '/vagrant/d' /etc/passwd /etc/shadow
groupmod -g $gid vagrant
useradd -u $uid -g vagrant -G sudo -s /bin/bash vagrant \
-p "$(perl -e "print crypt('vagrant', 'AG')")"
find /home/vagrant -xdev -print0 | xargs -0r chown $uid:$gid
chown $uid:$gid /tmp/vagrant-shell 2>/dev/null ||:
fi
}
install_packages() {
declare -a packages
packages+=( locales ) # for locale-gen
packages+=( python-software-properties ) # for add-apt-repository
packages+=( curl rsync )
packages+=( python-pip python-virtualenv python-dev virtualenv )
packages+=( ruby-dev bundler )
packages+=( git )
packages+=( sudo ssh )
packages+=( make gcc g++ binutils )
packages+=( inotify-tools ) # inotifywait
packages+=( nodejs yarn ) # add npm if not installing from nodesource
# Don't install extra stuff.
# Suggests list is long; recommends list is short and sensible.
# To omit recommends, add APT::Install-Recommends "false";
cat > /etc/apt/apt.conf.d/99vagrant <<EOT
APT::Install-Suggests "false";
EOT
# Add nodejs upstream.
# v4 is LTS until April 2017.
if [[ " ${packages[*]} " == *" nodejs "* && \
! -e /etc/apt/sources.list.d/nodesource.list ]]; then
which curl &>/dev/null || (apt-get update; apt-get install curl -y)
curl -sL https://deb.nodesource.com/setup_4.x | bash
fi
# Add yarn package manager.
if [[ " ${packages[*]} " == *" yarn "* && \
! -e /etc/apt/sources.list.d/yarn.list ]]; then
which curl &>/dev/null || (apt-get update; apt-get install curl -y)
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb http://dl.yarnpkg.com/debian/ stable main" | \
sudo tee /etc/apt/sources.list.d/yarn.list
fi
# This should prevent apt-get install/upgrade from asking ANY questions
export DEBIAN_FRONTEND=noninteractive
# Update package list
apt-get update
# Upgrade ssh server first to avoid killing the running server
apt-get install -y ssh \
-o 'PackageManager::Configure=no' \
-o 'DPkg::ConfigurePending=no'
chmod -x /etc/init.d/ssh # prevents restart
dpkg --configure -a
# Now the rest
apt-get install -y "${packages[@]}"
apt-get upgrade -y "${packages[@]}"
# Make /usr/bin/nodejs available as /usr/local/bin/node
ln -sfn /usr/bin/nodejs /usr/local/bin/node
}
as_user() {
cd ~
if [[ $PWD == */vagrant ]]; then
rm -f .profile
cat > .bash_profile <<EOT
source ~/.bashrc
EOT
cat > .bashrc <<EOT
PATH=~/node_modules/.bin:\$PATH
[[ -e $VAGRANT_TOP/vagrant-env.bash ]] && \\
source $VAGRANT_TOP/vagrant-env.bash
[[ -e ~/env ]] && source ~/env/bin/activate
[[ \$- != *i* ]] && return
PS1='\u@\h:\w\\\$ '
cd $VAGRANT_TOP
EOT
source .bash_profile
fi
user_virtualenv
user_gems
user_npm
}
user_virtualenv() {
cd ~
if ! type virtualenv &>/dev/null; then
echo "no virtualenv, skipping python requirements" >&2
return
fi
# Always create the virtualenv, even if there's no requirements.txt, since
# we also use it to isolate ruby gems.
if [[ ! -d env ]]; then
virtualenv env
fi
source env/bin/activate
declare reqs
if reqs=$(src requirements.txt); then
pip install -U pip
pip install -r "$reqs"
fi
}
pip() {
PYTHONUNBUFFERED=1 command pip "$@"
}
user_gems() {
cd ~
if [[ ! -d env ]]; then
echo "no virtualenv, skipping ruby gems" >&2
return
fi
if ! grep -q GEM_HOME env/bin/activate; then
echo 'export GEM_HOME="$VIRTUAL_ENV/ruby" PATH="$VIRTUAL_ENV/ruby/bin:$PATH"' >> env/bin/activate
fi
source env/bin/activate
declare gemfile
if gemfile=$(src Gemfile); then
cd "$(dirname "$gemfile")"
bundle clean --force
bundle install
fi
}
user_npm() {
cd ~
declare found
if found=$(src yarn.lock) || found=$(src npm-shrinkwrap.json) || found=$(src package.json); then
cd "$(dirname "$found")"
# This is a little bit of a hack in that it does a local install to a
# symlinked node_modules, so that the install is in the vagrant image
# rather than the bind-mounted src dir.
mkdir -p ~/node_modules
ln -sfn ~/node_modules node_modules
if [[ -f yarn.lock ]]; then
yarn install
elif [[ -f npm-shrinkwrap.json ]]; then
npm install
elif which yarn &>/dev/null; then
yarn install
else
npm install
fi
fi
}
src() {
# ff only checks one level of nesting, and testing it with -f will only
# succeed if there was a single match.
declare f=$VAGRANT_TOP/"$1" ff=$(echo $VAGRANT_TOP/$VAGRANT_PROJ/"$1")
if [[ -f $f ]]; then
echo "$f"
elif [[ -f $ff ]]; then
echo "$ff"
else
return 1
fi
}
msg() {
echo "$*"
}
die() {
echo "$*"
exit 1
}
is_docker() {
if [[ ! -d /home/vagrant ]]; then
echo "is_docker: running outside vagrant?" >&2
return 1
fi
sudo grep -qw docker /proc/1/cgroup
eval "is_docker() { return $?; }"
is_docker
}
is_lxc() {
if [[ ! -d /home/vagrant ]]; then
echo "is_lxc: running outside vagrant?" >&2
return 1
fi
# https://www.redhat.com/archives/virt-tools-list/2013-April/msg00117.html
sudo grep -q container=lxc /proc/1/environ
eval "is_lxc() { return $?; }"
is_lxc
}
is_vbox() {
if [[ ! -d /home/vagrant ]]; then
echo "is_vbox: running outside vagrant?" >&2
return 1
fi
which dmidecode &>/dev/null || sudo apt-get install -y dmidecode
sudo dmidecode 2>/dev/null | grep -q VirtualBox
eval "is_vbox() { return $?; }"
is_vbox
}
#######################################################################
#
# RUN MAIN only if not sourced into another script
#
#######################################################################
case ${0##*/} in
provision.bash|vagrant-shell) main "$@" ;;
esac