Summary
Note:
This issue was originally filed as ansible/ansible#84429 but was closed there due to the argument that I should create an issue in this repository.
When ansible-playbook is executed together with unbuffer (see https://linux.die.net/man/1/unbuffer ), The lock file in /tmp/ of viczem.keepass.keepass is not cleaned up after execution of ansible-playbook finishes.
My whole setup:
Ansible is used in a docker container. I use docker version 20.10.3, build 48d30b5. The Dockerfile looks like this:
FROM ubuntu:20.04
ARG MA_ANSIBLE_PASSWORD
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y expect-dev \
gcc \
git-all \
libkrb5-dev \
krb5-user \
openssh-server \
python3 \
python3-dev \
python3-pip \
unzip \
vim \
&& \
apt-get clean all && \
rm -rf /var/lib/apt/lists/*
RUN pip3 install --upgrade pip && \
pip3 install --upgrade virtualenv && \
pip3 install pywinrm[kerberos] && \
pip3 install pywinrm && \
pip3 install "pykeepass==4.0.3" && \
pip3 install ansible && \
pip3 install ansible-lint
RUN useradd -m -s /bin/bash ansible && usermod -aG sudo ansible
RUN echo "ansible:$MA_ANSIBLE_PASSWORD" | chpasswd
EXPOSE 22
COPY ./config/krb5.conf /etc/
COPY ./config/initialize.sh /root/
COPY ./galaxy /galaxy
RUN chmod +x /root/initialize.sh
CMD /root/initialize.sh && sleep infinity
The image is built on one host, then pushed into a private registry and pulled from another host and also started (and running) there. Inside the container I have a bash script doing the following:
#!/bin/bash
...
unbuffer ansible-playbook -i inventories/10_Site_Common.yml \
-i inventories/20a_Site_WRN_Test.yml \
-i inventories/20a_Site_WRN_ProdTest.yml \
-i inventories/20a_Site_WRN_ProdTest_291.yml \
-i inventories/20a_Site_WRN_ProdTest_292.yml \
-i inventories/20z_Development.yml \
--limit $LIMIT \
$PLAYBOOK \
--check -vvvvv \
| tee >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOGFILENAME)
...
When I enter the freshly started container by ssh-ing into it through the exposed ssh port (which is redirected to port 2222) and executing the above bash-script through the following command:
./deploy.sh --limit somemachine.EXAMPLE.COM --playbook playbooks/notepadplusplus.yml
... I get my expected behavior. This means that the playbook does what it is supposed to to: It fetches passwords from the keepass file (*.kdbx), gathers facts through authenticating as the correct user through credentials obtained from keepass, performs tasks successfully and exits.
BUT: Any subsequent execution of my script fails nearly instant at the beginning with the following error:
ansible-playbook [core 2.13.13]
config file = /opt/ansible/ansible.cfg
configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.8/dist-packages/ansible
ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible-playbook
python version = 3.8.10 (default, Nov 7 2024, 13:10:47) [GCC 9.4.0]
jinja version = 3.1.4
libyaml = True
Using /opt/ansible/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /opt/ansible/inventories/10_Site_Common.yml as it did not pass its verify_file() method
script declined parsing /opt/ansible/inventories/10_Site_Common.yml as it did not pass its verify_file() method
Skipping empty key (hosts) in group (somegroup_1)
Parsed /opt/ansible/inventories/10_Site_Common.yml inventory source with yaml plugin
setting up inventory plugins
host_list declined parsing /opt/ansible/inventories/20a_Site_WRN_Test.yml as it did not pass its verify_file() method
script declined parsing /opt/ansible/inventories/20a_Site_WRN_Test.yml as it did not pass its verify_file() method
Skipping empty key (hosts) in group (somegroup_2)
Parsed /opt/ansible/inventories/20a_Site_WRN_Test.yml inventory source with yaml plugin
setting up inventory plugins
host_list declined parsing /opt/ansible/inventories/20a_Site_WRN_ProdTest.yml as it did not pass its verify_file() method
script declined parsing /opt/ansible/inventories/20a_Site_WRN_ProdTest.yml as it did not pass its verify_file() method
Parsed /opt/ansible/inventories/20a_Site_WRN_ProdTest.yml inventory source with yaml plugin
setting up inventory plugins
host_list declined parsing /opt/ansible/inventories/20a_Site_WRN_ProdTest_291.yml as it did not pass its verify_file() method
script declined parsing /opt/ansible/inventories/20a_Site_WRN_ProdTest_291.yml as it did not pass its verify_file() method
Parsed /opt/ansible/inventories/20a_Site_WRN_ProdTest_291.yml inventory source with yaml plugin
setting up inventory plugins
host_list declined parsing /opt/ansible/inventories/20a_Site_WRN_ProdTest_292.yml as it did not pass its verify_file() method
script declined parsing /opt/ansible/inventories/20a_Site_WRN_ProdTest_292.yml as it did not pass its verify_file() method
Parsed /opt/ansible/inventories/20a_Site_WRN_ProdTest_292.yml inventory source with yaml plugin
setting up inventory plugins
host_list declined parsing /opt/ansible/inventories/20z_Development.yml as it did not pass its verify_file() method
script declined parsing /opt/ansible/inventories/20z_Development.yml as it did not pass its verify_file() method
Skipping empty key (hosts) in group (somegroup_3)
Parsed /opt/ansible/inventories/20z_Development.yml inventory source with yaml plugin
Loading collection chocolatey.chocolatey from /usr/local/lib/python3.8/dist-packages/ansible_collections/chocolatey/chocolatey
Loading callback plugin default of type stdout, v2.0 from /usr/local/lib/python3.8/dist-packages/ansible/plugins/callback/default.py
Loading collection ansible.posix from /usr/local/lib/python3.8/dist-packages/ansible_collections/ansible/posix
Attempting to use 'default' callback.
Skipping callback 'default', as we already have a stdout callback.
Attempting to use 'junit' callback.
Attempting to use 'minimal' callback.
Skipping callback 'minimal', as we already have a stdout callback.
Attempting to use 'oneline' callback.
Skipping callback 'oneline', as we already have a stdout callback.
Attempting to use 'tree' callback.
Attempting to use 'ansible.posix.profile_tasks' callback.
Loading callback plugin ansible.posix.profile_tasks of type aggregate, v2.0 from /usr/local/lib/python3.8/dist-packages/ansible_collections/ansible/posix/plugins/callback/profile_tasks.py
PLAYBOOK: notepadplusplus.yml ***********************************************************************************************************************************************************************************************
Positional arguments: playbooks/notepadplusplus.yml
verbosity: 5
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
check: True
inventory: ('/opt/ansible/inventories/10_Site_Common.yml', '/opt/ansible/inventories/20a_Site_WRN_Test.yml', '/opt/ansible/inventories/20a_Site_WRN_ProdTest.yml', '/opt/ansible/inventories/20a_Site_WRN_ProdTest_291.yml', '/opt/ansible/inventories/20a_Site_WRN_ProdTest_292.yml', '/opt/ansible/inventories/20z_Development.yml')
subset: somemachine.EXAMPLE.COM
forks: 5
1 plays in playbooks/notepadplusplus.yml
PLAY [Deploy Notepad++] *****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************************************
task path: /opt/ansible/playbooks/notepadplusplus.yml:3
Thursday 05 December 2024 05:53:45 +0000 (0:00:00.029) 0:00:00.029 *****
Loading collection viczem.keepass from /home/ansible/.ansible/collections/ansible_collections/viczem/keepass
KeePass: connect to '/tmp/ansible-keepass-9e61ddcf.sock'
exception during Jinja2 execution: Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/ansible/template/__init__.py", line 984, in _lookup
ran = instance.run(loop_terms, variables=self._available_variables, **kwargs)
File "/home/ansible/.ansible/collections/ansible_collections/viczem/keepass/plugins/lookup/keepass.py", line 154, in run
return self._send(socket_path, "fetch", terms)
File "/home/ansible/.ansible/collections/ansible_collections/viczem/keepass/plugins/lookup/keepass.py", line 161, in _send
sock.connect(kp_soc)
ConnectionRefusedError: [Errno 111] Connection refused
fatal: [somemachine.EXAMPLE.COM]: FAILED! => {
"msg": "An unhandled exception occurred while running the lookup plugin 'viczem.keepass.keepass'. Error was a <class 'ConnectionRefusedError'>, original message: [Errno 111] Connection refused. [Errno 111] Connection refused"
}
PLAY RECAP ******************************************************************************************************************************************************************************************************************
somemachine.EXAMPLE.COM : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Thursday 05 December 2024 05:53:46 +0000 (0:00:00.252) 0:00:00.282 *****
===============================================================================
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 0.25s
/opt/ansible/playbooks/notepadplusplus.yml:3 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The reason for the error:
An unhandled exception occurred while running the lookup plugin 'viczem.keepass.keepass'. Error was a <class 'ConnectionRefusedError'>, original message: [Errno 111] Connection refused. [Errno 111] Connection refused
could be tracked down to the use of unbuffer in my script. If I remove the "unbuffer" from the script, the playbook works correctly if called repeatedly. My investigations have shown that a lock file and the socket file of viczem.keepass.keepass are not cleaned up properly after execution of the playbook. To be precise: After ansible-playbook finishes. The following command shows what remains in the /tmp/ directory:
ansible@7c4670e0329b:/opt/ansible$ ls -la /tmp/
total 8
drwxrwxrwt 1 root root 4096 Dec 5 05:53 .
drwxr-xr-x 1 root root 4096 Dec 5 05:17 ..
srw------- 1 ansible ansible 0 Dec 5 05:25 ansible-keepass-9e61ddcf.sock
-rw------- 1 ansible ansible 0 Dec 5 05:25 ansible-keepass-9e61ddcf.sock.lock
srwxrwxr-x 1 ansible ansible 0 Dec 5 05:17 vscode-git-5449f56b2c.sock
srwxrwxr-x 1 ansible ansible 0 Dec 5 05:18 vscode-git-69fe405b86.sock
srwxrwxr-x 1 ansible ansible 0 Dec 5 05:18 vscode-ipc-7c3ccf14-f69d-45e3-84d5-7aca870cdf76.sock
srwxrwxr-x 1 ansible ansible 0 Dec 5 05:18 vscode-ipc-7c5270a5-5651-4f79-936d-ccfa3d41d6e7.sock
srwxrwxr-x 1 ansible ansible 0 Dec 5 05:17 vscode-ipc-9a116bb8-19ba-4764-a674-7670abc33495.sock
ansible@7c4670e0329b:/opt/ansible$
More explanation to the call to ansible-playbook as it is done in the script:
unbuffer ansible-playbook -i inventories/10_Site_Common.yml \
-i inventories/20a_Site_WRN_Test.yml \
-i inventories/20a_Site_WRN_ProdTest.yml \
-i inventories/20a_Site_WRN_ProdTest_291.yml \
-i inventories/20a_Site_WRN_ProdTest_292.yml \
-i inventories/20z_Development.yml \
--limit $LIMIT \
$PLAYBOOK \
--check -vvvvv \
| tee >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOGFILENAME)
- I split the inventory into multiple files for better handling of target hosts
- The variables
$LIMIT, $LOGFILENAME and $PLAYBOOK are populated with (for me) meaningful values in the script before
- We always limit execution to not by accident execute the playbook on all target hosts
- The
--check and -vvvvv are only there to provide input to this issue here and are not part of regular executions.
unbuffer, tee and sed are used for the purpose of:
- getting a log file of the
ansible-playbook execution
- retaining the console output for the user to see what happens
- retaining the colors in the console output for the user to better judge on the outcome of the execution
- having the logfile without escape characters that are responsible for coloring the UI
- The password of the keepass database file is provided through the environment variable
ANSIBLE_KEEPASS_PSW before execution of the script
If I manually rm /tmp/ansible-keepass-* after execution of the above script, the issue is gone.
Also, if I call a modified bash script with the following content, the issue does not occur:
ansible-playbook -i inventories/10_Site_Common.yml \
-i inventories/20a_Site_WRN_Test.yml \
-i inventories/20a_Site_WRN_ProdTest.yml \
-i inventories/20a_Site_WRN_ProdTest_291.yml \
-i inventories/20a_Site_WRN_ProdTest_292.yml \
-i inventories/20z_Development.yml \
--limit $LIMIT \
$PLAYBOOK \
--check -vvvvv \
| tee >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOGFILENAME)
I suspect the handling of the lock file (creation and cleanup) to have problems with unbuffer.
For the time being I will just cleanup after ansible-playbook has run by removing the lock file and socket file manually, but maybe there is a way to fix it directly in ansible or the plugin?
Issue Type
Bug Report
Component Name
viczem.keepass.keepass
Ansible Version
$ ansible --version
ansible [core 2.13.13]
config file = /opt/ansible/ansible.cfg
configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.8/dist-packages/ansible
ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.8.10 (default, Nov 7 2024, 13:10:47) [GCC 9.4.0]
jinja version = 3.1.4
libyaml = True
Configuration
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
CALLBACKS_ENABLED(/opt/ansible/ansible.cfg) = ['ansible.posix.profile_tasks']
OS / Environment
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
Steps to Reproduce
playbooks/notepadplusplus.yml
---
- name: Deploy Notepad++
hosts:
- npp
roles:
- { name: "notepadplusplus", tags: "notepadplusplus", when: not (done_role_notepadplusplus | default(false)) }
tags:
- notepadplusplus
playbooks/roles/tasks/notepadplusplus.yml
---
- name: Deploy Notepad++
chocolatey.chocolatey.win_chocolatey:
name: notepadplusplus
version: "{{ notepadplusplus_version }}"
state: present
- name: Mark role as visited
set_fact: done_role_notepadplusplus=true
inventories/20a_Site_WRN_Test.yml
---
npp:
hosts:
somemachine.EXAMPLE.COM
... other inventory files' content is not relevant to reproduce.
ansible.cfg
[defaults]
callbacks_enabled=ansible.posix.profile_tasks
inventories/group_vars/all/common.yml
---
ansible_connection: winrm
ansible_port: 5985
ansible_winrm_kinit_mode: managed
ansible_winrm_transport: kerberos
ansible_winrm_realm: EXAMPLE.COM
keepass_dbx: "ansible.kdbx"
ansible_user: "{{ lookup('viczem.keepass.keepass', 'ansible.svc', 'username') }}"
ansible_username: "{{ lookup('viczem.keepass.keepass', 'ansible.svc', 'username') }}"
ansible_password: "{{ lookup('viczem.keepass.keepass', 'ansible.svc', 'password') }}"
notepadplusplus_version: '8.6.0'
Expected Results
The expectation is that ansible-playbook can be run multiple times in sequence through the above script, even if used together with unbuffer, tee and sed to get a log file, colored console output, etc. (see description for the whole list).
Actual Results
The first execution works, but subsequent executions fail with the error:
An unhandled exception occurred while running the lookup plugin 'viczem.keepass.keepass'. Error was a <class 'ConnectionRefusedError'>, original message: [Errno 111] Connection refused. [Errno 111] Connection refused
Summary
Note:
This issue was originally filed as ansible/ansible#84429 but was closed there due to the argument that I should create an issue in this repository.
When ansible-playbook is executed together with
unbuffer(see https://linux.die.net/man/1/unbuffer ), The lock file in/tmp/ofviczem.keepass.keepassis not cleaned up after execution ofansible-playbookfinishes.My whole setup:
Ansible is used in a docker container. I use docker version
20.10.3, build 48d30b5. TheDockerfilelooks like this:The image is built on one host, then pushed into a private registry and pulled from another host and also started (and running) there. Inside the container I have a bash script doing the following:
When I enter the freshly started container by
ssh-ing into it through the exposed ssh port (which is redirected to port 2222) and executing the above bash-script through the following command:... I get my expected behavior. This means that the playbook does what it is supposed to to: It fetches passwords from the keepass file (*.kdbx), gathers facts through authenticating as the correct user through credentials obtained from keepass, performs tasks successfully and exits.
BUT: Any subsequent execution of my script fails nearly instant at the beginning with the following error:
The reason for the error:
could be tracked down to the use of
unbufferin my script. If I remove the "unbuffer" from the script, the playbook works correctly if called repeatedly. My investigations have shown that a lock file and the socket file ofviczem.keepass.keepassare not cleaned up properly after execution of the playbook. To be precise: Afteransible-playbookfinishes. The following command shows what remains in the/tmp/directory:ansible@7c4670e0329b:/opt/ansible$ ls -la /tmp/ total 8 drwxrwxrwt 1 root root 4096 Dec 5 05:53 . drwxr-xr-x 1 root root 4096 Dec 5 05:17 .. srw------- 1 ansible ansible 0 Dec 5 05:25 ansible-keepass-9e61ddcf.sock -rw------- 1 ansible ansible 0 Dec 5 05:25 ansible-keepass-9e61ddcf.sock.lock srwxrwxr-x 1 ansible ansible 0 Dec 5 05:17 vscode-git-5449f56b2c.sock srwxrwxr-x 1 ansible ansible 0 Dec 5 05:18 vscode-git-69fe405b86.sock srwxrwxr-x 1 ansible ansible 0 Dec 5 05:18 vscode-ipc-7c3ccf14-f69d-45e3-84d5-7aca870cdf76.sock srwxrwxr-x 1 ansible ansible 0 Dec 5 05:18 vscode-ipc-7c5270a5-5651-4f79-936d-ccfa3d41d6e7.sock srwxrwxr-x 1 ansible ansible 0 Dec 5 05:17 vscode-ipc-9a116bb8-19ba-4764-a674-7670abc33495.sock ansible@7c4670e0329b:/opt/ansible$More explanation to the call to
ansible-playbookas it is done in the script:unbuffer ansible-playbook -i inventories/10_Site_Common.yml \ -i inventories/20a_Site_WRN_Test.yml \ -i inventories/20a_Site_WRN_ProdTest.yml \ -i inventories/20a_Site_WRN_ProdTest_291.yml \ -i inventories/20a_Site_WRN_ProdTest_292.yml \ -i inventories/20z_Development.yml \ --limit $LIMIT \ $PLAYBOOK \ --check -vvvvv \ | tee >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOGFILENAME)$LIMIT,$LOGFILENAMEand$PLAYBOOKare populated with (for me) meaningful values in the script before--checkand-vvvvvare only there to provide input to this issue here and are not part of regular executions.unbuffer,teeandsedare used for the purpose of:ansible-playbookexecutionANSIBLE_KEEPASS_PSWbefore execution of the scriptIf I manually
rm /tmp/ansible-keepass-*after execution of the above script, the issue is gone.Also, if I call a modified bash script with the following content, the issue does not occur:
ansible-playbook -i inventories/10_Site_Common.yml \ -i inventories/20a_Site_WRN_Test.yml \ -i inventories/20a_Site_WRN_ProdTest.yml \ -i inventories/20a_Site_WRN_ProdTest_291.yml \ -i inventories/20a_Site_WRN_ProdTest_292.yml \ -i inventories/20z_Development.yml \ --limit $LIMIT \ $PLAYBOOK \ --check -vvvvv \ | tee >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOGFILENAME)I suspect the handling of the lock file (creation and cleanup) to have problems with
unbuffer.For the time being I will just cleanup after
ansible-playbookhas run by removing the lock file and socket file manually, but maybe there is a way to fix it directly in ansible or the plugin?Issue Type
Bug Report
Component Name
viczem.keepass.keepass
Ansible Version
Configuration
OS / Environment
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
Steps to Reproduce
playbooks/notepadplusplus.yml
playbooks/roles/tasks/notepadplusplus.yml
inventories/20a_Site_WRN_Test.yml
... other inventory files' content is not relevant to reproduce.
ansible.cfg
inventories/group_vars/all/common.yml
Expected Results
The expectation is that
ansible-playbookcan be run multiple times in sequence through the above script, even if used together withunbuffer,teeandsedto get a log file, colored console output, etc. (see description for the whole list).Actual Results