From 8c27b1e38dfa9a03f4ed620d996ca8b9a287efa1 Mon Sep 17 00:00:00 2001 From: Jason Cameron Date: Wed, 23 Oct 2024 17:22:14 -0400 Subject: [PATCH] Fmt tools Signed-off-by: Jason Cameron --- automation/Readme.md | 1 - automation/add_judge.sh | 70 ++++----- automation/new_worker.sh | 60 ++++---- automation/playbooks/initialize_worker.yml | 2 +- .../roles/jsoncameron.docker/README.md | 37 +++-- .../jsoncameron.docker/defaults/main.yml | 4 +- automation/playbooks/update.yml | 14 +- automation/remove_droplet.sh | 142 +++++++++--------- automation/swarm_info | 12 +- automation/update_nodes.sh | 9 +- automation/vm-host-problem-watch | 28 ++-- 11 files changed, 196 insertions(+), 183 deletions(-) diff --git a/automation/Readme.md b/automation/Readme.md index 469c591..5b36125 100644 --- a/automation/Readme.md +++ b/automation/Readme.md @@ -1,4 +1,3 @@ - Please install the following packages: ```bash diff --git a/automation/add_judge.sh b/automation/add_judge.sh index 8e8466e..3dc2d55 100755 --- a/automation/add_judge.sh +++ b/automation/add_judge.sh @@ -3,45 +3,46 @@ set -e # exit on error #set -x # print each command before executing it -if [ "$EUID" -ne 0 ] - then echo "Please run as root" +if [ "$EUID" -ne 0 ]; then + echo "Please run as root" exit fi -if [ "$HOSTNAME" != "general" ] - then echo "Please run on general" +if [ "$HOSTNAME" != "general" ]; then + echo "Please run on general" exit fi -cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )" # cd to the directory of this script +cd "$( + cd "$(dirname "${BASH_SOURCE[0]}")" + pwd -P +)" # cd to the directory of this script . /home/judge/docker/dmoj/scripts/utils/notify . ./utils/commands.sh # check if name was provided -if [ -z "$1" ] - then echo "Please provide a name for the judge" +if [ -z "$1" ]; then + echo "Please provide a name for the judge" echo "Usage: $0 " exit fi JUDGE_NAME=$1 -if [ -z "$2" ] - then - # Check if the droplet already exists as a safety measure - if ! doctl compute droplet list --format Name | grep -i "$2"; then - echo "Droplet $2 does not exist!" >&2 - exit 1 - fi - CONSTRAINT="node.name == $(doctl compute droplet list --format Name | grep -i "$2" | awk '{print $1}')" +if [ -z "$2" ]; then + # Check if the droplet already exists as a safety measure + if ! doctl compute droplet list --format Name | grep -i "$2"; then + echo "Droplet $2 does not exist!" >&2 + exit 1 + fi + CONSTRAINT="node.name == $(doctl compute droplet list --format Name | grep -i "$2" | awk '{print $1}')" else - CONSTRAINT="node.role == worker" + CONSTRAINT="node.role == worker" fi - rand=$(head -c 75 /dev/urandom | tr -d '\0') # Convert bytes to Base64 -JUDGE_AUTH_KEY=$(echo "$rand" | base64 | tr -d '\n' | cut -c -90 ) # db type is varchar(100) +JUDGE_AUTH_KEY=$(echo "$rand" | base64 | tr -d '\n' | cut -c -90) # db type is varchar(100) notify "Attempting to create new judge $JUDGE_NAME on $2" # Warning for future devs: THE LINE BELOW IS A PAIN TO WRITE/DEAL WITH. I KNOW IT'S UGLY. I'M SORRY. @@ -49,20 +50,19 @@ run_single_command_on_site "python3 manage.py shell -c 'from judge.models import notify "Judge $JUDGE_NAME's DB obj was created" - -docker service create \ - --name "judge_${JUDGE_NAME}" \ - --env JUDGE_NAME="${JUDGE_NAME}" \ - --env AUTH_KEY="${JUDGE_AUTH_KEY}" \ - --replicas 1 \ - --constraint "$CONSTRAINT" \ - --network name=wlmoj_judge \ - --cap-add SYS_PTRACE \ - -e DMOJ_IN_DOCKER=1 \ - --mount type=bind,src=/var/share/problems/,dst=/problems/ \ - ghcr.io/mcpt/wlmoj-judge:latest \ - run -p 9999 -c /judge.yml \ - --skip-self-test \ - --api-host=0.0.0.0 \ - --api-port=9995 \ - "bridged" "$JUDGE_NAME" "$JUDGE_AUTH_KEY" \ No newline at end of file +echo docker service create \ + --name "judge_${JUDGE_NAME}" \ + --env JUDGE_NAME="${JUDGE_NAME}" \ + --env AUTH_KEY="${JUDGE_AUTH_KEY}" \ + --replicas 1 \ + --constraint "$CONSTRAINT" \ + --network name=wlmoj_judge \ + --cap-add SYS_PTRACE \ + -e DMOJ_IN_DOCKER=1 \ + --mount type=bind,src=/var/share/problems/,dst=/problems/ \ + ghcr.io/mcpt/wlmoj-judge:latest \ + run -p 9999 -c /judge.yml \ + --skip-self-test \ + --api-host=0.0.0.0 \ + --api-port=9995 \ + "bridged" "$JUDGE_NAME" "$JUDGE_AUTH_KEY" diff --git a/automation/new_worker.sh b/automation/new_worker.sh index eb136ef..7897048 100755 --- a/automation/new_worker.sh +++ b/automation/new_worker.sh @@ -1,33 +1,36 @@ #!/usr/bin/env bash -set -e # Exit on error -cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )" +set -e # Exit on error +cd "$( + cd "$(dirname "${BASH_SOURCE[0]}")" + pwd -P +)" -[ "$(whoami)" = root ] || { sudo "$0" "$@"; exit $?; } # enforce root as the ansible ssh key is installed under root +[ "$(whoami)" = root ] || { + sudo "$0" "$@" + exit $? +} # enforce root as the ansible ssh key is installed under root # grab a argument of --size -if [[ $* == *--large* ]] -then - SIZE="s-2vcpu-2gb" +if [[ $* == *--large* ]]; then + SIZE="s-2vcpu-2gb" else - SIZE="s-1vcpu-1gb" + SIZE="s-1vcpu-1gb" fi - . ../dmoj/scripts/utils/notify . ./swarm_info if [ -z "$1" ]; then - echo "Usage: $0 [--large]" - exit 1 + echo "Usage: $0 [--large]" + exit 1 fi # Check if the droplet already exists as a safety measure if doctl compute droplet list --format Name | grep -i "$1"; then - echo "Droplet $1 already exists!" >&2 - exit 1 + echo "Droplet $1 already exists!" >&2 + exit 1 fi - SSH_KEYS=$(doctl compute ssh-key list --no-header --format ID) echo "Provisioning new droplet $1..." @@ -35,45 +38,40 @@ echo "SSH keys: $(doctl compute ssh-key list --no-header --format Name | tr '\n' echo "Creating droplet..." notify "## Provisioning new droplet **$1**" - # Create the droplet droplet_id=$(doctl compute droplet create \ - --image ubuntu-22-04-x64 \ - --size "$SIZE" \ - --region tor1 \ - --enable-monitoring \ - --tag-names "worker" \ - --ssh-keys "$SSH_KEYS" \ - "$1" --output json | jq -r '.[0].id') - - + --image ubuntu-22-04-x64 \ + --size "$SIZE" \ + --region tor1 \ + --enable-monitoring \ + --tag-names "worker" \ + --ssh-keys "$SSH_KEYS" \ + "$1" --output json | jq -r '.[0].id') # Wait for the droplet to be active echo "Waiting for droplet to be active..." while true; do - status=$(doctl compute droplet get "$droplet_id" --output json | jq -r '.[0].status') - if [ "$status" = "active" ]; then - break - fi - sleep 2 + status=$(doctl compute droplet get "$droplet_id" --output json | jq -r '.[0].status') + if [ "$status" = "active" ]; then + break + fi + sleep 2 done # Get the public and private IP addresses, guaranteed to be at index zero as we limit names droplet_pub_ipv4=$(doctl compute droplet get "$droplet_id" --output json | jq -r '.[0].networks.v4[] | select(.type == "public") | .ip_address') droplet_priv_ipv4=$(doctl compute droplet get "$droplet_id" --output json | jq -r '.[0].networks.v4[] | select(.type == "private") | .ip_address') - echo "Droplet is active!, public IP: $droplet_pub_ipv4, private IP: $droplet_priv_ipv4" notify "> Droplet **$1** is active at __ $droplet_pub_ipv4 __" # Wait for SSH to become available echo "Waiting for SSH to be available..." while ! ssh -o StrictHostKeyChecking=no -q root@"$droplet_priv_ipv4" exit; do - sleep 5 + sleep 5 done echo "SSH is available!" - # Run the Ansible playbook once SSH is up echo "Running Ansible playbook..." update_inventory diff --git a/automation/playbooks/initialize_worker.yml b/automation/playbooks/initialize_worker.yml index baa56c6..1cb26c2 100644 --- a/automation/playbooks/initialize_worker.yml +++ b/automation/playbooks/initialize_worker.yml @@ -149,7 +149,7 @@ module: ansible.builtin.shell cmd: "docker swarm join-token worker -q" register: join_token -# this works docker swarm join --token TOKLENNNNNNNNN 10.137.0.5:2377 + # this works docker swarm join --token TOKLENNNNNNNNN 10.137.0.5:2377 - name: 'Join the Swarm as a worker' run_once: true community.docker.docker_swarm: diff --git a/automation/playbooks/roles/jsoncameron.docker/README.md b/automation/playbooks/roles/jsoncameron.docker/README.md index e679eb4..157c950 100644 --- a/automation/playbooks/roles/jsoncameron.docker/README.md +++ b/automation/playbooks/roles/jsoncameron.docker/README.md @@ -22,12 +22,15 @@ docker_packages: docker_packages_state: present ``` -The `docker_edition` should be either `ce` (Community Edition) or `ee` (Enterprise Edition). -You can also specify a specific version of Docker to install using the distribution-specific format: +The `docker_edition` should be either `ce` (Community Edition) or `ee` (Enterprise Edition). +You can also specify a specific version of Docker to install using the distribution-specific format: Red Hat/CentOS: `docker-{{ docker_edition }}-` (Note: you have to add this to all packages); Debian/Ubuntu: `docker-{{ docker_edition }}=` (Note: you have to add this to all packages). -You can control whether the package is installed, uninstalled, or at the latest version by setting `docker_packages_state` to `present`, `absent`, or `latest`, respectively. Note that the Docker daemon will be automatically restarted if the Docker package is updated. This is a side effect of flushing all handlers (running any of the handlers that have been notified by this and any other role up to this point in the play). +You can control whether the package is installed, uninstalled, or at the latest version by setting +`docker_packages_state` to `present`, `absent`, or `latest`, respectively. Note that the Docker daemon will be +automatically restarted if the Docker package is updated. This is a side effect of flushing all handlers (running any of +the handlers that have been notified by this and any other role up to this point in the play). ```yaml docker_obsolete_packages: @@ -39,7 +42,9 @@ docker_obsolete_packages: - runc ``` -A list of packages to be uninstalled prior to running this role. See [Docker's installation instructions](https://docs.docker.com/engine/install/debian/#uninstall-old-versions) for an up-to-date list of old packages that should be removed. +A list of packages to be uninstalled prior to running this role. +See [Docker's installation instructions](https://docs.docker.com/engine/install/debian/#uninstall-old-versions) for an +up-to-date list of old packages that should be removed. ```yaml docker_service_manage: true @@ -48,7 +53,8 @@ docker_service_enabled: true docker_restart_handler_state: restarted ``` -Variables to control the state of the `docker` service, and whether it should start on boot. If you're installing Docker inside a Docker container without systemd or sysvinit, you should set `docker_service_manage` to `false`. +Variables to control the state of the `docker` service, and whether it should start on boot. If you're installing Docker +inside a Docker container without systemd or sysvinit, you should set `docker_service_manage` to `false`. ```yaml docker_install_compose_plugin: false @@ -56,7 +62,8 @@ docker_compose_package: docker-compose-plugin docker_compose_package_state: present ``` -Docker Compose Plugin installation options. These differ from the below in that docker-compose is installed as a docker plugin (and used with `docker compose`) instead of a standalone binary. +Docker Compose Plugin installation options. These differ from the below in that docker-compose is installed as a docker +plugin (and used with `docker compose`) instead of a standalone binary. ```yaml docker_install_compose: true @@ -71,7 +78,8 @@ Docker Compose installation options. docker_add_repo: true ``` -Controls whether this role will add the official Docker repository. Set to `false` if you want to use the default docker packages for your system or manage the package repository on your own. +Controls whether this role will add the official Docker repository. Set to `false` if you want to use the default docker +packages for your system or manage the package repository on your own. ```yaml docker_repo_url: https://download.docker.com/linux @@ -91,7 +99,10 @@ docker_apt_filename: "docker" (Used only for Debian/Ubuntu.) You can switch the channel to `nightly` if you want to use the Nightly release. You can change `docker_apt_gpg_key` to a different url if you are behind a firewall or provide a trustworthy mirror. -Usually in combination with changing `docker_apt_repository` as well. `docker_apt_filename` controls the name of the source list file created in `sources.list.d`. If you are upgrading from an older (<7.0.0) version of this role, you should change this to the name of the existing file (e.g. `download_docker_com_linux_debian` on Debian) to avoid conflicting lists. +Usually in combination with changing `docker_apt_repository` as well. `docker_apt_filename` controls the name of the +source list file created in `sources.list.d`. If you are upgrading from an older (<7.0.0) version of this role, you +should change this to the name of the existing file (e.g. `download_docker_com_linux_debian` on Debian) to avoid +conflicting lists. ```yaml docker_yum_repo_url: "{{ docker_repo_url }}/{{ (ansible_distribution == 'Fedora') | ternary('fedora','centos') }}/docker-{{ docker_edition }}.repo" @@ -124,7 +135,9 @@ Custom `dockerd` options can be configured through this dictionary representing ## Use with Ansible (and `docker` Python library) -Many users of this role wish to also use Ansible to then _build_ Docker images and manage Docker containers on the server where Docker is installed. In this case, you can easily add in the `docker` Python library using the `geerlingguy.pip` role: +Many users of this role wish to also use Ansible to then _build_ Docker images and manage Docker containers on the +server where Docker is installed. In this case, you can easily add in the `docker` Python library using the +`geerlingguy.pip` role: ```yaml - hosts: all @@ -158,8 +171,10 @@ MIT / BSD * [We Manage](https://we-manage.de): Helping start-ups and grown-ups scaling their infrastructure in a sustainable way. -The above sponsor(s) are supporting Jeff Geerling on [GitHub Sponsors](https://github.com/sponsors/geerlingguy). You can sponsor Jeff's work too, to help him continue improving these Ansible open source projects! +The above sponsor(s) are supporting Jeff Geerling on [GitHub Sponsors](https://github.com/sponsors/geerlingguy). You can +sponsor Jeff's work too, to help him continue improving these Ansible open source projects! ## Author Information -This role was created in 2017 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/). +This role was created in 2017 by [Jeff Geerling](https://www.jeffgeerling.com/), author +of [Ansible for DevOps](https://www.ansiblefordevops.com/). diff --git a/automation/playbooks/roles/jsoncameron.docker/defaults/main.yml b/automation/playbooks/roles/jsoncameron.docker/defaults/main.yml index 7449b5b..55c1a4a 100644 --- a/automation/playbooks/roles/jsoncameron.docker/defaults/main.yml +++ b/automation/playbooks/roles/jsoncameron.docker/defaults/main.yml @@ -59,7 +59,7 @@ docker_yum_repo_enable_test: '0' docker_yum_gpg_key: "{{ docker_repo_url }}/centos/gpg" # A list of users who will be added to the docker group. -docker_users: [] +docker_users: [ ] # Docker daemon options as a dict -docker_daemon_options: {} +docker_daemon_options: { } diff --git a/automation/playbooks/update.yml b/automation/playbooks/update.yml index c571bdf..9a21bf1 100644 --- a/automation/playbooks/update.yml +++ b/automation/playbooks/update.yml @@ -38,13 +38,13 @@ - name: Remove outdated docker artifacts ansible.builtin.include_tasks: "tasks/cleanup.yml" -# - name: Update docker stack -# docker_stack: -# state: present -# name: wlmoj -# compose: -# - /home/judge/docker/dmoj/docker-stack.yml -# when: ansible_hostname == "general" + # - name: Update docker stack + # docker_stack: + # state: present + # name: wlmoj + # compose: + # - /home/judge/docker/dmoj/docker-stack.yml + # when: ansible_hostname == "general" - name: Update packages apt: diff --git a/automation/remove_droplet.sh b/automation/remove_droplet.sh index 7d18620..b6801f5 100755 --- a/automation/remove_droplet.sh +++ b/automation/remove_droplet.sh @@ -1,19 +1,19 @@ #!/usr/bin/env bash -if [ "$EUID" -ne 0 ] - then echo "Please run as root" +if [ "$EUID" -ne 0 ]; then + echo "Please run as root" exit fi -if [ "$HOSTNAME" != "general" ] - then echo "Please run on general" +if [ "$HOSTNAME" != "general" ]; then + echo "Please run on general" exit fi set -e cd "$( - cd "$(dirname "${BASH_SOURCE[0]}")" - pwd -P + cd "$(dirname "${BASH_SOURCE[0]}")" + pwd -P )" . ../dmoj/scripts/utils/notify @@ -24,37 +24,37 @@ echo "----------------------------------------------" echo "Available Droplets:" function select_droplet() { - options=() - while read -r line; do - name=$(echo "$line" | awk '{print $1}') - id=$(echo "$line" | awk '{print $2}') - options+=("$name (ID: $id)") - done < <(doctl compute droplet list --format "Name,ID" --no-header) + options=() + while read -r line; do + name=$(echo "$line" | awk '{print $1}') + id=$(echo "$line" | awk '{print $2}') + options+=("$name (ID: $id)") + done < <(doctl compute droplet list --format "Name,ID" --no-header) - PS3="Choose an entry: " - COLUMNS=12 - select option in "${options[@]}" Exit; do - case $option in - Exit) - echo "Exiting..." - exit 0 - ;; - *) - if [[ -n $option ]]; then # Check if a valid choice was made - # Extract name and ID from selected option - droplet_name=$(echo "$option" | cut -d' ' -f1) - # shellcheck disable=SC2116 - droplet_id=$(echo "$option" | grep -oP '(?<=ID: )\d+') - break - else - echo "Invalid selection." - exit 1 + PS3="Choose an entry: " + COLUMNS=12 + select option in "${options[@]}" Exit; do + case $option in + Exit) + echo "Exiting..." + exit 0 + ;; + *) + if [[ -n $option ]]; then # Check if a valid choice was made + # Extract name and ID from selected option + droplet_name=$(echo "$option" | cut -d' ' -f1) + # shellcheck disable=SC2116 + droplet_id=$(echo "$option" | grep -oP '(?<=ID: )\d+') + break + else + echo "Invalid selection." + exit 1 - fi - ;; - esac - done - echo "$droplet_name $droplet_id" # Return both name and ID + fi + ;; + esac + done + echo "$droplet_name $droplet_id" # Return both name and ID } droplet_name_and_id=($(select_droplet)) # Store both name and ID in an array @@ -67,50 +67,50 @@ force_removal=false # Check for arguments and set force_removal if --force is provided while [[ $# -gt 0 ]]; do - case "$1" in - --force | -f) - force_removal=true - shift - ;; - *) - echo "Unknown option: $1" >&2 - exit 1 - ;; - esac + case "$1" in + --force | -f) + force_removal=true + shift + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac done if docker node ls | grep -q "$droplet_name"; then - echo "Warning: Droplet $droplet_name is part of the Swarm cluster." + echo "Warning: Droplet $droplet_name is part of the Swarm cluster." - if $force_removal; then - echo "Forcing removal of node $droplet_name from Swarm..." - docker node rm -f "$droplet_name" - else - echo "Draining node $droplet_name from Swarm..." - docker node update --availability drain "$droplet_name" - while ! docker node ps "$droplet_name" -q --filter "desired-state=Ready"; do - echo "Waiting for node to drain..." - sleep 5 - done - sleep 5 # Wait for the services to shutdown - echo "Droplet is fully drained + if $force_removal; then + echo "Forcing removal of node $droplet_name from Swarm..." + docker node rm -f "$droplet_name" + else + echo "Draining node $droplet_name from Swarm..." + docker node update --availability drain "$droplet_name" + while ! docker node ps "$droplet_name" -q --filter "desired-state=Ready"; do + echo "Waiting for node to drain..." + sleep 5 + done + sleep 5 # Wait for the services to shutdown + echo "Droplet is fully drained Removing node $droplet_name from Swarm..." - notify "## Removing Node: **$droplet_name** from Swarm" - node_ip=$(get_ip_from_node "$droplet_name") - ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@"$node_ip" "docker swarm leave" - sleep 3 - docker node rm "$droplet_name" --force - fi + notify "## Removing Node: **$droplet_name** from Swarm" + node_ip=$(get_ip_from_node "$droplet_name") + ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@"$node_ip" "docker swarm leave" + sleep 3 + docker node rm "$droplet_name" --force + fi fi read -r -p "Are you sure you want to delete Droplet \"$droplet_name?\" (please enter the droplet's name) " confirm_name if [ "$confirm_name" == "$droplet_name" ]; then - echo "Deleting droplet $droplet_name..." - notify "## Deleting Droplet: **$droplet_name**" - notify "> Droplet **$droplet_name** has been removed from the Swarm cluster. Deleting droplet..." - doctl compute droplet delete "$droplet_id" -f - notify "> Droplet **$droplet_name** is deleted!" - update_inventory + echo "Deleting droplet $droplet_name..." + notify "## Deleting Droplet: **$droplet_name**" + notify "> Droplet **$droplet_name** has been removed from the Swarm cluster. Deleting droplet..." + doctl compute droplet delete "$droplet_id" -f + notify "> Droplet **$droplet_name** is deleted!" + update_inventory else - echo "Deletion cancelled." + echo "Deletion cancelled." fi diff --git a/automation/swarm_info b/automation/swarm_info index 5fb02f4..2648677 100755 --- a/automation/swarm_info +++ b/automation/swarm_info @@ -4,7 +4,7 @@ get_worker_ips() { # check if there are any workers local workers - workers="$(doctl compute droplet list --format PrivateIPv4 --tag-name worker --no-header )" + workers="$(doctl compute droplet list --format PrivateIPv4 --tag-name worker --no-header)" if [ -z "$workers" ]; then return @@ -14,7 +14,7 @@ get_worker_ips() { get_manager_ips() { # check if there are any workers local managers - managers="$(doctl compute droplet list --format PrivateIPv4 --tag-name manager --no-header )" + managers="$(doctl compute droplet list --format PrivateIPv4 --tag-name manager --no-header)" if [ -z "$managers" ]; then return @@ -31,14 +31,14 @@ get_replica_ips() { for node in $nodes; do # Get IP address of the node - data=$(docker node inspect --format '{{.Description.Hostname}} {{.Status.Addr}}' "$node") - echo "$data" + data=$(docker node inspect --format '{{.Description.Hostname}} {{.Status.Addr}}' "$node") + echo "$data" done } fetch_inventory() { -# echo "ansible_ssh_common_args=\"-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\"" + # echo "ansible_ssh_common_args=\"-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\"" echo "[managers]" # todo: if we have multiple managers, we need to place general first get_manager_ips echo "[workers]" @@ -46,7 +46,7 @@ fetch_inventory() { } update_inventory() { - fetch_inventory > ./inventory.ini + fetch_inventory >./inventory.ini } get_ip_from_node() { diff --git a/automation/update_nodes.sh b/automation/update_nodes.sh index 06a7a40..a6645a8 100755 --- a/automation/update_nodes.sh +++ b/automation/update_nodes.sh @@ -1,11 +1,14 @@ #!/usr/bin/env bash set -e -if [ "$EUID" -ne 0 ] - then echo "Please run as root" +if [ "$EUID" -ne 0 ]; then + echo "Please run as root" exit fi -cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )" || exit 1 # cd to the directory of the script to ensure relative paths work +cd "$( + cd "$(dirname "${BASH_SOURCE[0]}")" + pwd -P +)" || exit 1 # cd to the directory of the script to ensure relative paths work ansible-playbook -i inventory.ini playbooks/update.yml diff --git a/automation/vm-host-problem-watch b/automation/vm-host-problem-watch index d08d98a..740d154 100755 --- a/automation/vm-host-problem-watch +++ b/automation/vm-host-problem-watch @@ -15,19 +15,19 @@ fi . ./swarm_info function get_judges() { - local filter_type="$1" - local container_names=() - for container_name in $(docker service ls --filter name='judge_' --format "{{.$filter_type}}"); do - container_names+=("$container_name") - done + local filter_type="$1" + local container_names=() + for container_name in $(docker service ls --filter name='judge_' --format "{{.$filter_type}}"); do + container_names+=("$container_name") + done - echo "${container_names[@]}" + echo "${container_names[@]}" } function formatted_judges() { local judges judges="$(get_judges Name)" - echo "${judges[@]// /, }" # Replace spaces with commas and spaces + echo "${judges[@]// /, }" # Replace spaces with commas and spaces } function formatted_time() { @@ -40,11 +40,9 @@ function format_problem() { } - problem_storage_root="$(realpath "$1")" recent_notifs_file=$(mktemp) - problem_notify "$(formatted_time): Watching ${problem_storage_root}, notifying judges **$(formatted_judges)**" inotifywait -rm "${problem_storage_root}" -e move,create,delete -q | while read -r line; do @@ -60,20 +58,20 @@ inotifywait -rm "${problem_storage_root}" -e move,create,delete -q | while read # Check if this directory has been notified recently if ! grep -q "^${problem}:" "$recent_notifs_file"; then - echo "${problem}:$(date +%s)" >> "$recent_notifs_file" + echo "${problem}:$(date +%s)" >>"$recent_notifs_file" if [ "$(echo "$line" | cut -d' ' -f2)" = "DELETE" ]; then problem_notify "-# $(formatted_time): Deleted $problem on **$(formatted_judges)** | __**$n_problems**__ problems in share" elif [ "$(echo "$line" | cut -d' ' -f2)" = "CREATE" ]; then - problem_notify "-# $(formatted_time): Created $(format_problem "$problem") on **$(formatted_judges)** | __**$n_problems**__ problems in share" + problem_notify "-# $(formatted_time): Created $(format_problem "$problem") on **$(formatted_judges)** | __**$n_problems**__ problems in share" else # Must be a UPDATE (move) - problem_notify "-# $(formatted_time): Updated $(format_problem "$problem") on **$(formatted_judges)** | __**$n_problems**__ problems in share" + problem_notify "-# $(formatted_time): Updated $(format_problem "$problem") on **$(formatted_judges)** | __**$n_problems**__ problems in share" fi # If curl_container doesnt exist, create it if ! docker ps -a --format "{{.Names}}" | grep -q "curl_container"; then - docker run -d --rm --network wlmoj_judge --name curl_container curlimages/curl sleep infinity + docker run -d --rm --network wlmoj_judge --name curl_container curlimages/curl sleep infinity fi judges="$(get_judges Name)" @@ -86,5 +84,5 @@ inotifywait -rm "${problem_storage_root}" -e move,create,delete -q | while read # Clean up old entries (older than 10 seconds) current_time=$(date +%s) temp_file_content=$(awk -v now="$current_time" '{split($0,a,":"); if (now - a[2] <= 10) print $0}' "$recent_notifs_file") - echo "$temp_file_content" > "$recent_notifs_file" -done \ No newline at end of file + echo "$temp_file_content" >"$recent_notifs_file" +done