Converted "with_items" play to new-style loop, now it is failing

Hi all,

I had a play in one of my roles that used to look like this:

`

  • name: Ensure PRTG monitoring scripts are installed
    copy:
    src: “{{ item }}”
    dest: /var/prtg/scriptsxml/{{ item }}
    owner: root
    group: root
    mode: 0744
    with_items:
  • get_gpu_watts.py
  • get_gpu_watts_wrapper.sh
    tags: prtgmon
    `

Since I’ve moved up to Ansible 2.7, and was getting the “with_items” deprecation warning, I re-wrote the play to be in this form:

`

  • name: Ensure PRTG monitoring scripts are installed
    copy:
    src: “{{ scripts }}”
    dest: /var/prtg/scriptsxml/{{ scripts }}
    owner: root
    group: root
    mode: 0744
    vars:
    scripts:
  • get_gpu_watts.py
  • get_gpu_watts_wrapper.sh
    tags: prtgmon

`

But now, when I run my role, this play errors out, with the traceback:

`
TASK [gpu-computing-stack : Ensure PRTG monitoring scripts are installed] **********************************************
task path: /home/its/wdennis/workstation-gpu/roles/gpu-computing-stack/tasks/main.yml:316
The full traceback is:
Traceback (most recent call last):
File “/usr/lib/python2.7/dist-packages/ansible/executor/task_executor.py”, line 140, in run
res = self._execute()
File “/usr/lib/python2.7/dist-packages/ansible/executor/task_executor.py”, line 612, in _execute
result = self._handler.run(task_vars=variables)
File “/usr/lib/python2.7/dist-packages/ansible/plugins/action/copy.py”, line 454, in run
trailing_slash = source.endswith(os.path.sep)
AttributeError: ‘list’ object has no attribute ‘endswith’

fatal: [skyserver15k]: FAILED! => {
“msg”: “Unexpected failure during module execution.”,
“stdout”: “”
}
`

Can anyone tell me what the problem is with my play? (AttributeError: ‘list’ object has no attribute ‘endswith’ doesn’t mean much to me…)

I don’t know what the deprecation warning was that you were experiencing, but I doubt it was for that task. It was likely for a package manager task, and not for the copy module.

There should be no deprecation for the task you provide in this email.

Ah, I see you are correct - I guess I was assuming that all “with_items” loops had to be re-written… I was getting “DEPRECIATION WARNING” outputs for all the “with_items” lists I was using with the ‘apt’ module. So, “with_items” is not deprecated across the board? Why was it deprecated for the package manager modules?

with_items is not deprecated for package manager modules either. What is deprecated is “squash actions”.

More info can be found at https://docs.ansible.com/ansible/latest/porting_guides/porting_guide_2.7.html#using-a-loop-on-a-package-module-via-squash-actions

Before, when using with_items on a package manager task, ansible would effectively remove the loop, and squash the items to call the module only 1 time, and not actually loop. That specific squashing functionality will be removed in a future version as indicated by the warning and in the docs link I provide.

I think it is because in your re-written version, there is no loop construct. Thus the variable “scripts” is being used in full, wherever you reference it. The problem is that it is a list, not a string. The copy module wants a string as the source, and expects to be able to check whether it has a trailing slash, but the check function (endwith) is an attribute of strings, not lists, hence the error you are seeing.

Whenever you see “X has no Y attribute” or similar, it means you have got X or Y wrong - or both. Or that you have misunderstood what X is. In this particular case, the error message is telling you that “scripts” is not what you think it is. You know it is “scripts” because that is the only list in your play.

If you want to avoid "with_items’, you will need to use some other loop construct, or unwind your loop (have two plays, one for each script).

Regards, K.

Thank you for clearing this up for me! Never knew about “squash actions” before…