1

I have a playbook in Ansible that will allow me to identify a specific set of firewalls, and then update them to a higher version of software. However, I need to take the existing output of my API call and find all instances of "currently installed" versions to ensure that it's not already at the latest version, and remove older instances.

Using this sample XML:

<response status="success">
    <result>
        <sw-updates last-updated-at="2025/10/10 11:11:11">
            <msg/>
            <versions>
                <entry>
                    <version>6.3.1</version>
                    <downloaded>no</downloaded>
                    <current>no</current>
                    <latest>no</latest>
                    <uploaded>no</uploaded>
                    <sha256>7e3505720ecbe981f3ce744b7530844eb2d892f340bcf967b66486112ff11808</sha256>
                </entry>
                <entry>
                    <version>6.3.1-c383</version>
                    <downloaded>no</downloaded>
                    <current>no</current>
                    <latest>no</latest>
                    <uploaded>no</uploaded>
                    <sha256>8a76ee798630ae3669ffe09f5a1805dd531d3cbc7c29b2e37dc6802223775f87</sha256>
                </entry>
                <entry>
                    <version>6.3.0</version>
                    <downloaded>no</downloaded>
                    <current>no</current>
                    <latest>no</latest>
                    <uploaded>no</uploaded>
                    <sha256>67a83ff5206d5b4a2aaf13bce3212de270cabe6204a4df1561c35aa4c1bc0f44</sha256>
                </entry>
            </versions>
        </sw-updates>
    </result>
</response>

I need to do two things:

  1. ID all instances where the string <current>yes</current> occurs, indicating the software is installed and active.
  2. Get the value between <version></version> for all of those instances.

I can do the first, but its super clunky and relies on me knowing the version number to use a specific XPath. Or using regex, which has its own issues. But I have no idea where to even start for the second. I feel like I am overthinking it, and there is a more simple way to gather the data I need.

2
  • sha256 might work as a unique value (id), correct? Commented Oct 14 at 1:41
  • It could, but if I needed a specific desired version irrespective of the SHA value, it would be easier to sort by version number. I might have gotten my answer below, in the process of testing. Commented Oct 14 at 16:22

2 Answers 2

3

Finding the version of entries with current="yes" is trivial in XPath, even XPath 1.0: it's simply //entry[current="yes"]/version

Sign up to request clarification or add additional context in comments.

4 Comments

I need to retrieve all version numbers where the neighboring key shows 'yes' under current. The list I am working with is far longer than this, I just edited it to make it more human-readable. Finding the version of entries with current="yes" is trivial in XPath, even XPath 1.0: it's simply //entry[current="yes"]/version Ugh... is it that simple? I am actually annoyed if it is that simple. If all the 3 examples above were equal to <current>yes</current> then I would get a list containing 6.3.1,6.3.1-c383,6.3.0 as a return.
@Moridn: Better update the question (but *** *** *** *** without *** *** *** *** "Edit:", "Update", or similar; the question should be as if it was written right now). Stack Overflow is not a forum.
(Regarding the missing OP icon: See Author widgets are not shown for answers anymore. It is likely to be resolved within 24 hours.)
1

Q: "I need to take the existing output of my API call ...

Since there is only limited description, no Minimal, Reproducible Example, no debugging details, it is assumed that the API call was made with Ansible too and the XML output provided is already available within a variable from Return Values of an other module, here in the example called XML.

Q: "... find all instances of "current" versions ..."

Then, a minimal playbook

- hosts: localhost
  become: false
  gather_facts: false

  vars:

    # Mimic REST API call on Control Node
    XML: "{{ lookup('file', 'input.xml') }}"

    # Convert given XML string to native Python dictionary
    YML: "{{ XML | ansible.utils.from_xml }}"

  tasks:

    - debug:
        msg: "{{ YML.response.result['sw-updates'] }}"

    - name: ID all instances where the string <current>yes</current> occurs
      debug:
        msg: "{{ YML.response.result['sw-updates'].versions.entry | selectattr('current', 'contains', 'yes') }}"

will result into an output of

TASK [debug] ****************************************************************
ok: [localhost] =>
  msg:
    '@last-updated-at': 2025/10/15 00:00:00
    msg: null
    versions:
      entry:
      - current: 'yes'
        sha256: efg456
        version: 1.2.3
      - current: 'yes'
        sha256: hij789
        version: 1.2.3-c123
      - current: 'no'
        sha256: abc123
        version: 1.1.0

TASK [ID all instances where the string <current>yes</current> occurs] ******
ok: [localhost] =>
  msg:
  - current: 'yes'
    sha256: efg456
    version: 1.2.3
  - current: 'yes'
    sha256: hij789
    version: 1.2.3-c123

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.