I am fairly new to Ansible and am trying to create a playbook that will look at my Docker Swarm machines, check what NFS shares are already mounted, mount specified NFS shares from a list if they are not already there and unmount any NFS shares that should not be on that type of machine.
Currently when I run this with --check
I get an error, that if I am reading correctly, is saying that the JSON query of the ansible_facts
does not exist. I am sure I am doing something wrong but not sure what. I have confirmed that there is at least one NFS mount in the ansible_facts
dictionary that has "fstype"="nfs4"
.
The actual error is below
fatal: [DockerSwarmManager01]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ ansible_facts | community.general.json_query(query) | list }}): ''NoneType'' object is not iterable. ''NoneType'' object is not iterable'
Playbook code below
---
- name: mount NFS shares to docker swarm members
hosts: "docker_swarm"
become: yes
vars:
nfsmounts:
- { path: "/srv/docker/paperless-consume", src: "192.168.100.5:/mnt/scale01-corvette/paperless", where: "worker" }
- { path: "/srv/docker/syncthing", src: "192.168.100.5:/mnt/scale01-corvette/docker/syncthing", where: "worker" }
- { path: "/srv/docker/paperless", src: "192.168.100.5:/mnt/scale01-corvette/docker/paperless", where: "worker" }
- { path: "/srv/docker/cloudflared", src: "192.168.100.5:/mnt/scale01-corvette/docker/cloudflared", where: "worker" }
- { path: "/srv/docker/portainer", src: "192.168.100.5:/mnt/scale01-corvette/docker/portainer", where: "all" }
- { path: "/srv/docker/gitlab", src: "192.168.100.5:/mnt/scale01-corvette/docker/gitlab", where: "worker" }
- { path: "/srv/docker/traefik", src: "192.168.100.5:/mnt/scale01-corvette/docker/traefik", where: "manager" }
- { path: "/srv/docker/flame", src: "192.168.100.5:/mnt/scale01-corvette/docker/flame", where: "worker" }
tasks:
- name: gather mounted nfs shares as ansible_fact
ansible.builtin.set_fact:
nfs_mounts_list: "{{ ansible_facts | json_query(query) | list }}"
vars:
query: "ansible_facts.ansible_mounts[?fstype=='nfs4'].mount"
- name: mount the nfsshare in client side docker worker
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: mounted
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(level=1) }}"
when: (item.path not in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_workers']) and (( {{ item.where }} == "worker" or ( {{ item.where }} == "all" ))
- name: ensure unwanted nfsshares are not present in client side docker worker
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: absent
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(level=1) }}"
when: (item.path in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_workers']) and (( {{ item.where }} != "worker" and ( {{ item.where }} != "all" ))
- name: mount the nfsshare in client side docker manager
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: mounted
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(level=1) }}"
when: (item.path not in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_managers']) and (( {{ item.where }} == "manager" or ( {{ item.where }} == "all" ))
- name: ensure unwanted nfsshares are not present in client side docker manager
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: absent
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(level=1) }}"
when: (item.path in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_managers']) and (( {{ item.where }} != "manager" and ( {{ item.where }} != "all" ))
Update I have changed the relevant task to be
- name: gather mounted nfs shares from ansible_facts
ansible.builtin.set_fact:
nfs_mounts_list: "{{ ansible_facts | community.general.json_query(query) | list }}"
vars:
query: "ansible_mounts[?fstype==`nfs4`].mount"
and still get the same output.
Taking a sample of the ansible_facts
as seen below
{
"ansible_facts":
{
"ansible_mounts":
[
{
"mount": "/srv/docker/paperless-consume",
"device": "192.168.100.5:/mnt/scale01-corvette/paperless",
"fstype": "nfs4",
"options": "rw,relatime,vers=4.2,rsize=8192,wsize=8192,namlen=255,hard,proto=tcp,timeo=14,retrans=2,sec=sys,clientaddr=192.168.100.26,local_lock=none,addr=192.168.100.5",
"size_total": 3800493850624,
"size_available": 3800493588480,
"block_size": 8192,
"block_total": 463927472,
"block_available": 463927440,
"block_used": 32,
"inode_total": 7422839117,
"inode_available": 7422839109,
"inode_used": 8,
"uuid": "N/A"
},
{
"mount": "/srv/docker/portainer",
"device": "192.168.100.5:/mnt/scale01-corvette/docker/portainer",
"fstype": "nfs",
"options": "rw,relatime,vers=3,rsize=8192,wsize=8192,namlen=255,hard,proto=tcp,timeo=14,retrans=2,sec=sys,mountaddr=192.168.100.5,mountvers=3,mountport=47071,mountproto=tcp,local_lock=none,addr=192.168.100.5",
"size_total": 3800494243840,
"size_available": 3800493588480,
"block_size": 8192,
"block_total": 463927520,
"block_available": 463927440,
"block_used": 80,
"inode_total": 7422839236,
"inode_available": 7422839109,
"inode_used": 127,
"uuid": "N/A"
}
]
}
}
Full section error message
TASK [gather mounted nfs shares from ansible_facts] **********************************************************************************************************************************************
task path: /home/travis/playbooks/one_time/mount_nfs_share.yml:22
fatal: [DockerSwarmManager01]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ ansible_facts | community.general.json_query(query) | list }}): ''NoneType'' object is not iterable. ''NoneType'' object is not iterable'
fatal: [DockerSwarmManager02]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ ansible_facts | community.general.json_query(query) | list }}): ''NoneType'' object is not iterable. ''NoneType'' object is not iterable'
fatal: [DockerSwarmManager03]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ ansible_facts | community.general.json_query(query) | list }}): ''NoneType'' object is not iterable. ''NoneType'' object is not iterable'
fatal: [DockerSwarmWorker01]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ ansible_facts | community.general.json_query(query) | list }}): ''NoneType'' object is not iterable. ''NoneType'' object is not iterable'
fatal: [DockerSwarmWorker02]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ ansible_facts | community.general.json_query(query) | list }}): ''NoneType'' object is not iterable. ''NoneType'' object is not iterable'
fatal: [DockerSwarmWorker03]: FAILED! =>
msg: 'Unexpected templating type error occurred on ({{ ansible_facts | community.general.json_query(query) | list }}): ''NoneType'' object is not iterable. ''NoneType'' object is not iterable'
I got it working with the following code
---
- name: mount nfs shares to docker swarm members
hosts: "docker_swarm"
become: yes
vars:
nfsmounts:
- { path: "/srv/docker/paperless-consume", src: "192.168.100.5:/mnt/scale01-corvette/paperless", where: "worker" }
- { path: "/srv/docker/syncthing", src: "192.168.100.5:/mnt/scale01-corvette/docker/syncthing", where: "worker" }
- { path: "/srv/docker/paperless", src: "192.168.100.5:/mnt/scale01-corvette/docker/paperless", where: "worker" }
- { path: "/srv/docker/cloudflared", src: "192.168.100.5:/mnt/scale01-corvette/docker/cloudflared", where: "worker" }
- { path: "/srv/docker/portainer", src: "192.168.100.5:/mnt/scale01-corvette/docker/portainer", where: "all" }
- { path: "/srv/docker/gitlab", src: "192.168.100.5:/mnt/scale01-corvette/docker/gitlab", where: "worker" }
- { path: "/srv/docker/traefik", src: "192.168.100.5:/mnt/scale01-corvette/docker/traefik", where: "manager" }
- { path: "/srv/docker/flame", src: "192.168.100.5:/mnt/scale01-corvette/docker/flame", where: "worker" }
tasks:
- name: gather mounted nfs shares from ansible_facts
ansible.builtin.set_fact:
nfs_mounts_list: "{{ ansible_facts | to_json | from_json | community.general.json_query(query) | list }}"
vars:
query: mounts[?contains(fstype, `nfs`)].mount
- name: mount the nfsshare in client side docker worker
vars:
where_to_mount: "{{item.where}}"
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: mounted
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(1) }}"
when: (item.path not in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_worker']) and (( item.where == "worker") or ( item.where == "all" ))
- name: ensure unwanted nfsshares are not present in client side docker worker
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: absent
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(1) }}"
when: (item.path in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_worker']) and (( item.where != "worker") and ( item.where != "all" ))
- name: mount the nfsshare in client side docker manager
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: mounted
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(1) }}"
when: (item.path not in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_manager']) and (( item.where == "manager") or ( item.where == "all" ))
- name: ensure unwanted nfsshares are not present in client side docker manager
ansible.posix.mount:
fstype: nfs
opts: rw,rsize=8192,wsize=8192,timeo=14,proto=tcp
state: absent
src: "{{ item.src }}"
path: "{{ item.path }}"
loop: "{{ nfsmounts | flatten(1) }}"
when: (item.path in nfs_mounts_list) and (inventory_hostname in groups['docker_swarm_manager']) and (( item.where != "manager") and ( item.where != "all" ))
where I've mainly changed the JSON query from ansible_facts.ansible_mounts
- name: gather mounted nfs shares as ansible_fact
ansible.builtin.set_fact:
nfs_mounts_list: "{{ ansible_facts | json_query(query) | list }}"
vars:
query: "ansible_facts.ansible_mounts[?fstype=='nfs4'].mount"
to mounts
- name: gather mounted nfs shares from ansible_facts
ansible.builtin.set_fact:
nfs_mounts_list: "{{ ansible_facts | to_json | from_json | community.general.json_query(query) | list }}"
vars:
query: mounts[?contains(fstype, `nfs`)].mount
As you have already mentioned within your comments
I got it figured out. It seems that the Ansible facts JSON output shows the
ansible_mounts
section name but it can not be referenced with that rather you have to leave theansible_
off and only use mounts.
you have to use either ansible_facts.mounts
or ansible_mounts
.
Very detailed background information can be found within a Q&A about Why should I remove the ansible_
prefix when referring to an Ansible fact?.