# update_broker_kafka-ui.yml - name: Update Kafka broker3 and Redpanda Console on VM via Proxmox hosts: proxmox gather_facts: false become: true become_user: root become_method: sudo vars: # --- Connection to VM (provided by Semaphore env vars) --- vm_ip: "{{ lookup('env', 'VM_IP') }}" vm_user: "{{ lookup('env', 'VM_USER') }}" vm_pass: "{{ lookup('env', 'VM_PASS') }}" use_sudo: false # --- Debug mode (controlled via Semaphore variable) --- DEBUG: "{{ lookup('env', 'DEBUG') | default(0) | int }}" RETRIES: "{{ lookup('env', 'RETRIES') | default(25) | int }}" # --- Kafka / Redpanda Console specifics --- kafka_project: "kafka" # Adjusted to match your actual compose file location kafka_compose_file: "/data/compose/docker-compose.yml" kafka_services: - broker3 - kafka-ui redpanda_console_port: 8084 # Controller-side URL (default to direct VM IP/port or external URL) redpanda_console_url: "{{ lookup('env', 'REDPANDA_CONSOLE_URL') | default('http://192.168.69.254:8084/overview', true) }}" redpanda_retries: "{{ RETRIES }}" redpanda_delay: 2 # Docker command prefix (consistent behavior and quiet hints) docker_prefix: "unalias docker 2>/dev/null || true; DOCKER_CLI_HINTS=0; command docker" # Commands to run on the target VM (quiet outputs) # 1) Pull latest images for broker3 + kafka-ui # 2) Stop any running containers with these names (legacy or compose-managed) # 3) Remove any containers with these names to avoid name conflicts # 4) Recreate services via docker compose kafka_commands: - "{{ docker_prefix }} compose -p {{ kafka_project }} -f {{ kafka_compose_file }} pull {{ kafka_services | join(' ') }} >/dev/null" - "{{ docker_prefix }} stop {{ kafka_services | join(' ') }} >/dev/null 2>&1 || true" - "{{ docker_prefix }} rm -f {{ kafka_services | join(' ') }} >/dev/null 2>&1 || true" - "{{ docker_prefix }} compose -p {{ kafka_project }} -f {{ kafka_compose_file }} up -d --no-deps --force-recreate {{ kafka_services | join(' ') }} >/dev/null" tasks: - name: Ensure sshpass is installed (for password-based SSH) # English comments ansible.builtin.apt: name: sshpass state: present update_cache: yes - name: Run Kafka update commands on VM (via SSH) # use SSHPASS env, hide item value ansible.builtin.command: argv: - sshpass - -e # read password from SSHPASS environment - ssh - -o - StrictHostKeyChecking=no - -o - ConnectTimeout=15 - "{{ vm_user }}@{{ vm_ip }}" - bash - -lc - "{{ ('sudo ' if use_sudo else '') + item }}" environment: SSHPASS: "{{ vm_pass }}" # supply password via environment loop: "{{ kafka_commands }}" loop_control: index_var: idx # capture loop index label: "cmd-{{ idx }}" # avoid printing full command in (item=...) line register: kafka_cmds changed_when: false no_log: "{{ DEBUG == 0 }}" # hide outputs and env when not debugging - name: Show outputs for each Kafka command ansible.builtin.debug: msg: | CMD: {{ item.item }} RC: {{ item.rc }} STDOUT: {{ (item.stdout | default('')).strip() }} STDERR: {{ (item.stderr | default('')).strip() }} loop: "{{ kafka_cmds.results }}" when: DEBUG == 1 - name: Fail play if any Kafka command failed # also hide item label ansible.builtin.assert: that: "item.rc == 0" fail_msg: "Kafka/Redpanda Console update failed on VM: {{ item.item }} (rc={{ item.rc }})" success_msg: "All Kafka/Redpanda Console update commands succeeded." loop: "{{ kafka_cmds.results }}" loop_control: index_var: idx label: "cmd-{{ idx }}" # ------------------------- # Readiness check – Redpanda Console UI # ------------------------- - name: Redpanda Console | Wait for overview page (controller, with retries) ansible.builtin.uri: url: "{{ redpanda_console_url }}" method: GET return_content: true validate_certs: false # plain HTTP on 192.168.69.254 (or as configured) status_code: 200 register: redpanda_controller delegate_to: localhost run_once: true when: redpanda_console_url is defined and (redpanda_console_url | length) > 0 retries: "{{ redpanda_retries }}" delay: "{{ redpanda_delay }}" until: redpanda_controller.status == 200 failed_when: false changed_when: false - name: Redpanda Console | Print concise summary ansible.builtin.debug: msg: >- Redpanda Console overview {{ 'reachable' if (redpanda_controller is defined and (redpanda_controller.status|default(0))==200) else 'NOT reachable' }}. status={{ redpanda_controller.status | default('n/a') }}; length={{ (redpanda_controller.content | default('')) | length }}; when: DEBUG == 1 and (redpanda_controller is defined) # Optional detailed dump (short excerpt only) - name: Redpanda Console | HTML excerpt (debug) ansible.builtin.debug: msg: "{{ (redpanda_controller.content | default(''))[:500] }}" when: DEBUG == 1 and (redpanda_controller is defined) and (redpanda_controller.content is defined) # ------------------------- # Final assertion: Console URL must be reachable # ------------------------- - name: Redpanda Console | Assert overview reachable (if URL configured) ansible.builtin.assert: that: - > not (redpanda_console_url is defined and (redpanda_console_url | length) > 0) or ( redpanda_controller is defined and (redpanda_controller.status | default(0)) == 200 ) fail_msg: "Redpanda Console URL {{ redpanda_console_url }} is NOT reachable with HTTP 200 after retries." success_msg: "Redpanda Console URL {{ redpanda_console_url }} is reachable with HTTP 200."