-
Notifications
You must be signed in to change notification settings - Fork 0
/
scythe-server
executable file
·172 lines (159 loc) · 8.65 KB
/
scythe-server
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
#!/bin/bash
export SCYTHE_SERVER_VERSION=1.3.2
export TESTER_ID="$1" # this is safe since it is in .ssh/authorized_keys
if [ -z "$TESTER_ID" ]; then
echo "scythe-server: missing TESTER_ID" >&2
exit 1
fi
arguments=($SSH_ORIGINAL_COMMAND)
export SCYTHE_VERSION="${arguments[0]}"
if [ "$SCYTHE_SERVER_VERSION" != "$SCYTHE_VERSION" ]; then
echo "scythe-server: version mismatch: client is '$SCYTHE_VERSION', server is '$SCYTHE_SERVER_VERSION'" >&2
exit 1
fi
export SCYTHE_COMMAND="${arguments[1]}"
export SESSION_ID="${arguments[2]}"
if [ -z "$SESSION_ID" ]; then
echo "scythe-server: missing SESSION_ID" >&2
exit 1
fi
export REMAINING_ARGS="${arguments[@]:3}"
export SCYTHE_ROOT="$HOME/scythe-root/$TESTER_ID/$SESSION_ID"
export SCYTHE_TM_CONF="$SCYTHE_ROOT/conf-tm.py"
export SCYTHE_ST_CONF="$SCYTHE_ROOT/conf-st.py"
export SCYTHE_UPLOADS="$SCYTHE_ROOT/uploads"
export SCYTHE_NAME="${TESTER_ID}-${SESSION_ID}"
export SCYTHE_LABEL="scythe=session-${SCYTHE_NAME}"
export SCYTHE_TM_ENDPOINT="http://$(hostname)/tm/$TESTER_ID/$SESSION_ID/"
export SCYTHE_DASHBOARD="$(hostname)/st/$TESTER_ID/#/session/$SESSION_ID/$auth"
mkdir -p "$SCYTHE_ROOT"
mkdir -p "$SCYTHE_UPLOADS"
if [ ! -r "$SCYTHE_UPLOADS/no.log" ]; then
touch "$SCYTHE_UPLOADS/no.log" # to avoid tail failures
fi
echo -e "$(date)\t$SSH_CONNECTION\t$TESTER_ID\t$SCYTHE_COMMAND\t$SESSION_ID" >> "$HOME/scythe-server.log"
check_session() {
if [ ! -r "$SCYTHE_TM_CONF" ] || [ ! -r "$SCYTHE_ST_CONF" ]; then
echo "scythe-server: unknown session '$SESSION_ID' for '$TESTER_ID'" >&2
exit 1
fi
}
case "$SCYTHE_COMMAND" in
start-tm)
did=$(docker ps -a --filter name="scythe-${SCYTHE_NAME}-tm" --format '{{.ID}}')
if [ ! -z "$did" ]; then
echo "scythe-server: sart-tm: killing old instance..." $(docker rm -f $did) >&2
fi
if [ -r "$SCYTHE_TM_CONF" ]; then
echo "scythe-server: start-tm: replacing '$SESSION_ID' configuration for '$TESTER_ID'" >&2
else
echo "scythe-server: start-tm: installing '$SESSION_ID' configuration for '$TESTER_ID'" >&2
fi
cat > "$SCYTHE_TM_CONF" <<EOF
UPLOAD_DIR = '/uploads'
BASE_URL = '$SCYTHE_TM_ENDPOINT'
EOF
cat >> "$SCYTHE_TM_CONF"
echo "scythe-server: start-tm: removing signature for test UID '000000' in '$SESSION_ID' for tester '$TESTER_ID'" >&2
rm -f "$SCYTHE_UPLOADS/000000/SIGNATURE.tsv"
did=$(docker run --user "$(id -u):$(id -g)" -l "$SCYTHE_LABEL" --name "scythe-${SCYTHE_NAME}-tm" -d --network=scythe -v "$SCYTHE_UPLOADS":/uploads -v "$SCYTHE_TM_CONF":/app/conf.py:ro scythe-server/tmserver)
echo "scythe-server: start-tm: started 'scythe-${SCYTHE_NAME}-tm' with conf '$SCYTHE_TM_CONF', and uploads in '$SCYTHE_UPLOADS' (docker id '$did')..." >&2
echo "scythe-server: start-tm: attempting to sign..." >&2
sleep 2
docker run --network scythe --rm -i --entrypoint sh scythe-server/tmserver -c "mkdir /tmp/test && export HOME=/tmp/test; eval \$( python3 -c 'from urllib.request import urlopen; exec(urlopen(\"http://scythe-router/tm/$TESTER_ID/$SESSION_ID/000000\").read().decode(\"utf-8\"))' ) && cd /tmp/test && find"
echo "scythe-server: start-tm: getting hash from router..." >&2
curl -s "$SCYTHE_TM_ENDPOINT" && echo
;;
nuke-restart)
did=$(docker ps -a --filter name="scythe-${SCYTHE_NAME}-st" --format '{{.ID}}')
if [ ! -z "$did" ]; then
echo "scythe-server: nuke-restart: killing old instance..." $(docker rm -f $did) >&2
fi
echo "scythe-server: nuke-restart: nuking old data..." >&2
docker run -e SCYTHE_REDIS_HOST="scythe-${TESTER_ID}-redis" --network scythe --rm -v "$SCYTHE_ST_CONF":/conf.py:ro scythe-server/stserver nuke -s "$SESSION_ID"
echo "scythe-server: nuke-restart: loading configurations on stserver..." >&2
docker run -e SCYTHE_REDIS_HOST="scythe-${TESTER_ID}-redis" --network scythe --rm -v "$SCYTHE_ST_CONF":/conf.py:ro scythe-server/stserver configure -c /conf.py -s "$SESSION_ID"
did=$(docker run -l "$SCYTHE_LABEL" --name "scythe-${SCYTHE_NAME}-st" -d --network=scythe -e SCYTHE_REDIS_HOST="scythe-${TESTER_ID}-redis" -v "$SCYTHE_UPLOADS":/uploads:ro scythe-server/stserver stage -wH /uploads -s "$SESSION_ID")
echo "scythe-server: nuke-restart: started st 'scythe-${SCYTHE_NAME}-st' with uploads in '$SCYTHE_UPLOADS' (docker id '$did')..." >&2
;;
start-st)
did=$(docker ps -a --filter name="scythe-${SCYTHE_NAME}-st" --format '{{.ID}}')
if [ ! -z "$did" ]; then
echo "scythe-server: start-st: killing old instance..." $(docker rm -f $did) >&2
fi
if [ -r "$SCYTHE_ST_CONF" ]; then
old_hash=$(docker run --rm -v "$SCYTHE_ST_CONF":/conf.py:ro scythe-server/tmserver tm hashconf /conf.py)
echo "scythe-server: start-st: replacing '$SESSION_ID' configuration for tester '$TESTER_ID' (old hash '$old_hash')" >&2
else
old_hash=
echo "scythe-server: start-st: installing '$SESSION_ID' configuration for tester '$TESTER_ID'" >&2
fi
cat > "$SCYTHE_ST_CONF"
if [ ! -z "$old_hash" ]; then
new_hash=$(docker run --rm -v "$SCYTHE_ST_CONF":/conf.py:ro scythe-server/tmserver tm hashconf /conf.py)
if [ "$old_hash" != "$new_hash" ]; then
echo "scythe-server: start-st: detected deep configuration change (new hash '$new_hash'), nuking old data..." >&2
docker run -e SCYTHE_REDIS_HOST="scythe-${TESTER_ID}-redis" --network scythe --rm -v "$SCYTHE_ST_CONF":/conf.py:ro scythe-server/stserver nuke -s "$SESSION_ID"
fi
fi
echo "scythe-server: start-st: loading configurations on stserver..." >&2
docker run -e SCYTHE_REDIS_HOST="scythe-${TESTER_ID}-redis" --network scythe --rm -v "$SCYTHE_ST_CONF":/conf.py:ro scythe-server/stserver configure -c /conf.py -s "$SESSION_ID"
did=$(docker run -l "$SCYTHE_LABEL" --name "scythe-${SCYTHE_NAME}-st" -d --network=scythe -e SCYTHE_REDIS_HOST="scythe-${TESTER_ID}-redis" -v "$SCYTHE_UPLOADS":/uploads:ro scythe-server/stserver stage -wH /uploads -s "$SESSION_ID")
echo "scythe-server: start-st: started st 'scythe-${SCYTHE_NAME}-st' with uploads in '$SCYTHE_UPLOADS' (docker id '$did')..." >&2
;;
stop)
check_session
echo "scythe-server: stop: stopping '$SESSION_ID' containers for tester '$TESTER_ID'" >&2
dids=$(docker ps -a --filter label="$SCYTHE_LABEL" --format '{{.ID}}')
if [ ! -z "$dids" ]; then
echo "scythe-server: stop: killing old session instances..." $(docker rm -f $dids) >&2
else
echo "scythe-server: stop: no running container found" >&2
fi
;;
auth)
check_session
echo "scythe-server: auth: use this URL to access the dashboard with '$REMAINING_ARGS' permissions" >&2
auth=$(docker run --network scythe -e SCYTHE_REDIS_HOST="scythe-${TESTER_ID}-redis" --rm -i scythe-server/stserver auth -s "$SESSION_ID" $REMAINING_ARGS)
echo "$SCYTHE_DASHBOARD$auth" >&2
;;
status)
check_session
dids=$(docker ps --filter label="$SCYTHE_LABEL" --format "{{.Names}}")
if [ -z "$dids" ]; then
echo "scythe-server: status: no running sessions for tester '$TESTER_ID'" >&2
else
echo "scythe-server: status: running containers for tester '$TESTER_ID'" >&2
echo $dids
echo "scythe-server: status: getting remote hash..." >&2
curl -s "$SCYTHE_TM_ENDPOINT" && echo
fi
;;
backup)
check_session
docker cp "scythe-${TESTER_ID}-redis":/data/appendonly.aof "${SCYTHE_UPLOADS}/"
rsync --server --sender -vlogDtprz . "${SCYTHE_UPLOADS}/" # the leading / is crucial to have the content without uploads/ on the client
;;
logtail)
check_session
echo "scythe-server: logtail: tailing '$SESSION_ID' logs for tester '$TESTER_ID', hit ctrl-c to stop..." >&2
tail -f "$SCYTHE_ROOT/uploads"/*.log >&2
;;
unsign)
check_session
signature="${SCYTHE_UPLOADS}/${REMAINING_ARGS}/SIGNATURE.tsv"
if [ -r "$signature" ]; then
echo "scythe-server: unsign: removed signature for '$REMAINING_ARGS' in '$SESSION_ID' for tester '$TESTER_ID'" >&2
yes | rm -f "$signature"
else
echo "scythe-server: unsign: no signature found for '$REMAINING_ARGS' in '$SESSION_ID' for tester '$TESTER_ID'" >&2
fi
;;
version)
echo "scythe-server: version: version v$SCYTHE_SERVER_VERSION" >&2
exit 0
;;
*)
echo "scythe-server: command '$SCYTHE_COMMAND' not recognized" >&2
exit 1
esac