In my Ansible script i would like to verify whether I have certain packages and repos available using the yum module.
Afterwards I want to filter my the results of that task to get installed packages and repos above a certain version using selectattr within a loop to manipulate my data
But when I filter my data, one query works and one doesnt. I dont see the difference.
Version: Ansible 2.9.25
Detailed Description starts here:
I get my first dict like this:
- name: 'checks A | check (available) base packages'
yum:
list: '{{ item }}'
with_items: '{{ base_packages_to_install }}'
register: yum_base_packages_result
and
- name: 'checks B | Verify mongodb repos'
block:
- name: 'repolist_checks B | check (available) mongodb repos'
yum:
list: mongodb
register: mongodb_repos_result
Afterwards I filter those lists to get what I am looking for.
This works just fine, I get my intended dataset (installed packages)
- set_fact:
yum_list_installed: []
- name: 'checks A | create list of installed packages'
set_fact:
yum_list_installed: '{{ yum_list_installed + item.results | selectattr("yumstate", "match", "installed") | list }}'
with_items: '{{ yum_base_packages_result.results }}'
However, this doesnt work:
- set_fact:
mongodb_repos_version: []
- name: 'checks B | check list for version lower/greater than ...'
set_fact:
mongo_list_version: '{{ mongodb_repos_version+ item.results | selectattr("version", "version", required_version, ">" ) | list }}'
with_items: '{{ mongodb_repos_result.results }}'
The error messsage says:
"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'results'\n\nThe error appears to be in 'path/to/task.yml': line, column, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: 'checks B | check list for version lower/greater than ...'\n ^ here\n"
When I run a type debug like this
- name: 'checks B | Output TYPE mongodb_repos_result'
debug:
msg: '{{ mongodb_repos_result| type_debug }}'
verbosity: 0
- name: 'checks B | Output TYPE mongodb_repos_result.results'
debug:
msg: '{{ mongodb_repos_result.results | type_debug }}'
verbosity: 0
My problem:
I get dict for the first, and list for the second, which is what I expected. I dont see the difference between check A and check B aside from the initial yum query, where one loops over a list and one asks for mongodb_repos. But this shouldnt make the difference since the data structure that is yielded, is the same (since i get multiple mongodb_repos)
Maybe useful to you, maybe not:
Data structure mongodb_repos_result looks like this:
"mongodb_repos_result": {
"changed": false,
"failed": false,
"results": [
{
"arch": "foo",
"envra": "foo",
"epoch": "foo",
"name": "mongodb-repo-foo",
"release": "foo",
"repo": "repo-name-1",
"version": "4.2.0",
"yumstate": "available"
},
{
"arch": "foo",
"envra": "foo",
"epoch": "foo",
"name": "mongodb-repo-foo",
"release": "foo",
"repo": "repo-name-2",
"version": "6.0.0",
"yumstate": "available"
}
]
}
And the data structure mongodb_repos_result.results looks of course like this:
"mongodb_repos_result.results": [
{
"arch": "foo",
"envra": "foo",
"epoch": "foo",
"name": "mongodb-repo-foo",
"release": "foo",
"repo": "repo-name-1",
"version": "4.2.0",
"yumstate": "available"
},
{
"arch": "foo",
"envra": "foo",
"epoch": "foo",
"name": "mongodb-repo-foo",
"release": "foo",
"repo": "repo-name-2",
"version": "6.0.0",
"yumstate": "available"
}
]
Your first task is using a loop, which means that
registerbehaves differently than it does when used in a non-looping task. Specifically, when used in a loop your registered variable will have a keyresultscontaining a list of results from each task execution. That gets you:When used in a non-looping task, the results are directly accessible in the registered variable:
One solution is to rewrite the mongodb task to use a loop:
Now both variables will have the same structure.