You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
6.5 KiB
Bash
266 lines
6.5 KiB
Bash
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
# Services Manager for 42l
|
|
|
|
ABS_FULLPATH=$(realpath $0)
|
|
ABS_FOLDER=$(dirname $(realpath $0))
|
|
|
|
SRV_FOLDER=$ABS_FOLDER/services
|
|
IMG_FOLDER=$ABS_FOLDER/images
|
|
|
|
# load global vars
|
|
if [ -f "$ABS_FOLDER/global-vars.sh" ]; then
|
|
set -a
|
|
. $ABS_FOLDER/global-vars.sh
|
|
set +a
|
|
fi
|
|
|
|
## service-related functions
|
|
|
|
check_service_exists()
|
|
{
|
|
SRV_EXISTS=`ls $SRV_FOLDER | grep -w $1 || true`
|
|
if [ "$SRV_EXISTS" == "" ]; then
|
|
echo "Specified service does not exist."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_image_exists()
|
|
{
|
|
IMG_EXISTS=`ls $IMG_FOLDER | grep -w $1 || true`
|
|
if [ ! $IMG_EXISTS ]; then
|
|
echo "Specified image does not exist."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
list_services()
|
|
{
|
|
ls $SRV_FOLDER
|
|
}
|
|
|
|
build_service()
|
|
{
|
|
check_service_exists $1
|
|
if [ -f "$SRV_FOLDER/$1/buildtime.env" ]; then
|
|
env $(cat $SRV_FOLDER/$1/buildtime.env | xargs) docker compose -f $SRV_FOLDER/$1/docker-compose.yml build
|
|
else
|
|
docker compose -f $SRV_FOLDER/$1/docker-compose.yml build
|
|
fi
|
|
}
|
|
|
|
start_service()
|
|
{
|
|
check_service_exists $1
|
|
if [ -f "$SRV_FOLDER/$1/buildtime.env" ]; then
|
|
env $(cat $SRV_FOLDER/$1/buildtime.env | xargs) docker compose -f $SRV_FOLDER/$1/docker-compose.yml up -d
|
|
else
|
|
docker compose -f $SRV_FOLDER/$1/docker-compose.yml up -d
|
|
fi
|
|
}
|
|
|
|
stop_service()
|
|
{
|
|
check_service_exists $1
|
|
if [ -f "$SRV_FOLDER/$1/buildtime.env" ]; then
|
|
env $(cat $SRV_FOLDER/$1/buildtime.env | xargs) docker compose -f $SRV_FOLDER/$1/docker-compose.yml down
|
|
else
|
|
docker compose -f $SRV_FOLDER/$1/docker-compose.yml down
|
|
fi
|
|
}
|
|
|
|
restart_service()
|
|
{
|
|
check_service_exists $1
|
|
stop_service $1
|
|
start_service $1
|
|
}
|
|
|
|
reload_service()
|
|
{
|
|
check_service_exists $1
|
|
if [ -f "$SRV_FOLDER/$1/buildtime.env" ]; then
|
|
env $(cat $SRV_FOLDER/$1/buildtime.env | xargs) docker compose -f $SRV_FOLDER/$1/docker-compose.yml restart
|
|
else
|
|
docker compose -f $SRV_FOLDER/$1/docker-compose.yml restart
|
|
fi
|
|
}
|
|
|
|
pull_service()
|
|
{
|
|
check_service_exists $1
|
|
if [ -f "$SRV_FOLDER/$1/buildtime.env" ]; then
|
|
env $(cat $SRV_FOLDER/$1/buildtime.env | xargs) docker compose -f $SRV_FOLDER/$1/docker-compose.yml pull
|
|
else
|
|
docker compose -f $SRV_FOLDER/$1/docker-compose.yml pull
|
|
fi
|
|
}
|
|
|
|
## image-related functions
|
|
|
|
list_images()
|
|
{
|
|
ls $IMG_FOLDER
|
|
}
|
|
|
|
build_image()
|
|
{
|
|
check_image_exists $1
|
|
if [ -f "$IMG_FOLDER/$1/buildtime.env" ]; then
|
|
docker build -t "local/$1" $(for i in `cat $IMG_FOLDER/$1/buildtime.env`; do out+="--build-arg $i "; done; echo $out; out="") $IMG_FOLDER/$1/
|
|
else
|
|
docker build -t "local/$1" $IMG_FOLDER/$1/
|
|
fi
|
|
}
|
|
|
|
start_image()
|
|
{
|
|
check_image_exists $1
|
|
if [ -f "$IMG_FOLDER/$1/runtime.env" ]; then
|
|
export $(cat $IMG_FOLDER/$1/runtime.env | xargs)
|
|
fi
|
|
|
|
if [ -f $IMG_FOLDER/$1/start.sh ]; then
|
|
$IMG_FOLDER/$1/start.sh
|
|
else
|
|
echo "$1 is not runnable (base image)."
|
|
fi
|
|
}
|
|
|
|
image_main()
|
|
{
|
|
if [ "$1" = "list" ]; then
|
|
list_images
|
|
elif [ -n "$2" ]; then
|
|
case $1 in
|
|
build) build_image $2;;
|
|
start) start_image $2;;
|
|
*) usage;;
|
|
esac
|
|
else
|
|
usage
|
|
fi
|
|
|
|
}
|
|
|
|
## audit-related functions
|
|
|
|
audit_all() {
|
|
audit_tabheader
|
|
for srv in $(ls $SRV_FOLDER); do
|
|
# do not audit services marked as disabled
|
|
if [ ! -f "$SRV_FOLDER/$srv/.disabled" ]; then
|
|
audit_single $srv ""
|
|
fi
|
|
done
|
|
}
|
|
|
|
audit_single() {
|
|
if [ "$2" == "+header" ]; then
|
|
audit_tabheader
|
|
fi
|
|
printf "%-14s\t" "$1"
|
|
|
|
RUNNING=$(docker ps -q -f name=$1)
|
|
if [[ -z $RUNNING ]]; then
|
|
c_red "DOWN\t"
|
|
else
|
|
c_green "UP!\t"
|
|
fi
|
|
|
|
chkbool "$(grep "pids_limit" $SRV_FOLDER/$1/docker-compose.yml | xargs | sed 's/pids_limit: //g')"
|
|
echo -ne "\t\t"
|
|
|
|
chkbool "$(grep "cpu_shares" $SRV_FOLDER/$1/docker-compose.yml | xargs | sed 's/cpu_shares: //g')"
|
|
echo -ne "\t\t"
|
|
|
|
chkbool "$(grep "mem_limit" $SRV_FOLDER/$1/docker-compose.yml | xargs | sed 's/mem_limit: //g')"
|
|
echo -ne "\t\t"
|
|
|
|
if ! [[ -z $RUNNING ]]; then
|
|
chkbool "$(docker inspect --format '{{ .Id }}:ReadonlyRootfs={{ .HostConfig.ReadonlyRootfs }}' $1 | grep -o "true" | sed 's/true/YES/g')"
|
|
echo -ne "\t\t"
|
|
|
|
#chkbool $(ps -p $(docker inspect --format='{{ .State.Pid }}' $1) -o user | tail -n 1 | sed 's/root//g')
|
|
chkbool "$(ps -p $(docker inspect --format='{{ .State.Pid }}' $1) -o user | tail -n 1 | sed 's/root//g' | sed -E 's/.+/YES/g')"
|
|
echo -ne "\t\t"
|
|
|
|
chkbool "$(docker inspect --format '{{ .Id }}:SecurityOpt={{ .HostConfig.SecurityOpt }}' $1 | grep "no-new-privileges" | sed -E 's/.+/YES/g')"
|
|
echo -ne "\t\t"
|
|
|
|
chkbool "$($(docker run --rm -it --net container:$1 nicolaka/netshoot netstat -tnul | tail -n +3 | awk '$1=$1' | cut -d ' ' -f4 | grep -q '0.0.0.0') || echo "YES")"
|
|
echo -ne "\t\t"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
audit_tabheader() {
|
|
echo -e "NAME\t\tSTATUS\tPID LIMIT\tCPU SHARES\tRAM LIMIT\tREAD-ONLY\tUNPRIVILEGED\tRESTR.PRIV.\tFIXED ADDR."
|
|
}
|
|
|
|
chkbool() {
|
|
if [[ -z "$1" ]]; then
|
|
c_red "NO"
|
|
else
|
|
c_green "$1"
|
|
fi
|
|
}
|
|
|
|
c_red() {
|
|
echo -ne '\033[0;31m'$1'\033[0m'
|
|
}
|
|
|
|
c_green() {
|
|
echo -ne '\033[0;32m'$1'\033[0m'
|
|
}
|
|
|
|
## main
|
|
|
|
register_manager() {
|
|
if [ ! -f "/usr/local/bin/manager" ]; then
|
|
echo "Create symbolic link…"
|
|
sudo ln -s $ABS_FULLPATH /usr/local/bin/manager
|
|
fi
|
|
echo "Add autocompletions for the fish shell…"
|
|
mkdir -p ~/.config/fish/completions/
|
|
cp $ABS_FOLDER/tools/setup/conf/manager.fish ~/.config/fish/completions/
|
|
}
|
|
|
|
usage()
|
|
{
|
|
echo -e "Usage:\t$0 list\n"
|
|
echo -e "\t$0 <build|start|stop|restart|reload|pull> <service_name>"
|
|
echo -e "\t$0 image list"
|
|
echo -e "\t$0 image <build|start> <service_name>"
|
|
echo -e "\t$0 audit [service_name]"
|
|
echo -e "\t$0 register"
|
|
}
|
|
|
|
if [ -z "${1:-""}" ]; then
|
|
usage
|
|
elif [ "$1" = "list" ]; then
|
|
list_services
|
|
elif [ "$1" = "audit" ] && [ -z "${2:-""}" ]; then
|
|
audit_all
|
|
elif [ "$1" = "register" ] && [ -z "${2:-""}" ]; then
|
|
register_manager
|
|
elif [ -n "$2" ]; then
|
|
case $1 in
|
|
build) build_service $2;;
|
|
start) start_service $2;;
|
|
stop) stop_service $2;;
|
|
restart) restart_service $2;;
|
|
reload) reload_service $2;;
|
|
pull) pull_service $2;;
|
|
image) image_main $2 ${3:-""};;
|
|
audit) audit_single $2 "+header";;
|
|
*) usage;;
|
|
esac
|
|
else
|
|
usage
|
|
fi
|