Setting & Retrieving Ansible-Solace Log Files

When running Ansible Playbooks on a remote host, e.g. a ‘bastion’ or ‘jump’ host, we want to retrieve the log files generated by the Ansible-Solace modules to our local host (our Ansible controller) for debugging purposes.

Consider the following inventory file:

  • describes a bastion host

  • describes a solace cloud service

---
all:
  hosts:
    my-solace-cloud-service: # name of solace cloud service
      # start: bastion host config
      ansible_become: true
      ansible_host: {ip-address-of-bastion-host}
      ansible_python_interpreter: /usr/bin/python3
      ansible_user: {ansible-user-on-bastion-host}
      # log path on bastion host
      # note: ensure that the ansible_user (here: root) has write access to the path
      ansible_solace_log_base_path: /var/local
      # end: bastion host config
      # start: solace cloud service config
      broker_type: solace_cloud
      meta:
        datacenterId: aws-ca-central-1a
        sc_service_id: d9x91ert6e
        serviceClassDisplayedAttributes:
          Clients: '250'
          High Availability: HA Group
          Message Broker Tenancy: Dedicated
          Network Speed: 450 Mbps
          Network Usage: 50 GB per month
          Queues: '250'
          Storage: 25 GB
        serviceClassId: enterprise-250-nano
        serviceTypeId: enterprise
        service_name: asct_sc_bastion_2
      sempv2_host: {dns-or-ip-of-semp-service-of-broker-service}
      sempv2_is_secure_connection: true
      sempv2_password: {password}
      sempv2_port: 943
      sempv2_timeout: '60'
      sempv2_username: {username}
      solace_cloud_service_id: d9x91ert6e
      virtual_router: primary
      vpn: my-solace-cloud-service
      # end: solace cloud service config

We can use the following playbook to:

  • create a dynamic log file name with date/time stamp & inventory hostname

  • define & setup two handlers, one to fetch the log file from the remote host, the other one to delete it

  • a block for all the ansible-solace tasks:

    • this ensures the handlers are always executed, regardless of error or success

    • set the environment variables for logging: ANSIBLE_SOLACE_ENABLE_LOGGING & ANSIBLE_SOLACE_LOG_PATH

  • a variable ANSIBLE_SOLACE_LOCAL_LOG_BASE_PATH with the path on the ansible controller for the log files

hosts: all
gather_facts: yes
any_errors_fatal: true
collections:
  - solace.pubsub_plus
module_defaults:
  # ... define additional module defaults
  solace_queue:
    host: "{{ sempv2_host }}"
    port: "{{ sempv2_port }}"
    secure_connection: "{{ sempv2_is_secure_connection }}"
    username: "{{ sempv2_username }}"
    password: "{{ sempv2_password }}"
    timeout: "{{ sempv2_timeout }}"
    msg_vpn: "{{ vpn }}"
handlers:
- name: Fetch log file
  fetch:
    src: "{{ remote_ansible_solace_log_path }}"
    dest: "{{ ANSIBLE_SOLACE_LOCAL_LOG_BASE_PATH }}/"
    flat: yes
    fail_on_missing: no
  listen: log-file-handler
  no_log: true
- name: Delete log file
  file:
    path: "{{ remote_ansible_solace_log_path }}"
    state: absent
  listen: log-file-handler
pre_tasks:
  # generate the name of the log file with timestamp and inventory host
- set_fact:
    # Note: use this custom formatting, no ':' in file name!
    date_time_file: "{{ lookup('pipe','date +%Y-%m-%d-%H-%M-%S') }}"
- set_fact:
    # e.g. resulting in: /var/local/my-solace-cloud-service.2021-05-14-09-01-00.ansible-solace.log
    remote_ansible_solace_log_path: "{{ ansible_solace_log_base_path }}/{{ inventory_hostname }}.{{ date_time_file }}.ansible-solace.log"
tasks:
  # ensure the handler is notified at least once
- name: Set up Handler
  debug:
    msg: setup handler
  changed_when: true
  notify: log-file-handler

- name: Block of ansible-solace tasks
  block:
  - name: Create Queue
    solace_queue:
      name: my-queue
      state: present
  environment:
    ANSIBLE_SOLACE_ENABLE_LOGGING: true
    ANSIBLE_SOLACE_LOG_PATH: "{{ remote_ansible_solace_log_path }}"
  always:
    # ensure handlers are called no matter if a task inside the block fails or not
    - meta: flush_handlers

… and call the playbook with the local log path:

bastionVmPrivateKeyFile="bastionvm_key"
ansibleSolaceLocalLogBasePath="my/path/to/my/log/files"
mkdir -p $ansibleSolaceLocalLogBasePath
ansible-playbook \
              -i inventory.yml \
              playbook.yml \
              --private-key $bastionVmPrivateKeyFile \
              --extra-vars "ANSIBLE_SOLACE_LOCAL_LOG_BASE_PATH=$ansibleSolaceLocalLogBasePath"