/
otomi
executable file
·324 lines (292 loc) · 8.87 KB
/
otomi
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
#!/usr/bin/env bash
#####################################################################################
##
## NOTE:
## This is a command line tool to operate on otomi-core.
## All commands are executed in docker container.
## Keep this file as simple as possible:
## - do not depend on any external files.
## - do not use any non standard tooling.
## - only Docker is needed to run otomi-core image
## If you need to use any extra binaries then most probably you want to add them to the otomi/tools image.
##
#####################################################################################
# shellcheck disable=SC2128
[ "${BASH_VERSINFO:-0}" -lt 4 ] && echo "You are using $BASH_VERSINFO, while we only support Bash -ge than version 4. Please upgrade." && exit 1
calling_args="$*"
if [ -n "$CI" ] || [ -n "$TESTING" ]; then
calling_args="$calling_args --non-interactive"
fi
readonly calling_args
if [ -n "$TESTING" ]; then
CI=1
ENV_DIR="$PWD/tests/fixtures"
source "$ENV_DIR/env/.env"
NOPULL=1
elif [ -z "$ENV_DIR" ]; then
ENV_DIR=$PWD
else
mkdir -p $ENV_DIR
fi
# set -x
silent() {
if [[ $calling_args == *'-v'* ]] && [ -t 1 ]; then
"$@"
else
"$@" &>/dev/null
fi
}
# shellcheck disable=SC2155
readonly base_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
in_core=false
if [[ $base_dir == *"otomi-core"* ]] || [[ $(pwd) == *"otomi-core"* ]]; then
in_core=true
fi
function docker_tag_exists() {
curl --silent -f -lSL https://index.docker.io/v1/repositories/otomi/core/tags/$1 >/dev/null
}
# Parse yaml block without yq: https://stackoverflow.com/a/49190338/14982291
otomi_version="latest"
if [ "$in_core" = true ]; then
current_branch="$(git branch --show-current 2>/dev/null)"
current_branch="${current_branch##*/}"
current_branch="${current_branch:-'master'}"
otomi_version='master'
if docker_tag_exists $current_branch; then
otomi_version=$current_branch
fi
elif [ -f "${ENV_DIR}/env/settings.yaml" ]; then
otomi_version=$(awk '/otomi/{flag=1} flag && /version:/{print $NF;flag=""}' $ENV_DIR/env/settings.yaml)
fi
OTOMI_TAG=${OTOMI_TAG:-$otomi_version}
readonly otomi_tools_image="otomi/core:${OTOMI_TAG}"
script_full_path="$base_dir/${BASH_SOURCE[0]##*/}"
if [[ ${BASH_SOURCE[0]} == '/'* ]]; then
script_full_path="${BASH_SOURCE[0]}"
fi
readonly script_full_path
update_base="https://raw.githubusercontent.com/redkubes/otomi-core/${OTOMI_TAG}/binzx/otomi"
date_to_format() {
date=$1
format=${2:-+%s}
which_date=$(which date)
if [[ $(uname -s) == "Darwin" ]] && [[ "$which_date" == "/bin/date" ]]; then
date -j -f "%Y-%m-%dT%H:%M:%SZ" $date $format
return $?
fi
date --date="$date" $format
return $?
}
universal_stat() {
file=$1
which_stat=$(which stat)
if [[ $(uname -s) == "Darwin" ]] && [[ "$which_stat" == "/usr/bin/stat" ]]; then
stat -f %A $file
return $?
fi
stat -c '%a' $file
return $?
}
run_self_update() {
echo "Performing self-update..."
# Download new version
echo -n "Downloading latest version..."
if ! wget --quiet --output-document="$0.tmp" $update_base; then
echo "Failed: Error while trying to wget new version!"
echo "File requested: $update_base"
exit 1
fi
echo "Done."
# Copy over modes from old version
OCTAL_MODE=$(universal_stat $script_full_path)
if ! chmod $OCTAL_MODE "$0.tmp"; then
echo "Failed: Error while trying to set mode on $0.tmp."
exit 1
fi
# Spawn update script
cat >update-otomi.sh <<EOF
#!/bin/bash
# Overwrite old file with new
if mv "$0.tmp" "$0"; then
echo "Done. Update complete."
rm \$0
exec "$0" "$calling_args"
else
echo "Failed!"
fi
EOF
echo -n "Inserting update process..."
exec /bin/bash update-otomi.sh
}
check_update() {
if [ "$in_core" = true ] ||
[[ $calling_args == *'-non-interactive'* ]] ||
[[ $calling_args == *'-ni'* ]]; then
return 0
fi
last_commit_date=$(curl -s "https://api.github.com/repos/redkubes/otomi-core/commits?sha=${OTOMI_TAG}&path=binzx%2Fotomi&page=1&per_page=1" | grep -A5 '"committer":' | grep '"date":' | awk -F': ' '{print $2}' | tr -d '"')
last_file_change=$(date -u -r $script_full_path '+%Y-%m-%dT%H:%M:%SZ')
last_commit_date_sec=$(date_to_format $last_commit_date)
last_file_change_sec=$(date_to_format $last_file_change)
if [ "$last_commit_date_sec" -ne "0" ] && [ "$last_commit_date_sec" -gt "$last_file_change_sec" ]; then
read -r -p "Newer version is available, do you want to update (yes/No)? " answer
case ${answer:0:1} in
y | Y)
run_self_update
;;
*)
return 0
;;
esac
fi
}
silent echo "Checking for updates"
[ -z $CI ] && check_update
silent echo "Preparing docker environment variables"
tmp_env=$(mktemp)
function dump_vars() {
for var in "$@"; do
val="${!var}"
[ -n "$val" ] && echo "$var=$val" >>$tmp_env
done
}
OTOMI_PORT=${OTOMI_PORT:-17771}
OTOMI_IN_TERMINAL="false"
if [ -t 1 ]; then
# shellcheck disable=SC2034
OTOMI_IN_TERMINAL="true"
fi
vars=(
AWS_ACCESS_KEY_ID
AWS_REGION
AWS_SECRET_ACCESS_KEY
AZURE_CLIENT_ID
AZURE_CLIENT_SECRET
AZURE_TENANT_ID
CI
DEBUG
ENV_DIR
GCLOUD_SERVICE_KEY
K8S_CONTEXT
KUBE_VERSION_OVERRIDE
OTOMI_DRY_RUN
OTOMI_IN_TERMINAL
OTOMI_PASSWORD
OTOMI_PORT
OTOMI_SERVER
OTOMI_TAG
OTOMI_USERNAME
OTOMI_NON_INTERACTIVE
PROFILE
STATIC_COLORS
SHELL
TESTING
TRACE
VERBOSITY
VAULT_TOKEN
)
dump_vars "${vars[@]}"
cat >>$tmp_env <<EOF
OTOMI_CALLER_COMMAND=${BASH_SOURCE[0]##*/}
IN_DOCKER=1
EOF
helm_config="$HOME/.config/helm"
if [[ $(uname -s) == "Darwin" ]]; then
helm_config="$HOME/Library/Preferences/helm"
else
readonly linux_workaround='--user=root:root'
fi
stack_dir='/home/app/stack'
executable="node --experimental-specifier-resolution=node ${stack_dir}/dist/otomi.js --"
stack_volume=""
tmp_volume_dir=$(mktemp -d)
tmp_volume=" -v $tmp_volume_dir:/tmp"
if [ "$in_core" = true ]; then
silent echo "Checking if in dev environment"
if [[ $base_dir == *"otomi-core"* ]]; then
stack_dir=$(cd "$base_dir/.." && pwd)
elif [[ $(pwd) == *"otomi-core"* ]]; then
stack_dir=$(pwd | awk -F'otomi-core' '{print $1"otomi-core"}')
fi
stack_volume="-v $stack_dir:$stack_dir"
tmp_volume="-v /tmp:/tmp"
# Use development distribution if exists
if [ -f "${stack_dir}/dist/otomi.js" ]; then
executable="node --experimental-specifier-resolution=node ${stack_dir}/dist/otomi.js --"
else
executable="node --no-warnings --experimental-specifier-resolution=node --loader ts-node/esm ${stack_dir}/src/otomi.ts --"
fi
echo "OTOMI_DEV=1" >>$tmp_env
fi
check_volume_path() {
source=$1
dest=$2
[ -z $source ] && [ -z $dest ] && echo "" && return 0
echo "-v $source:$dest"
return 0
}
cmd="${executable} $*"
# If command is "otomi bash"
if [ "$1" = "bash" ] && [ "$#" = "1" ]; then
cmd="bash"
fi
if { { [ "$OTOMI_TAG" = 'latest' ] || [ "$OTOMI_TAG" = 'master' ]; } || [ -n "$FORCE_PULL" ]; } && [ -z $NOPULL ] && [ -z $IN_DOCKER ]; then
silent echo "Pulling latest version of the docker image, please wait"
silent docker pull $otomi_tools_image
status=$?
if [ "$status" -ne 0 ]; then
echo "Something went wrong when trying to pull '${otomi_tools_image}'"
exit $status
fi
fi
it='-it'
if [[ $calling_args == *'-non-interactive'* ]] ||
[[ $calling_args == *'-ni'* ]]; then
it=''
fi
network='--network host'
if [[ $calling_args == 'server'* ]]; then
network="--init -p $OTOMI_PORT:$OTOMI_PORT"
fi
mkdir -p /tmp/otomi
if [ -n "$IN_DOCKER" ]; then
$cmd
status=$?
elif [[ $calling_args == *'--get-yargs-completions'* ]]; then
docker run --rm -e SHELL=$SHELL "$otomi_tools_image" bash -c "$cmd"
status=$?
else
docker run --rm $it \
$linux_workaround \
$network \
$stack_volume \
$tmp_volume \
-v /tmp/otomi:/tmp/otomi \
$(check_volume_path $HOME/.kube "/home/app/.kube") \
$([ -n "$KUBECONFIG" ] && check_volume_path $KUBECONFIG "/home/app/.kube/config") \
$(check_volume_path $HOME/.ssh "/home/app/.ssh") \
$(check_volume_path $helm_config "/home/app/.config/helm") \
$(check_volume_path $HOME/.config/gcloud "/home/app/.config/gcloud") \
$(check_volume_path $HOME/.aws "/home/app/.aws") \
$(check_volume_path $HOME/.azure "/home/app/.azure") \
$(check_volume_path $ENV_DIR "$stack_dir/env") \
$(check_volume_path $ENV_DIR "$ENV_DIR") \
$(check_volume_path /var/run/docker.sock "/var/run/docker.sock") \
--env-file "$tmp_env" \
-w "$stack_dir" \
"$otomi_tools_image" \
bash -c "$cmd"
status=$?
fi
if [[ $calling_args == *'-skip-cleanup'* ]] || [[ $calling_args == *'-s'* ]]; then
running_date=$(date -u '+%y%m%d-%H%M')
backup_path="/tmp/otomi/otomi-$running_date"
mkdir -p "$backup_path"
mv "$tmp_env" "$backup_path/running_env"
else
# Docker seems to be slow to release these files, needs to sleep to make sure that the file & volume are released and can be removed
sleep 0.1
rm -f "$tmp_env" &>/dev/null
rm -rf "$tmp_volume_dir" &>/dev/null
fi
exit $status