ansiblescheduleansible-awxansible-tower

Schedule deletion of unused template


In Ansible Tower, is there a possibility to create a scheduled task that checks if a template has not been executed for one year and if so, deletes it?


Solution

  • The short answers is: yes, of course. The long answer is: someone has to create such task. To do so, one may getting familiar with the Ansible Tower REST API, in detail Job Templates - List Jobs for a Job Template.

    In example, a call for Jobs of a Job Template which was never executed

    curl --silent --user ${ACCOUNT}:${PASSWORD} https://${TOWER_URL}/api/v2/job_templates/${ID}/jobs/ --write-out "\n%{http_code}\n"| jq .
    

    would result into an output of

    {
      "count": 0,
      "next": null,
      "previous": null,
      "results": []
    }
    200
    

    A call for Jobs of a Job Template which is executed daily would result into an output of

    {
      "count": 70,
      "next": "/api/v2/job_templates/<id>/jobs/?page=2",
      "previous": null,
      "results": [
        {
          "id": <id>,
        <snip>
          "created": "2022-06-10T05:57:18.976798Z",
          "modified": "2022-06-10T05:57:19.666354Z",
          "name": "<name>",
          "description": "<description>",
          "unified_job_template": <id>,
          "launch_type": "manual",
          "status": "successful",
          "failed": false,
          "started": "2022-06-10T05:57:19.870208Z",
          "finished": "2022-06-10T05:57:33.752072Z",
          "canceled_on": null,
          "elapsed": 13.882,
          "job_explanation": "",
          "execution_node": "<executionNode>",
          "controller_node": "",
          "job_type": "run",
          "inventory": <id>,
          "project": <id>,
          "playbook": "<path>",
          "scm_branch": "",
          "forks": 0,
          "limit": "<hostgroup>",
          "verbosity": 0,
          "extra_vars": "{\"if_there_any\": \"false\"}",
          "job_tags": "check",
          "force_handlers": false,
          "skip_tags": "",
          "start_at_task": "",
          "timeout": 0,
          "use_fact_cache": false,
          "organization": <id>,
          "job_template": <id>,
          "passwords_needed_to_start": [
            "ssh_password"
          ],
          "allow_simultaneous": false,
          "artifacts": {},
          "scm_revision": "<rev>",
          "instance_group": 1,
          "diff_mode": false,
          "job_slice_number": 0,
          "job_slice_count": 1,
          "webhook_service": "",
          "webhook_credential": null,
          "webhook_guid": ""
        }
      ]
    }
    200
    

    Since the goal is to execute it via Ansible Engine, as well schedule via Ansible Tower, a sample rest.yml playbook

    ---
    - hosts: localhost
      become: false
      gather_facts: false
    
      vars:
    
        TOWER_API_URL: "<tower_url>/api/v2"
        FILTER: ".version"
        ID: "<id>"
    
      tasks:
    
      - name: Example REST API call
        shell:
          cmd: curl --silent -u '{{ ansible_user }}:{{ ansible_password }}' --location {{ TOWER_API_URL }}/ping | jq {{ FILTER }}
          warn: false
        register: result
        failed_when: result.rc != 0
        changed_when: false
        check_mode: false
    
      - name: Show result
        debug:
          msg: "{{ result.stdout }}"
    
      - name: List Jobs for a Job Template
        uri:
          url: "https://{{ TOWER_API_URL }}/job_templates/{{ ID }}/jobs/"
          user: "{{ ansible_user }}"
          password: "{{ ansible_password }}"
          force_basic_auth: true
          method: GET
          validate_certs: yes
          return_content: yes
          status_code: 200
          body_format: json
        check_mode: false
        register: result
    
      - name: Show result
        debug:
          msg: "{{ result.json.results }}" # list of jobs
    

    which can be called from CLI via

    sshpass -p ${PASSWORD} ansible-playbook --user ${ACCOUNT} --ask-pass rest.yml
    

    Please take note that the "count": 70 is greater than the result set result.json.results | length of 25 and there is a next page mentioned "next": "...?page=2". The result.json.results | last therefore does not contain the most recent execution. This is because of Pagination.

    Depending on the setup and actual configuration of Ansible Tower one may need to adjust the page_size. In example to get the most recent result

    ...
          url: "https://{{ TOWER_API_URL }}/job_templates/{{ ID }}/jobs/?page_size=100"
    ...
          msg: "{{ result.json.results | last }}"