forked from gruntwork-io/gruntwork-installer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbootstrap-gruntwork-installer.sh
executable file
·254 lines (211 loc) · 8.07 KB
/
bootstrap-gruntwork-installer.sh
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
#!/bin/bash
#
# A bootstrap script to install the Gruntwork Installer.
#
# Why:
#
# The goal of the Gruntwork Installer is to make make installing Gruntwork Script Modules feel as easy as installing a
# package using apt-get, brew, or yum. However, something has to install the Gruntwork Installer first. One option is
# for each Gruntwork client to do so manually, which would basically entail copying and pasting all the code below.
# This is tedious and would give us no good way to push updates to this bootstrap script.
#
# So instead, we recommend that clients use this tiny bootstrap script as a one-liner:
#
# curl -LsS https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer/master/bootstrap-gruntwork-installer.sh | bash /dev/stdin --version 0.0.3
#
# You can copy this one-liner into your Packer and Docker templates and immediately after, start using the
# gruntwork-install command.
set -e
readonly BIN_DIR="/usr/local/bin"
readonly USER_DATA_DIR="/etc/user-data"
readonly DEFAULT_FETCH_VERSION="v0.2.0"
readonly FETCH_DOWNLOAD_URL_BASE="https://github.com/gruntwork-io/fetch/releases/download"
readonly FETCH_INSTALL_PATH="$BIN_DIR/fetch"
readonly GRUNTWORK_INSTALLER_DOWNLOAD_URL_BASE="https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer"
readonly GRUNTWORK_INSTALLER_INSTALL_PATH="$BIN_DIR/gruntwork-install"
readonly GRUNTWORK_INSTALLER_SCRIPT_NAME="gruntwork-install"
function print_usage {
echo
echo "Usage: bootstrap-gruntwork-installer.sh [OPTIONS]"
echo
echo "A bootstrap script to install the Gruntwork Installer ($GRUNTWORK_INSTALLER_SCRIPT_NAME)."
echo
echo "Options:"
echo
echo -e " --version\t\tRequired. The version of $GRUNTWORK_INSTALLER_SCRIPT_NAME to install (e.g. 0.0.3)."
echo -e " --fetch-version\tOptional. The version of fetch to install. Default: $DEFAULT_FETCH_VERSION."
echo -e " --user-data-owner\tOptional. The user who shown own the $USER_DATA_DIR folder. Default: (current user)."
echo -e " --download-url\tOptional. The URL from where to download $GRUNTWORK_INSTALLER_SCRIPT_NAME. Mostly used for automated tests. Default: $GRUNTWORK_INSTALLER_DOWNLOAD_URL_BASE/(version)/$GRUNTWORK_INSTALLER_SCRIPT_NAME."
echo
echo "Examples:"
echo
echo " Install version 0.0.3:"
echo " bootstrap-gruntwork-installer.sh --version 0.0.3"
echo
echo " One-liner to download this bootstrap script from GitHub and run it to install version 0.0.3:"
echo " curl -Ls https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer/master/bootstrap-gruntwork-installer.sh | bash /dev/stdin --version 0.0.3"
}
# http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script
function command_exists {
local readonly cmd="$1"
type "$cmd" > /dev/null 2>&1
}
function download_url_to_file {
local readonly url="$1"
local readonly file="$2"
local readonly tmp_path=$(mktemp "/tmp/gruntwork-bootstrap-download-XXXXXX")
echo "Downloading $url to $tmp_path"
if $(command_exists "curl"); then
local readonly status_code=$(curl -L -s -w '%{http_code}' -o "$tmp_path" "$url")
assert_successful_status_code "$status_code" "$url"
echo "Moving $tmp_path to $file"
sudo mv -f "$tmp_path" "$file"
else
echo "ERROR: curl is not installed. Cannot download $url."
exit 1
fi
}
function assert_successful_status_code {
local readonly status_code="$1"
local readonly url="$2"
if [[ "$status_code" == "200" ]]; then
echo "Got expected status code 200"
elif $(string_starts_with "$url" "file://") && [[ "$status_code" == "000" ]]; then
echo "Got expected status code 000 for local file URL"
else
echo "ERROR: Expected status code 200 but got $status_code when downloading $url"
exit 1
fi
}
function string_starts_with {
local readonly str="$1"
local readonly prefix="$2"
[[ "$str" == "$prefix"* ]]
}
function string_contains {
local readonly str="$1"
local readonly contains="$2"
[[ "$str" == *"$contains"* ]]
}
# http://stackoverflow.com/a/2264537/483528
function to_lower_case {
tr '[:upper:]' '[:lower:]'
}
function get_os_name {
uname | to_lower_case
}
function get_os_arch {
uname -m
}
function get_os_arch_gox_format {
local readonly arch=$(get_os_arch)
if $(string_contains "$arch" "64"); then
echo "amd64"
elif $(string_contains "$arch" "386"); then
echo "386"
elif $(string_contains "$arch" "686"); then
echo "386" # Not a typo; 686 is also 32-bit and should work with 386 binaries
elif $(string_contains "$arch" "arm"); then
echo "arm"
fi
}
function download_and_install {
local readonly url="$1"
local readonly install_path="$2"
download_url_to_file "$url" "$install_path"
sudo chmod 0755 "$install_path"
}
function install_fetch {
local readonly install_path="$1"
local readonly version="$2"
local readonly os=$(get_os_name)
local readonly os_arch=$(get_os_arch_gox_format)
if [[ -z "$os_arch" ]]; then
echo "ERROR: Unrecognized OS architecture: $(get_os_arch)"
exit 1
fi
echo "Installing fetch version $version to $install_path"
local readonly url="${FETCH_DOWNLOAD_URL_BASE}/${version}/fetch_${os}_${os_arch}"
download_and_install "$url" "$install_path"
}
function install_gruntwork_installer {
local readonly install_path="$1"
local readonly version="$2"
local readonly download_url="$3"
echo "Installing $GRUNTWORK_INSTALLER_SCRIPT_NAME version $version to $install_path"
download_and_install "$download_url" "$install_path"
}
function assert_not_empty {
local readonly arg_name="$1"
local readonly arg_value="$2"
if [[ -z "$arg_value" ]]; then
echo "ERROR: The value for '$arg_name' cannot be empty"
print_usage
exit 1
fi
}
function create_user_data_folder {
local readonly user_data_folder="$1"
local readonly user_data_folder_owner="$2"
local readonly user_data_folder_readme="$user_data_folder/README.txt"
echo "Creating $user_data_folder as a place to store scripts intended to be run in the User Data of an EC2 instance during boot"
sudo mkdir -p "$user_data_folder"
sudo tee "$user_data_folder_readme" > /dev/null <<EOF
The /etc/user-data folder contains scripts that should be executed while an EC2 instance is booting as part of its
User Data (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) configuration.
This folder is not an industry standard, but a convention we use at Gruntwork (http://www.gruntwork.io) make User Data
scripts manageable. Many of the modules in Script Modules (https://github.com/gruntwork-io/script-modules) need not
only to be installed, but also to execute while a server is booting, and instead of scattering them in random locations
all over the file system, /etc/user-data gives us a single, common place to put them all.
EOF
sudo chown -R "$user_data_folder_owner" "$user_data_folder"
}
function bootstrap {
local fetch_version="$DEFAULT_FETCH_VERSION"
local installer_version=""
local user_data_folder_owner=$(id -u -n)
local download_url=""
while [[ $# > 0 ]]; do
local key="$1"
case "$key" in
--version)
installer_version="$2"
shift
;;
--fetch-version)
fetch_version="$2"
shift
;;
--user-data-owner)
user_data_folder_owner="$2"
shift
;;
--download-url)
download_url="$2"
shift
;;
--help)
print_usage
exit
;;
*)
echo "ERROR: Unrecognized option: $key"
print_usage
exit 1
;;
esac
shift
done
assert_not_empty "--version" "$installer_version"
assert_not_empty "--fetch-version" "$fetch_version"
assert_not_empty "--user-data-owner" "$user_data_folder_owner"
if [[ -z "$download_url" ]]; then
download_url="${GRUNTWORK_INSTALLER_DOWNLOAD_URL_BASE}/${installer_version}/${GRUNTWORK_INSTALLER_SCRIPT_NAME}"
fi
echo "Installing $GRUNTWORK_INSTALLER_SCRIPT_NAME..."
install_fetch "$FETCH_INSTALL_PATH" "$fetch_version"
install_gruntwork_installer "$GRUNTWORK_INSTALLER_INSTALL_PATH" "$installer_version" "$download_url"
create_user_data_folder "$USER_DATA_DIR" "$user_data_folder_owner"
echo "Success!"
}
bootstrap "$@"