181 lines
5.3 KiB
Bash
Executable File
181 lines
5.3 KiB
Bash
Executable File
#!/bin/bash
|
|
set -eo pipefail
|
|
|
|
COLOR_RED="\e[0;31m"
|
|
COLOR_GREEN="\e[0;32m"
|
|
COLOR_YELLOW="\e[0;33m"
|
|
COLOR_NONE="\e[0m"
|
|
function log_info() { echo -e "${COLOR_GREEN}$*${COLOR_NONE}" 1>&2; }
|
|
function log_warn() { echo -e "${COLOR_YELLOW}$*${COLOR_NONE}" 1>&2; }
|
|
function log_error() { echo -e "${COLOR_RED}$*${COLOR_NONE}" 1>&2; }
|
|
|
|
function check_env() {
|
|
# $1 -> var name
|
|
# $2 -> default value
|
|
# $3 -> quota or not
|
|
val=$(eval "echo -n \${$1}")
|
|
if test -z "$val"; then
|
|
log_warn "Environment variable $1 is not set, using default value \"$2\""
|
|
export "$1"="$2"
|
|
else
|
|
log_info "Using $1=$val"
|
|
fi
|
|
|
|
if "$3"; then
|
|
val=$(eval "echo -n \${$1}")
|
|
# shellcheck disable=SC2140
|
|
export "$1"="'$val'"
|
|
fi
|
|
|
|
# echo -n ">>>>> "
|
|
# eval "echo -n \${$1}"
|
|
# echo " <<<<<"
|
|
}
|
|
|
|
function extract_web_server() {
|
|
check_env "WEB_SERVER_ADDRESS" "0.0.0.0" true
|
|
check_env "WEB_SERVER_PORT" 8000 false
|
|
check_env "WEB_SERVER_PUBLIC_BASE" "http://127.0.0.1:8000" true
|
|
check_env "WEB_SERVER_TRUSTED_PLATFORM" "" true
|
|
check_env "WEB_SERVER_JWT_SIGNING_KEY" "$(head -n 10 /dev/urandom | md5sum | cut -c 1-32)" true
|
|
check_env "WEB_SERVER_JWT_EXPIRE_HOUR" 12 false
|
|
check_env "WEB_SERVER_OAUTH_DOMAIN" "" true
|
|
check_env "WEB_SERVER_OAUTH_CLIENT_ID" "" true
|
|
check_env "WEB_SERVER_OAUTH_CLIENT_SECRET" "" true
|
|
}
|
|
|
|
function extract_redis() {
|
|
check_env "REDIS_DB" 0 false
|
|
check_env "REDIS_QUEUE_DB" 1 false
|
|
check_env "REDIS_ADDRESS" "redis" true
|
|
check_env "REDIS_PORT" 6379 false
|
|
check_env "REDIS_PASSWORD" "" true
|
|
}
|
|
|
|
function extract_database() {
|
|
check_env "DATABASE_HOST" "postgres" true
|
|
check_env "DATABASE_PORT" 5432 false
|
|
check_env "DATABASE_USER" "dev" true
|
|
check_env "DATABASE_PASSWORD" "password" true
|
|
check_env "DATABASE_NAME" "dev" true
|
|
check_env "DATABASE_PREFIX" "oj_" true
|
|
check_env "DATABASE_MAX_OPEN_CONNS" 100 false
|
|
check_env "DATABASE_MAX_IDLE_CONNS" 60 false
|
|
check_env "DATABASE_CONN_MAX_LIFETIME" 60 false
|
|
check_env "DATABASE_TIMEZONE" "Asia/Shanghai" true
|
|
}
|
|
|
|
function extract_storage() {
|
|
check_env "STORAGE_ENDPOINT" "minio:9000" true
|
|
check_env "STORAGE_USE_SSL" "false" false
|
|
check_env "STORAGE_ACCESS_KEY" "access_key" true
|
|
check_env "STORAGE_SECRET_KEY" "secret_key" true
|
|
check_env "STORAGE_BUCKET" "woj" true
|
|
}
|
|
|
|
function extract_runner() {
|
|
check_env "CGROUP_PATH" "/sys/fs/cgroup/nsjail" true
|
|
}
|
|
|
|
function extract_metrics() {
|
|
check_env "METRICS_NAMESPACE" "woj" true
|
|
check_env "METRICS_SUBSYSTEM" "server" true
|
|
}
|
|
|
|
function extract_misc() {
|
|
check_env "DEVELOPMENT" false false
|
|
}
|
|
|
|
function generate_config() {
|
|
if [ -f '/app/config.yaml' ]; then
|
|
log_info "config.yaml already exists, skip"
|
|
return
|
|
fi
|
|
|
|
# extract env vars
|
|
extract_web_server
|
|
extract_redis
|
|
extract_database
|
|
extract_storage
|
|
extract_runner
|
|
extract_metrics
|
|
extract_misc
|
|
|
|
# dump script
|
|
rm -f /tmp/tmp.yaml
|
|
(
|
|
echo "cat <<EOF >/app/config.yaml"
|
|
cat /app/config.docker.yaml
|
|
echo "EOF"
|
|
) >/tmp/tmp.yaml
|
|
|
|
# dump env vars
|
|
log_info "creating config.yaml"
|
|
. /tmp/tmp.yaml || { log_error "failed to create config.yaml"; exit 1; }
|
|
|
|
# cleanup
|
|
rm -f /tmp/tmp.yaml
|
|
}
|
|
|
|
setup_cgroups() {
|
|
# taken from https://github.com/moby/moby/blob/ee6cbc540e9c62feb143c2a8d3f0c86d2a468767/hack/dind#L59-L69
|
|
# cgroup v2: enable nesting
|
|
if [ -f /sys/fs/cgroup/cgroup.controllers ]; then
|
|
# move the processes from the root group to the /init group,
|
|
# otherwise writing subtree_control fails with EBUSY.
|
|
# An error during moving non-existent process (i.e., "cat") is ignored.
|
|
mkdir -p /sys/fs/cgroup/init
|
|
xargs -rn1 < /sys/fs/cgroup/cgroup.procs > /sys/fs/cgroup/init/cgroup.procs || :
|
|
# enable controllers
|
|
sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/cgroup.controllers \
|
|
> /sys/fs/cgroup/cgroup.subtree_control
|
|
fi
|
|
|
|
# create nsjail group
|
|
mkdir -p /sys/fs/cgroup/nsjail
|
|
sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/nsjail/cgroup.controllers > /sys/fs/cgroup/nsjail/cgroup.subtree_control
|
|
}
|
|
|
|
setup_user_runner() {
|
|
# runner use debian as base image
|
|
groupadd --gid 1000 woj || true
|
|
useradd --gid 1000 --uid 1000 woj || true
|
|
# runner data
|
|
chown -R woj:woj /app/resource/runner/problem
|
|
chown -R woj:woj /app/resource/runner/tmp
|
|
chown -R woj:woj /app/resource/runner/user
|
|
# rootfs mount path
|
|
chown -R woj:woj /app/resource/runner/framework/rootfs/full/woj
|
|
chown -R woj:woj /app/resource/runner/framework/rootfs/run/woj
|
|
# cgroups
|
|
chown -R woj:woj /sys/fs/cgroup/nsjail
|
|
chown -R woj:root /sys/fs/cgroup/cgroup.procs
|
|
# create run dir: nsjail will try to use it
|
|
mkdir -p /run/user/1000
|
|
chown -R woj:woj /run/user/1000
|
|
chmod 700 /run/user/1000
|
|
}
|
|
|
|
setup_user_server() {
|
|
# server use alpine as base image
|
|
addgroup -g 1000 -S woj || true
|
|
adduser -u 1000 -S -G woj woj || true
|
|
}
|
|
|
|
setup_user() {
|
|
if [ -n "$RUNNER_IMAGE" ]; then
|
|
setup_user_runner
|
|
else
|
|
setup_user_server
|
|
fi
|
|
}
|
|
|
|
if [ -n "$RUNNER_IMAGE" ]; then setup_cgroups; fi
|
|
generate_config
|
|
setup_user
|
|
|
|
log_info "starting woj"
|
|
if [ -n "$RUNNER_IMAGE" ]; then EXEC=gosu; else EXEC=su-exec; fi
|
|
exec $EXEC woj /app/woj "$@"
|
|
|