--- # --- на jump-хосте (один раз) ------------------------------------------- - name: Check that the env file exists on the jump host ansible.builtin.stat: path: "{{ local_env_file }}" delegate_to: localhost become: false run_once: true check_mode: false register: env_file_stat - name: Fail early without an env file ansible.builtin.assert: that: env_file_stat.stat.exists fail_msg: >- Нет env-файла {{ local_env_file }}. Создайте его: cp env/validator-agent.env.example env/validator-agent.env и заполните. quiet: true run_once: true # Содержимое файла (в нём токен) не выводится: разбор идёт в задаче с no_log, # а проверка и её сообщение — по готовым булевым значениям. - name: Inspect the env file without printing it ansible.builtin.set_fact: env_url_set: "{{ env_file_text is regex('(?m)^VALIDATOR_AGENT_CONTROL_API_URL=\\S+') }}" env_url_is_example: "{{ env_file_text is regex('(?m)^VALIDATOR_AGENT_CONTROL_API_URL=\\S*example\\.com') }}" vars: env_file_text: "{{ lookup('ansible.builtin.file', local_env_file) }}" run_once: true no_log: true - name: Check that the env file sets the control-api address ansible.builtin.assert: that: - env_url_set | bool - not (env_url_is_example | bool) fail_msg: >- В {{ local_env_file }} не задан VALIDATOR_AGENT_CONTROL_API_URL (или остался адрес-пример example.com). quiet: true run_once: true # --- на каждом валидаторе ----------------------------------------------- - name: Check that Docker answers ansible.builtin.command: docker version --format {% raw %}'{{.Server.Version}}'{% endraw %} changed_when: false check_mode: false - name: Check that git is installed ansible.builtin.command: git --version changed_when: false check_mode: false - name: Check that the git clone exists ansible.builtin.stat: path: "{{ repo_dir }}/.git" check_mode: false register: clone_stat - name: Fail without a clone ansible.builtin.assert: that: clone_stat.stat.exists fail_msg: "Нет git-клона {{ repo_dir }} на {{ inventory_hostname }}." quiet: true - name: Read the CPU architecture ansible.builtin.command: uname -m changed_when: false check_mode: false register: arch - name: The image is linux/amd64 only ansible.builtin.assert: that: arch.stdout in ['x86_64', 'amd64'] fail_msg: "Архитектура {{ arch.stdout }}: образ {{ platform }} здесь не запустится (exec format error)." quiet: true - name: Look at the current container ansible.builtin.command: >- docker container inspect --format {% raw %}'{{.Config.Image}} {{.State.Status}}'{% endraw %} {{ container_name }} register: current_container changed_when: false failed_when: false check_mode: false # Защита от второго агента: если на хосте уже есть другой контейнер этого # агента (по имени или по образу), сценарий остановится, а не запустит # рядом ещё один с тем же validator_id. - name: List containers on the validator ansible.builtin.command: docker ps -a --format {% raw %}'{{.Names}}|{{.Image}}'{% endraw %} register: all_containers changed_when: false check_mode: false - name: Check that there is no other agent container ansible.builtin.assert: that: (other_agents | from_json) | length == 0 fail_msg: >- {{ inventory_hostname }}: найден другой контейнер агента: {{ (other_agents | from_json) | join(', ') }}. Сценарий заменяет только контейнер {{ container_name }}. Проверьте container_name в inventory/group_vars/validators.yml или удалите лишний контейнер вручную. quiet: true vars: other_agents: >- {%- set found = [] -%} {%- for line in all_containers.stdout_lines -%} {%- set row = line.split('|') -%} {%- if row[0] != container_name and ('validator-agent' in row[0] or row[1] == image_name or row[1].startswith(image_name ~ ':')) -%} {%- set _ = found.append(row[0] ~ ' (' ~ row[1] ~ ')') -%} {%- endif -%} {%- endfor -%} {{- found | to_json -}} # validator_id работающего контейнера — эталон: если он отличается от # inventory, заменять контейнер нельзя (агент зарегистрировался бы под чужим # именем, адреса привязывались бы к порту другой ВМ). Выводится только он, # а не все переменные окружения (там токен). - name: Read validator_id of the running container ansible.builtin.shell: | set -o pipefail docker container inspect --format '{% raw %}{{range .Config.Env}}{{println .}}{{end}}{% endraw %}' {{ container_name }} \ | sed -n 's/^VALIDATOR_AGENT_VALIDATOR_ID=//p' args: executable: /bin/bash register: running_validator_id changed_when: false failed_when: false check_mode: false when: current_container.rc == 0 - name: Check validator_id against the running container ansible.builtin.assert: that: >- current_container.rc != 0 or (running_validator_id.stdout | trim) == '' or (running_validator_id.stdout | trim) == effective_validator_id fail_msg: >- {{ inventory_hostname }}: в запущенном контейнере validator_id={{ running_validator_id.stdout | default('') | trim }}, а в inventory {{ effective_validator_id }}. Проверьте соответствие имени ВМ и validator_id в inventory/hosts.yml; контейнер не тронут. quiet: true - name: Report the current container ansible.builtin.debug: msg: >- {{ container_name }}: {{ current_container.stdout if current_container.rc == 0 else 'контейнера нет (будет создан)' }}; validator_id для запуска: {{ effective_validator_id }}