Passing more than one var between tasks - how is it done?

Hello. This is a continuation of the post “Passing a var between tasks”. Thanks all who chimed in on that one, your help is immensely appreciated! There is no need to read that previous post, as the question is stated clearly enough herein.
I have a playbook that does the following:

Go to ServiceNow ticketing system, get a Change Request meeting specific parameters, pass its SYS_ID to the next task which will download all the attachments in it. Each such attachment bears a unique SYS_ID, just like the master CR which has its own SYS_ID as well.

I managed to write it (barely!) in such a way that it only gets the first attachment to the Change Request and ignores the remaining ones. That means I will have to limit the users to upload multiple scripts to a request, which is unreasonable.

sys_id: "{{ dcr_new_cr_request_found_out.records[0].sys_id }}"

However, a Change Request may and will have multiple attachments.

Therefore, I need to re-write the playbook below in such a way that downloads all attachments, however many there may be.

The playbook and output below are downloading only one attachment.

Change Request “sys_id”: “fc2b752983bab210f28198c6feaad3a5”
attachments:
“sys_id”: “fc2b752983bab210f28198c6feaad3a5”
“sys_id”: “742b752983bab210f28198c6feaad3a7”
“sys_id”: “f82b752983bab210f28198c6feaad3a8”

---
    - name: Oracle database Data Change Request Process ID 2872.56
#      hosts: dbservers
      hosts: localhost
      gather_facts: true
      vars_files:
        - vars/main.yml

      tasks:

        - name: 0. Prepare. Display Ansible date_time fact and register | itsm_dcr
          delegate_to: localhost
          run_once: true
          set_fact: 
            currenttime: "{{ ansible_date_time.iso8601 }}"
          tags: linux

        - name: 1. Retrieve new DCR change requests
          servicenow.itsm.change_request_info:
             instance:
               host: "{{ sn_instance}}"
               username: "{{ sn_username }}"
               password:  "{{ sn_password }}"
             query:
              - state: = new
              - short_description: LIKE DCR
          register: dcr_new_cr_request_found_out
          delegate_to: localhost

        - name: 1.1 Debug the ServiceNow Change Request details to get the attachment SYS_ID | itsm_dcr
          debug: var=dcr_new_cr_request_found_out  

        - name: Cache the CR SYS_ID {{ ansible_date_time.iso8601 }} | itsm_dcr
          ansible.builtin.set_fact:
            sys_id: "{{ dcr_new_cr_request_found_out.records[0].sys_id }}"    

        - name: 2. Download the Change Request attachment with its hardcoded SYS_ID from Step 1 | itsm_dcr
          servicenow.itsm.attachment: 
            instance:
              host: "{{ sn_instance}}"
              username: "{{ sn_username }}"
              password:  "{{ sn_password }}"
            dest: /tmp/DCR_{{ currenttime }}_00000001.sql
            sys_id: "{{ dcr_new_cr_request_found_out.records[0].attachments[0].sys_id }}"            
#            sys_id: 003a3ef24ff1120031577d2ca310c74b
          register: dcr_new_cr_attachment_out  

        - name: 2.1 Debug the hardcoded-SYS-ID attachment download details | itsm_dcr
          debug: var=dcr_new_cr_attachment_out   

and the output (note there are four *.sql attachments in that CR):

[ansible_admin@ctrl ansible]$ ansible-playbook ./playbooks/dcr_03.yml

PLAY [Oracle database Data Change Request Process ID 2872.56] *************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************************
ok: [localhost]
[WARNING]: Using run_once with the free strategy is not currently supported. This task will still be executed for every host in the inventory list.

TASK [0. Prepare. Display Ansible date_time fact and register | itsm_dcr] *************************************************************************************************************
ok: [localhost]

TASK [1. Retrieve new DCR change requests] ********************************************************************************************************************************************
[WARNING]: Encountered unknown value  while mapping field risk.
[WARNING]: Encountered unknown value Software while mapping field category.
ok: [localhost]

TASK [1.1 Debug the ServiceNow Change Request details to get the attachment SYS_ID | itsm_dcr] ****************************************************************************************
ok: [localhost] => {
    "dcr_new_cr_request_found_out": {
        "changed": false,
        "failed": false,
        "records": [
            {
                "active": "true",
                "activity_due": "",
                "additional_assignee_list": "",
                "approval": "approved",
                "approval_history": "",
                "approval_set": "2026-01-27 19:29:50",
                "assigned_to": "3c589a008334f210f28198c6feaad375",
                "assignment_group": "db53580b0a0a0a6501aa37c294a2ba6b",
                "attachments": [
                    {
                        "average_image_color": "",
                        "chunk_size_bytes": "700000",
                        "compressed": "true",
                        "content_type": "text/x-sql",
                        "download_link": "https://dev276659.service-now.com/api/now/attachment/fc2b752983bab210f28198c6feaad3a5/file",
                        "file_name": "DCR_002.sql",
                        "hash": "495a9dfd6868afb81786f3edb5183ebbde68fe136395373d7bacabb1fa36c24a",
                        "image_height": "",
                        "image_width": "",
                        "size_bytes": "76",
                        "size_compressed": "92",
                        "state": "available",
                        "sys_created_by": "admin",
                        "sys_created_on": "2026-02-01 10:42:41",
                        "sys_id": "fc2b752983bab210f28198c6feaad3a5",
                        "sys_mod_count": "1",
                        "sys_tags": "",
                        "sys_updated_by": "system",
                        "sys_updated_on": "2026-02-01 10:42:41",
                        "table_name": "change_request",
                        "table_sys_id": "34a34e0883f6f210f28198c6feaad380"
                    },
                    {
                        "average_image_color": "",
                        "chunk_size_bytes": "700000",
                        "compressed": "true",
                        "content_type": "text/x-sql",
                        "download_link": "https://dev276659.service-now.com/api/now/attachment/742b752983bab210f28198c6feaad3a7/file",
                        "file_name": "DCR_003.sql",
                        "hash": "468948ef7571706b68865cb9617fa979decc5664d30353742f03c024c0e6f3c5",
                        "image_height": "",
                        "image_width": "",
                        "size_bytes": "148",
                        "size_compressed": "141",
                        "state": "available",
                        "sys_created_by": "admin",
                        "sys_created_on": "2026-02-01 10:42:41",
                        "sys_id": "742b752983bab210f28198c6feaad3a7",
                        "sys_mod_count": "1",
                        "sys_tags": "",
                        "sys_updated_by": "system",
                        "sys_updated_on": "2026-02-01 10:42:41",
                        "table_name": "change_request",
                        "table_sys_id": "34a34e0883f6f210f28198c6feaad380"
                    },
                    {
                        "average_image_color": "",
                        "chunk_size_bytes": "700000",
                        "compressed": "true",
                        "content_type": "text/x-sql",
                        "download_link": "https://dev276659.service-now.com/api/now/attachment/f82b752983bab210f28198c6feaad3a8/file",
                        "file_name": "DCR_004_controlled_failure.sql",
                        "hash": "5d48a20d5bd0003a1d3bad56aa43127b33b4274f55978e6404aeb1b49d602aa1",
                        "image_height": "",
                        "image_width": "",
                        "size_bytes": "264",
                        "size_compressed": "198",
                        "state": "available",
                        "sys_created_by": "admin",
                        "sys_created_on": "2026-02-01 10:42:41",
                        "sys_id": "f82b752983bab210f28198c6feaad3a8",
                        "sys_mod_count": "1",
                        "sys_tags": "",
                        "sys_updated_by": "system",
                        "sys_updated_on": "2026-02-01 10:42:41",
                        "table_name": "change_request",
                        "table_sys_id": "34a34e0883f6f210f28198c6feaad380"
                    }
                ],
                "backout_plan": "",
                "business_duration": "",
                "business_service": "281a4d5fc0a8000b00e4ba489a83eedc",
                "cab_date_time": "",
                "cab_delegate": "",
                "cab_recommendation": "",
                "cab_required": "false",
                "calendar_duration": "",
                "category": "Software",
                "change_plan": "",
                "chg_model": "007c4001c343101035ae3f52c1d3aeb2",
                "close_code": "",
                "close_notes": "",
                "closed_at": "",
                "closed_by": "",
                "cmdb_ci": "0c43d5e2c61122750182c132a8b9e2d9",
                "comments": "",
                "comments_and_work_notes": "",
                "company": "",
                "conflict_last_run": "",
                "conflict_status": "Not Run",
                "contact_type": "",
                "contract": "",
                "copied_from": "",
                "correlation_display": "",
                "correlation_id": "",
                "delivery_plan": "",
                "delivery_task": "",
                "description": "--- Managed by r-able.com hyperautomation (TurboCharged, V2.2.2). Do not change manually. Do not deviate. ---\r\n--- This Change Request adds a new deployment to an already installed GoldenGate hub binaries ---\r\n--- Enter the required parameters on the right side of the \":\" below ---\r\nRun dcr\r\n",
                "due_date": "",
                "end_date": "",
                "escalation": "0",
                "expected_start": "",
                "follow_up": "",
                "group_list": "",
                "impact": "low",
                "implementation_plan": "",
                "justification": "",
                "knowledge": "false",
                "location": "",
                "made_sla": "true",
                "number": "CHG0030971",
                "on_hold": false,
                "on_hold_reason": "",
                "on_hold_task": "",
                "opened_at": "2026-01-27 19:28:56",
                "opened_by": "6816f79cc0a8016401c5a33be04be441",
                "order": "",
                "outside_maintenance_schedule": "false",
                "parent": "",
                "phase": "requested",
                "phase_state": "open",
                "priority": "low",
                "production_system": "false",
                "reason": "",
                "reassignment_count": "0",
                "requested_by": "6816f79cc0a8016401c5a33be04be441",
                "requested_by_date": "",
                "review_comments": "",
                "review_date": "",
                "review_status": "",
                "risk": "",
                "risk_impact_analysis": "",
                "route_reason": "",
                "scope": "3",
                "service_offering": "04b89573835e7210f28198c6feaad3f0",
                "short_description": "DCR",
                "sla_due": "",
                "start_date": "",
                "state": "new",
                "std_change_producer_version": "",
                "sys_class_name": "change_request",
                "sys_created_by": "admin",
                "sys_created_on": "2026-01-27 19:29:50",
                "sys_domain": "global",
                "sys_domain_path": "/",
                "sys_id": "34a34e0883f6f210f28198c6feaad380",
                "sys_mod_count": "9",
                "sys_tags": "",
                "sys_updated_by": "admin",
                "sys_updated_on": "2026-02-01 10:49:31",
                "task_effective_number": "CHG0030971",
                "test_plan": "",
                "time_worked": "",
                "type": "normal",
                "unauthorized": "false",
                "universal_request": "",
                "upon_approval": "proceed",
                "upon_reject": "cancel",
                "urgency": "low",
                "user_input": "",
                "watch_list": "",
                "work_end": "",
                "work_notes": "",
                "work_notes_list": "",
                "work_start": ""
            }
        ],
        "warnings": [
            "Encountered unknown value  while mapping field risk.",
            "Encountered unknown value Software while mapping field category."
        ]
    }
}

TASK [Cache the CR SYS_ID 2026-02-01T12:24:11Z | itsm_dcr] ****************************************************************************************************************************
ok: [localhost]

TASK [2. Download the Change Request attachment with its hardcoded SYS_ID from Step 1 | itsm_dcr] *************************************************************************************
changed: [localhost]

TASK [2.1 Debug the hardcoded-SYS-ID attachment download details | itsm_dcr] **********************************************************************************************************
ok: [localhost] => {
    "dcr_new_cr_attachment_out": {
        "changed": true,
        "failed": false,
        "record": {
            "elapsed": 0.41,
            "msg": "OK",
            "size": 76,
            "status_code": 200
        }
    }
}

PLAY RECAP ****************************************************************************************************************************************************************************
localhost                  : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[ansible_admin@ctrl ansible]$ 

Please help me tackle this monster.
Nestor Kandinsky-Clerambeau.

1 Like

I’d approach this as follows, of course there are lots of other ways to do this and others will probably suggest better ideas!

  1. Save the output to a file, eg dcr_new_cr_request_found_out.json:
{
  dcr_new_cr_request_found_out: {
    changed: false,
    failed: false,
    records: [
      {
        active: true,
        activity_due: "",
        additional_assignee_list: "",
        approval: approved,
        approval_history: "",
        approval_set: 2026-01-27 19:29:50,
        assigned_to: 3c589a008334f210f28198c6feaad375,
        assignment_group: db53580b0a0a0a6501aa37c294a2ba6b,
        attachments: [
          {
            average_image_color: "",
            chunk_size_bytes: 700000,
            compressed: true,
            content_type: text/x-sql,
            download_link: https://dev276659.service-now.com/api/now/attachment/fc2b752983bab210f28198c6feaad3a5/file,
            file_name: DCR_002.sql,
            hash: 495a9dfd6868afb81786f3edb5183ebbde68fe136395373d7bacabb1fa36c24a,
            image_height: "",
            image_width: "",
            size_bytes: 76,
            size_compressed: 92,
            state: available,
            sys_created_by: admin,
            sys_created_on: 2026-02-01 10:42:41,
            sys_id: fc2b752983bab210f28198c6feaad3a5,
            sys_mod_count: 1,
            sys_tags: "",
            sys_updated_by: system,
            sys_updated_on: 2026-02-01 10:42:41,
            table_name: change_request,
            table_sys_id: 34a34e0883f6f210f28198c6feaad380
          },
          {
            average_image_color: "",
            chunk_size_bytes: 700000,
            compressed: true,
            content_type: text/x-sql,
            download_link: https://dev276659.service-now.com/api/now/attachment/742b752983bab210f28198c6feaad3a7/file,
            file_name: DCR_003.sql,
            hash: 468948ef7571706b68865cb9617fa979decc5664d30353742f03c024c0e6f3c5,
            image_height: "",
            image_width: "",
            size_bytes: 148,
            size_compressed: 141,
            state: available,
            sys_created_by: admin,
            sys_created_on: 2026-02-01 10:42:41,
            sys_id: 742b752983bab210f28198c6feaad3a7,
            sys_mod_count: 1,
            sys_tags: "",
            sys_updated_by: system,
            sys_updated_on: 2026-02-01 10:42:41,
            table_name: change_request,
            table_sys_id: 34a34e0883f6f210f28198c6feaad380
          },
          {
            average_image_color: "",
            chunk_size_bytes: 700000,
            compressed: true,
            content_type: text/x-sql,
            download_link: https://dev276659.service-now.com/api/now/attachment/f82b752983bab210f28198c6feaad3a8/file,
            file_name: DCR_004_controlled_failure.sql,
            hash: 5d48a20d5bd0003a1d3bad56aa43127b33b4274f55978e6404aeb1b49d602aa1,
            image_height: "",
            image_width: "",
            size_bytes: 264,
            size_compressed: 198,
            state: available,
            sys_created_by: admin,
            sys_created_on: 2026-02-01 10:42:41,
            sys_id: f82b752983bab210f28198c6feaad3a8,
            sys_mod_count: 1,
            sys_tags: "",
            sys_updated_by: system,
            sys_updated_on: 2026-02-01 10:42:41,
            table_name: change_request,
            table_sys_id: 34a34e0883f6f210f28198c6feaad380
          }
        ],
        backout_plan: "",
        business_duration: "",
        business_service: 281a4d5fc0a8000b00e4ba489a83eedc,
        cab_date_time: "",
        cab_delegate: "",
        cab_recommendation: "",
        cab_required: false,
        calendar_duration: "",
        category: Software,
        change_plan: "",
        chg_model: 007c4001c343101035ae3f52c1d3aeb2,
        close_code: "",
        close_notes: "",
        closed_at: "",
        closed_by: "",
        cmdb_ci: 0c43d5e2c61122750182c132a8b9e2d9,
        comments: "",
        comments_and_work_notes: "",
        company: "",
        conflict_last_run: "",
        conflict_status: Not Run,
        contact_type: "",
        contract: "",
        copied_from: "",
        correlation_display: "",
        correlation_id: "",
        delivery_plan: "",
        delivery_task: "",
        description: --- Managed by r-able.com hyperautomation (TurboCharged, V2.2.2). Do not change manually. Do not deviate. ---\r\n--- This Change Request adds a new deployment to an already installed GoldenGate hub binaries ---\r
\n--- Enter the required parameters on the right side of the \":\" below ---\r\nRun dcr\r\n,
        due_date: "",
        end_date: "",
        escalation: 0,
        expected_start: "",
        follow_up: "",
        group_list: "",
        impact: low,
        implementation_plan: "",
        justification: "",
        knowledge: false,
        location: "",
        made_sla: true,
        number: CHG0030971,
        on_hold: false,
        on_hold_reason: "",
        on_hold_task: "",
        opened_at: 2026-01-27 19:28:56,
        opened_by: 6816f79cc0a8016401c5a33be04be441,
        order: "",
        outside_maintenance_schedule: false,
        parent: "",
        phase: requested,
        phase_state: open,
        priority: low,
        production_system: false,
        reason: "",
        reassignment_count: 0,
        requested_by: 6816f79cc0a8016401c5a33be04be441,
        requested_by_date: "",
        review_comments: "",
        review_date: "",
        review_status: "",
        risk: "",
        risk_impact_analysis: "",
        route_reason: "",
        scope: 3,
        service_offering: 04b89573835e7210f28198c6feaad3f0,
        short_description: DCR,
        sla_due: "",
        start_date: "",
        state: new,
        std_change_producer_version: "",
        sys_class_name: change_request,
        sys_created_by: admin,
        sys_created_on: 2026-01-27 19:29:50,
        sys_domain: global,
        sys_domain_path: /,
        sys_id: 34a34e0883f6f210f28198c6feaad380,
        sys_mod_count: 9,
        sys_tags: "",
        sys_updated_by: admin,
        sys_updated_on: 2026-02-01 10:49:31,
        task_effective_number: CHG0030971,
        test_plan: "",
        time_worked: "",
        type: normal,
        unauthorized: false,
        universal_request: "",
        upon_approval: proceed,
        upon_reject: cancel,
        urgency: low,
        user_input: "",
        watch_list: "",
        work_end: "",
        work_notes: "",
        work_notes_list: "",
        work_start: ""
      }
    ],
    warnings: [
      Encountered unknown value  while mapping field risk.,
      Encountered unknown value Software while mapping field category.
    ]
  }
}
  1. Open the file using jpterm and work out the JMESPath query needed to get the attachment paths:
  2. Use the json_query module to get the paths:
- name: Set a fact for the attachment download paths
  ansible.builtin.set_fact:
    attachment_urls: "{{ dcr_new_cr_request_found_out | community.general.json_query('records[0].attachments[].download_link') }}"
  1. Use get_url to download the files in a loop and using the string before /filein the URL for the file name:
- name: Download attachments
  ansible.builtin.get_url:
    url: "{{ attachment_url }}"
    dest: "/tmp/{{ attachment_url | ansible.builtin.regex_search('[a-z0-9]{32}[\/]file$') }}"
  loop: "{{ attachment_urls }}"
  loop_control:
    loop_var: attachment_url
1 Like

As was said before, .records is a list, each item of which contains .attachments which is also a list, so to handle it correctly you’ll need to iterate over each record × attachment combination.

A typical way to handle nested loops is to use an included tasks file. The first task below just dumps out CR sys_ids paired with their attachments’ sys_ids. The second task iterates over each of the CRs.

    - name: Dump CRs and Attachments
      ansible.builtin.debug:
        msg: "{{ dcr_new_cr_request_found_out.records
                 | json_query('[].{cr_sysid: sys_id,
                                   cr_attachments: attachments[].sys_id
                                  }'
                             ) }}"
    - name: Handle each CR
      ansible.builtin.include_tasks:
        file: clerambeau370_01_cr.yml
      loop: "{{ dcr_new_cr_request_found_out.records }}"
      loop_control:
        loop_var: cr

The included task sees each CR in the variable cr, and the debug task there loops over that cr’s attachments. Behold:

---
# clerambeau370_01_cr.yml
- name: Handle CR attachments
  ansible.builtin.debug:
    msg: "handling CR {{ cr.sys_id }}, Attachment {{ attachment.sys_id }}."
  loop: "{{ cr.attachments }}"
  loop_control:
    loop_var: attachment

The output contains

msg: handling CR 34a34e0883f6f210f28198c6feaad380, Attachment fc2b752983bab210f28198c6feaad3a5.
msg: handling CR 34a34e0883f6f210f28198c6feaad380, Attachment 742b752983bab210f28198c6feaad3a7.
msg: handling CR 34a34e0883f6f210f28198c6feaad380, Attachment f82b752983bab210f28198c6feaad3a8.

If your initial results contained more than one CR, this would still work.

1 Like

You can do it without involving additional tasks files with the ansible.builtin.subelements filter.

- name: Using ansible.builtin.subelements
  ansible.builtin.debug:
    msg: "CR: {{ item[0].sys_id }}, Attachment: {{ item[1].sys_id }}"
  loop: "{{ dcr_new_cr_request_found_out.records
            | ansible.builtin.subelements('attachments', skip_missing=True) }}"

which produces

msg: 'CR: 34a34e0883f6f210f28198c6feaad380, Attachment: fc2b752983bab210f28198c6feaad3a5'
msg: 'CR: 34a34e0883f6f210f28198c6feaad380, Attachment: 742b752983bab210f28198c6feaad3a7'
msg: 'CR: 34a34e0883f6f210f28198c6feaad380, Attachment: f82b752983bab210f28198c6feaad3a8'

It also correctly handles the case of multiple records (i.e., multiple CR),
as well as zero or more attachments per CR.

1 Like

There’s another important point that isn’t a direct answer to your question, but rather more generally about tasks and data management.

Tasks take a lot of time compared to data manipulations. If you find yourself eking out lots of discrete datums and stashing them away with set_fact tasks, consider whether the same information can be derived from existing data at the time of use with appropriate jinja expressions.

For example, {{ dcr_new_cr_request_found_out.records | ansible.builtin.subelements('attachments', skip_missing=True) }} gives you a list of 2-item lists, the first item being a record, the second item being one of the record’s attachments. Looping over this list of pairs gives you access to all the relevant sys_ids etc without having to do a bunch of set_facts beforehand.

Take some time to browse through the list of available filters and lookups, for example:
ansible-doc -t filter --list
ansible-doc -t lookup --list
and dive deeper into any that look like they might be useful in whatever you’re working on (or recently worked on). For example:
ansible-doc -t filter ansible.builtin.subelements
If it seems like it should be useful but the examples don’t make it clear, it’s worth the time to whip up a test playbook with some toy data and play with it until it makes sense. Then when you hit a situation like the one you’re dealing with, you’ll have perhaps enough familiarity with these tools that you can handle it efficiently. That self-training time pays off later.

1 Like