diff --git a/provision-contest/ansible/hosts b/provision-contest/ansible/hosts index 7286b888..c442eb63 100644 --- a/provision-contest/ansible/hosts +++ b/provision-contest/ansible/hosts @@ -9,6 +9,7 @@ ansible_python_interpreter=/usr/bin/python3 domserver judgehost grafana +scriptserver admin [online:children] @@ -70,6 +71,11 @@ domjudge-ccsadmin5 ansible_host=10.3.3.228 # Doesn't matter which (admin) machine but should not be 1 as that runs ansible domjudge-ccsadmin2 ansible_host=10.3.3.225 +[scriptserver] +# During the WFs we use one of the ccsadmin machines +# Doesn't matter which (admin) machine but in the past we used 1 as that runs ansible +domjudge-ccsadmin1 ansible_host=10.3.3.224 + [analyst-domserver] # Discuss if we can have this host dualhomed in blue to make management easier.\ # Looking at the IP sheet that would mean that our emergency laptop needs to move. diff --git a/provision-contest/ansible/roles/script_server/defaults/main.yml b/provision-contest/ansible/roles/script_server/defaults/main.yml new file mode 100644 index 00000000..f6d568c9 --- /dev/null +++ b/provision-contest/ansible/roles/script_server/defaults/main.yml @@ -0,0 +1,55 @@ +--- +SCRIPT_SERVER_PORT: 5000 + +script_server_commands: + - name: make-invocations + description: Run the make targets as last years + parameters: + - name: make_pattern + type: multiselect + separator: ' ' + values: + - admin + - domserver + - judgehost + - grafana + - cds + content: | + #!/bin/bash + set -euxo pipefail + if [ "$make_pattern" = "" ]; then + exit 1 + fi + cd /home/domjudge/domjudge-scripts-checkout/provision-contest/ansible + for make_single in $make_pattern; do + make "$make_single" + done + - name: ansible-admin + description: (Re)configure the (other) admin machines + content: | + #!/bin/bash + set -euxo pipefail + if [ "$host_pattern" = "" ]; then + exit 1 + fi + if [ "$tag_pattern" != "" ]; then + tag="--tags $tag_pattern" + fi + cd /home/domjudge/domjudge-scripts-checkout/provision-contest/ansible + ansible-playbook --limit $host_pattern ${tag:-} admin.yml + parameters: + - name: host_pattern + # pass_as: env_variable # this is default + # env_var: host_pattern # default is same as name + type: multiselect + values: "{{ groups['admin'] }}" + default: "{{ groups['admin'] | difference(['domjudge-ccsadmin2']) }}" + - name: tag_pattern + type: "multiselect" + values: ["reboot"] + default: [] + +script_server_command_defaults: + output_format: terminal + # scheduling: # Don't allow scheduling, the ui for it is not good... + # enabled: false diff --git a/provision-contest/ansible/roles/script_server/files/.gitignore b/provision-contest/ansible/roles/script_server/files/.gitignore new file mode 100644 index 00000000..c4c4ffc6 --- /dev/null +++ b/provision-contest/ansible/roles/script_server/files/.gitignore @@ -0,0 +1 @@ +*.zip diff --git a/provision-contest/ansible/roles/script_server/handlers/main.yml b/provision-contest/ansible/roles/script_server/handlers/main.yml new file mode 100644 index 00000000..1e3e86a1 --- /dev/null +++ b/provision-contest/ansible/roles/script_server/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart script-server + ansible.builtin.service: + name: script-server + state: restarted diff --git a/provision-contest/ansible/roles/script_server/tasks/main.yml b/provision-contest/ansible/roles/script_server/tasks/main.yml new file mode 100644 index 00000000..de770b7a --- /dev/null +++ b/provision-contest/ansible/roles/script_server/tasks/main.yml @@ -0,0 +1,89 @@ +--- +- name: Install script-server dependencies + apt: + name: + - python3-tornado + - apache2-utils # for htpasswd auth + state: present + +- name: Create directory for script-server to live + file: + path: /opt/script-server + mode: "0755" + owner: root + group: root + state: directory + +- name: Install script-server + when: ICPC_IMAGE + unarchive: + src: "script-server.zip" + dest: /opt/script-server + remote_src: false + creates: /opt/script-server/launcher.py + +- name: Install script-server + when: not ICPC_IMAGE + unarchive: + src: "https://github.com/bugy/script-server/releases/download/1.18.0/script-server.zip" + dest: /opt/script-server + remote_src: true + creates: /opt/script-server/launcher.py + +- name: Configure the server + template: + src: conf.json.j2 + dest: /opt/script-server/conf/conf.json + mode: "0644" + owner: root + group: root + +- name: Create systemd service for script-server + notify: Restart script-server + copy: + mode: "0644" + dest: /etc/systemd/system/script-server.service + content: | + [Unit] + Description=Script Server + After=network.target + StartLimitIntervalSec=0 + + [Service] + Type=simple + Restart=always + RestartSec=1 + ExecStart=/usr/bin/python3 /opt/script-server/launcher.py + + [Install] + WantedBy=multi-user.target + +- name: Ensure required directories exist + file: + state: directory + mode: "0755" + path: /opt/script-server/conf/{{ item }} + loop: + - scripts + - runners + +- name: Create scripts + copy: + content: "{{ item.content }}" + dest: /opt/script-server/conf/scripts/{{ item.name }} + mode: "0755" + with_items: "{{ script_server_commands }}" + +- name: Create script config definitions + ansible.builtin.template: + src: command_template.yml.j2 + dest: /opt/script-server/conf/runners/{{ item.name }}.yaml + mode: "0644" + with_items: "{{ script_server_commands }}" + +- name: Start + enable script-server + service: + name: script-server + state: started + enabled: true + diff --git a/provision-contest/ansible/roles/script_server/templates/command_template.yml.j2 b/provision-contest/ansible/roles/script_server/templates/command_template.yml.j2 new file mode 100644 index 00000000..367b3c0f --- /dev/null +++ b/provision-contest/ansible/roles/script_server/templates/command_template.yml.j2 @@ -0,0 +1,44 @@ +--- +{% set _unused_content = item.pop('content') %} +{% set parameters = item.pop('parameters', []) %} +{% set admin_users = groups['admin'] %} +{% set allowed_users = groups['onprem'] %} +{# set admin_users = (admin_users if ( admin_users | type_debug == "list" ) else [admin_users]) #} +{# set allowed_users = (allowed_users if ( allowed_users | type_debug == "list" ) else [allowed_users]) #} +{{ + script_server_command_defaults | + combine(item) | + to_nice_yaml +}} + +{% if admin_users %} +admin_users: + - 127.0.0.1 +{% for u in admin_users %} + - {{ hostvars[u].ansible_host }} +{% endfor %} +{% endif %} +{% if allowed_users %} +skipped_allowed_users: + - 127.0.0.1 +{% for u in (allowed_users + admin_users)|unique %} + - {{ hostvars[u].ansible_host }} +{% endfor %} +{% endif %} + +{% if parameters %} +parameters: +{% for param in parameters %} + - name: {{ param.name }} + pass_as: {{ param.pass_as | default('env_variable') }} +{% if param.pass_as|default('env_variable') == 'env_variable' %} + env_var: {{ param.env_var | default(param.name) }} +{% endif %} +{% for k,v in param.items() if k not in ['pass_as','env_var','name'] %} + {{ k}}: {{ v|to_json }} +{% endfor %} +{% endfor %} +{% endif %} + +# assume default path for the script file +script_path: conf/scripts/{{ item.name }} diff --git a/provision-contest/ansible/roles/script_server/templates/conf.json.j2 b/provision-contest/ansible/roles/script_server/templates/conf.json.j2 new file mode 100644 index 00000000..3fcfa8b4 --- /dev/null +++ b/provision-contest/ansible/roles/script_server/templates/conf.json.j2 @@ -0,0 +1,19 @@ +{ + "title": "sysops script server", + "port": {{ SCRIPT_SERVER_PORT }}, + "access": { + "admin_users": [ + {%- for host in groups['admin'] -%} + "{{ hostvars[host].ansible_host}}", + {% endfor %} + "127.0.0.1" + ] + }, + "logging": { + "execution_file": "$DATE-$ID.log", + "execution_date_format": "%y-%m-%d_%H-%M" + }, + "security": { + "xsrf_protection": "token" + } +} diff --git a/provision-contest/ansible/scriptserver.yml b/provision-contest/ansible/scriptserver.yml new file mode 100644 index 00000000..cabbf334 --- /dev/null +++ b/provision-contest/ansible/scriptserver.yml @@ -0,0 +1,20 @@ +--- + +- hosts: scriptserver + vars: + host_type: scriptserver + become: true + handlers: + - include: handlers.yml + roles: + - role: base_packages + tags: base_packages + - role: icpc_fixes + tags: icpc_fixes + when: ICPC_IMAGE + - role: system_fixes + tags: system_fixes + - role: hosts + tags: hosts + - role: script_server + tags: script_server