I'm learning Ansible and I'm trying to convert these Homebrew commands using Ansible's homebrew_tap and homebrew_cask:
brew tap homebrew/cask-fonts
brew install --cask font-hack-nerd-font
My Ansible playbook looks like this:
---
- name: test
hosts: localhost
tasks:
- name: Tapping homebrew/cask-fonts
homebrew_tap:
name: homebrew/cask-fonts
- name: Installing Nerd Font
homebrew_cask:
name: font-hack-nerd-font
When I run it, I get this error:
PLAY [test] ****************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Tapping homebrew/cask-fonts] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Installing Nerd Font] ************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Invalid cask: font-hack-nerd-font."}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
I'm hoping to be able to pull this off using homebrew_cask without brew command directly.
Any guidance is greatly appreciated. Thank you.
It's reported as a bug due to hyphen(s) in the cask package name. This bug is resolved via pull request.
Related
I am trying to understand --become in order to use ansible to do some local task on my centos. I tried several ansible modules (copy, unarchive) with become that each result with diffetent kind of errors.
Platform used: centos 7
Ansible (installed in a python 3 virtual env) version:
(ansible) [maadam#linux update_centos]$ ansible --version
ansible 2.10.16
config file = None
configured module search path = ['/home/maadam/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/maadam/Sources/python/venv/ansible/lib64/python3.6/site-packages/ansible
executable location = /home/maadam/Sources/python/venv/ansible/bin/ansible
python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
I tried to reproduice the example provided by #techraf in this issue to test become: Using --become for ansible_connection=local.
I used the same playbook:
---
- hosts: localhost
gather_facts: no
connection: local
tasks:
- command: whoami
register: whoami
- debug:
var: whoami.stdout
So I hope the same result as this:
(ansible) [maadam#linux update_centos]$ sudo whoami
root
Whithout become:
ansible) [maadam#linux update_centos]$ ansible-playbook playbook.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost
does not match 'all'
PLAY [localhost] ***************************************************************************************
TASK [command] *****************************************************************************************
changed: [localhost]
TASK [debug] *******************************************************************************************
ok: [localhost] => {
"whoami.stdout": "maadam"
}
PLAY RECAP *********************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
With become I have this error:
(ansible) [maadam#linux update_centos]$ ansible-playbook playbook.yml --become
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost
does not match 'all'
PLAY [localhost] ***************************************************************************************
TASK [command] *****************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "/var/tmp/sclPip796: line 8: -H: command not found\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 127}
PLAY RECAP *********************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
So I don't understand what I am missing with become.
Thanks for your helps
in ansible.cfg file check for the become_method. you can use "sudo su -".
I don't know if I handle this correctly but if I run my playbook as root, I have no error:
(ansible) [maadam#linux update_centos]$ sudo ansible-playbook playbook.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [command] ****************************************************************************************************************************************************************************************************
changed: [localhost]
TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [localhost] => {
"whoami.stdout": "root"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Not sure it is the right way to doing things in local with ansible. Sure if you are already root, no need for privilege escalation.
I want a playbook to validate that some packages are installed and fail that system if they are not. I thought I could use the package: module as a non-root user and have it validate the packages were installed.
I thought that the idempotency of Ansible would permit (actually encourage) this usage. Is this a bug or enhancement that I should escalate, or am I overlooking something simple to achieve this?
Here is my playbook for testing:
---
- name: Show package module non-root usage
hosts: all
become: false
tasks:
- name: Check that a packages is installed
package:
name:
- vim-common
state: installed
As a normal user I can see that vim-common is installed:
$ rpm -qa vim-common
vim-common-8.0.1763-15.el8.x86_64
$ dnf list vim-common
Not root, Subscription Management repositories not updated
Last metadata expiration check: 0:00:29 ago on Thu 21 Jan 2021 12:50:56 PM CST.
Installed Packages
vim-common.x86_64 2:8.0.1763-15.el8 #rhel-8-for-x86_64-appstream-rpms
$
But when I run the playbook I get this error instead of a "success" result:
$ ansible-playbook package_check.yml -i localhost, --connection=local
PLAY [Show package module non-root usage] *********************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [localhost]
TASK [Check that a packages is installed] *********************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "This command has to be run under the root user.", "results": []}
PLAY RECAP ****************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
$
As expected, when I run it as root it works properly:
$ sudo ansible-playbook package_check.yml -i localhost, --connection=local
PLAY [Show package module non-root usage] *********************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [localhost]
TASK [Check that a packages is installed] *********************************************************************************************
ok: [localhost]
PLAY RECAP ****************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$
My system is Red Hat Enterprise Linux release 8.3 (Ootpa) with Ansible 2.10:
$ ansible-playbook --version
ansible-playbook 2.10.4
config file = /home/dan/.ansible.cfg
configured module search path = ['/home/dan/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 3.6.8 (default, Aug 18 2020, 08:33:21) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
Update #1
Searching through the Ansible code, the dnf.py module is where this comes from:
$ egrep -C3 "This command has to be run under the root user." /usr/local/lib/python3.6/site-packages/ansible/modules/dnf.py
# before running it.
if not dnf.util.am_i_root():
self.module.fail_json(
msg="This command has to be run under the root user.",
results=[],
)
self.base = self._base(
$
If I comment out that root check block:
$ egrep -C3 "This command has to be run under the root user." /usr/local/lib/python3.6/site-packages/ansible/modules/dnf.py
# before running it.
# if not dnf.util.am_i_root():
# self.module.fail_json(
# msg="This command has to be run under the root user.",
# results=[],
# )
self.base = self._base(
$
I can now run the playbook and it confirms the package is installed without needing root permissions:
$ ansible-playbook package_check.yml -i localhost, --connection=local
PLAY [Show package module non-root usage] *********************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [localhost]
TASK [Check that a packages is installed] *********************************************************************************************
ok: [localhost]
PLAY RECAP ****************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$
Update #2
Slightly modifying the playbook to check an installed and a missing package:
$ cat package_check.yml
#!/usr/bin/env /usr/local/bin/ansible-playbook
---
- name: Show package module non-root usage
hosts: all
become: false
tasks:
- name: Check that VIM common is installed
package:
name:
- vim-common
state: installed
- name: Check that EMACS is installed
package:
name:
- vim-common
- emacs
state: installed
$
Now we get a success on the first and a failure on the second:
$ ansible-playbook package_check.yml -i localhost, --connection=local
PLAY [Show package module non-root usage] *********************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [localhost]
TASK [Check that VIM common is installed] *********************************************************************************************
ok: [localhost]
TASK [Check that EMACS is installed] **************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "2021-01-21 13:27:23,224 [ERROR] dnf.py:724879:MainThread #logutil.py:194 - [Errno 13] Permission denied: '/var/log/rhsm/rhsm.log' - Further logging output will be written to stderr\n2021-01-21 13:27:23,233 [ERROR] dnf.py:724879:MainThread #identity.py:156 - Reload of consumer identity cert /etc/pki/consumer/cert.pem raised an exception with msg: [Errno 13] Permission denied: '/etc/pki/consumer/key.pem'\nTraceback (most recent call last):\n File \"/home/dan/.ansible/tmp/ansible-tmp-1611257242.3944752-724867-4205539601634/AnsiballZ_dnf.py\", line 102, in <module>\n _ansiballz_main()\n File \"/home/dan/.ansible/tmp/ansible-tmp-1611257242.3944752-724867-4205539601634/AnsiballZ_dnf.py\", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/home/dan/.ansible/tmp/ansible-tmp-1611257242.3944752-724867-4205539601634/AnsiballZ_dnf.py\", line 40, in invoke_module\n runpy.run_module(mod_name='ansible.modules.dnf', init_globals=None, run_name='__main__', alter_sys=True)\n File \"/usr/lib64/python3.6/runpy.py\", line 205, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File \"/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\n mod_name, mod_spec, pkg_name, script_name)\n File \"/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\n exec(code, run_globals)\n File \"/tmp/ansible_ansible.legacy.dnf_payload_ewju4h_n/ansible_ansible.legacy.dnf_payload.zip/ansible/modules/dnf.py\", line 1330, in <module>\n File \"/tmp/ansible_ansible.legacy.dnf_payload_ewju4h_n/ansible_ansible.legacy.dnf_payload.zip/ansible/modules/dnf.py\", line 1319, in main\n File \"/tmp/ansible_ansible.legacy.dnf_payload_ewju4h_n/ansible_ansible.legacy.dnf_payload.zip/ansible/modules/dnf.py\", line 1294, in run\n File \"/tmp/ansible_ansible.legacy.dnf_payload_ewju4h_n/ansible_ansible.legacy.dnf_payload.zip/ansible/modules/dnf.py\", line 1213, in ensure\n File \"/usr/lib/python3.6/site-packages/dnf/base.py\", line 882, in do_transaction\n tid = self._run_transaction(cb=cb)\n File \"/usr/lib/python3.6/site-packages/dnf/base.py\", line 955, in _run_transaction\n tid = self.history.beg(rpmdbv, using_pkgs, [], cmdline, comment)\n File \"/usr/lib/python3.6/site-packages/dnf/db/history.py\", line 473, in beg\n comment)\n File \"/usr/lib64/python3.6/site-packages/libdnf/transaction.py\", line 763, in beginTransaction\n return _transaction.Swdb_beginTransaction(self, *args)\nlibdnf._error.Error: SQLite error on \"/var/lib/dnf/history.sqlite\": Reading a row failed: attempt to write a readonly database\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
PLAY RECAP ****************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
$
And running as root works as expected:
$ sudo ansible-playbook package_check.yml -i localhost, --connection=local
PLAY [Show package module non-root usage] *********************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************
ok: [localhost]
TASK [Check that VIM common is installed] *********************************************************************************************
ok: [localhost]
TASK [Check that EMACS is installed] **************************************************************************************************
changed: [localhost]
PLAY RECAP ****************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$
This is because state: installed is meant to install the package if it does not exists. So, this is not strictly equal to polling your package manager for a packet.
In order to do this, you will have to use the package_facts gatherer.
Then you can easily use failed_when on that same task if the package(s) you expect are not present.
Here would be an example playbook:
- hosts: all
gather_facts: no
tasks:
- package_facts:
failed_when: "'apache2' not in ansible_facts.packages"
In order to solve the use case you stated in the comment below, you can always use the variable ansible_check_mode:
- hosts: all
gather_facts: no
tasks:
- package_facts:
failed_when: "'apache2' not in ansible_facts.packages"
when: ansible_check_mode
- package:
name: apache2
when: not ansible_check_mode
[root#prdx-ansible docker_ansible]# ansible-playbook playbook.yml -i inventory.txt
PLAY [Deploy web app] *******************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [target1]
ok: [target2]
TASK [Install all dependencies] *********************************************************************************************************************************************
[WARNING]: Updating cache and auto-installing missing dependency: python3-apt
fatal: [target1]: FAILED! => {"changed": false, "msg": "'/usr/bin/apt-mark manual python python-setuptools python-dev build-essential python-pip python-mysqldb' failed: E: Couldn't create temporary file to work with /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_InRelease - mkstemp (28: No space left on device)\nE: The package lists or status file could not be parsed or opened.\n", "rc": 100, "stderr": "E: Couldn't create temporary file to work with /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_InRelease - mkstemp (28: No space left on device)\nE: The package lists or status file could not be parsed or opened.\n", "stderr_lines": ["E: Couldn't create temporary file to work with /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_InRelease - mkstemp (28: No space left on device)", "E: The package lists or status file could not be parsed or opened."], "stdout": "", "stdout_lines": []}
fatal: [target2]: FAILED! => {"changed": false, "msg": "'/usr/bin/apt-mark manual python python-setuptools python-dev build-essential python-pip python-mysqldb' failed: E: Couldn't create temporary file to work with /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_InRelease - mkstemp (28: No space left on device)\nE: The package lists or status file could not be parsed or opened.\n", "rc": 100, "stderr": "E: Couldn't create temporary file to work with /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_InRelease - mkstemp (28: No space left on device)\nE: The package lists or status file could not be parsed or opened.\n", "stderr_lines": ["E: Couldn't create temporary file to work with /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_InRelease - mkstemp (28: No space left on device)", "E: The package lists or status file could not be parsed or opened."], "stdout": "", "stdout_lines": []}
PLAY RECAP ******************************************************************************************************************************************************************
target1 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
target2 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
here is playbook
[root#prdx-ansible docker_ansible]# cat playbook.yml
- name: Deploy web app
hosts: target1,target2
tasks:
- name: Install all dependencies
package:
name: ['python', 'python-setuptools', 'python-dev', 'build-essential', 'python-pip', 'python-mysqldb']
state: present
- name: Install MySQL database
apt: name={{ item }} state=installed
with_items:
- mysql-server
- mysql-client
- name: Start the database service
service:
name: mysql
state: statred
enabled: yes
- name: Create database
mysql_db: name=emploee_db state=present
- name: Create DB user
mysql_user:
name: db_user
password: Passw0rd
priv: '*.*:ALL'
state: present
host: '%'
- name: Install Flask
pip:
name: "{{ item }}"
state: present
with_items:
Couldn't create temporary file to work with [..] mkstemp (28: No space left on device)
Your target server disk seems to be full. Check with df -h how much space you have left. You may have to run apt-get clean and similar commands to clean up some space.
[root#prdx-ansible docker_ansible]# ansible-playbook playbook.yml -i inventory.txt
PLAY [Deploy web app] *******************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [target1]
ok: [target2]
TASK [Install all dependencies] *********************************************************************************************************************************************
[WARNING]: Updating cache and auto-installing missing dependency: python3-apt
changed: [target2]
changed: [target1]
TASK [Install MySQL database] ***********************************************************************************************************************************************
[DEPRECATION WARNING]: Invoking "apt" only once while using a loop via squash_actions is deprecated. Instead of using a loop to supply multiple items and specifying `name:
"{{ item }}"`, please use `name: ['mysql-server', 'mysql-client']` and remove the loop. This feature will be removed in version 2.11. Deprecation warnings can be disabled
by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Invoking "apt" only once while using a loop via squash_actions is deprecated. Instead of using a loop to supply multiple items and specifying `name:
"{{ item }}"`, please use `name: ['mysql-server', 'mysql-client']` and remove the loop. This feature will be removed in version 2.11. Deprecation warnings can be disabled
by setting deprecation_warnings=False in ansible.cfg.
changed: [target2] => (item=[u'mysql-server', u'mysql-client'])
changed: [target1] => (item=[u'mysql-server', u'mysql-client'])
TASK [Start the database service] *******************************************************************************************************************************************
fatal: [target2]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 172.17.03 closed.\r\n", "module_stdout": "/bin/sh: 1: sudo: not found\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 127}
fatal: [target1]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 172.17.02 closed.\r\n", "module_stdout": "/bin/sh: 1: sudo: not found\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 127}
PLAY RECAP ******************************************************************************************************************************************************************
target1 : ok=3 changed=2 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
target2 : ok=3 changed=2 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
NOW I GOT THIS ERROR!!
When i try to install a list of packages('apache2', 'libapache2-mod-wsgi', 'python-pip', 'python-virtualenv') on on a group of hosts (app01 and app02),
it fails randomly either on app01 or app02.
After a first few retries the required packages are already installed on the host. Subsequent execution continue to fail randomly on app01 or app02 instead of returning a simple success.
The ansible controller and hosts are all running ubuntu 16.04
The controller has ansible 2.8.4
I have already set "become: yes" in playbook.
I have already tried running apt-get clean and apt-get update. on the hosts
Inventory file
[webserver]
app01 ansible_python_interpreter=python3
app02 ansible_python_interpreter=python3
Playbook
---
- hosts: webserver
tasks:
- name: install web components
become: yes
apt:
name: ['apache2', 'libapache2-mod-wsgi', 'python-pip', 'python-virtualenv']
state: present
update_cache: yes
In the first run , the execution fails on host app01
In the second run, the execution fails on host app02
1 st Run
shekhar#control:~/ansible$ ansible-playbook -v playbooks/webservers.yml
Using /home/shekhar/ansible/ansible.cfg as config file
PLAY [webserver] ******************************************************************************
TASK [Gathering Facts] ******************************************************************************
ok: [app01]
ok: [app02]
TASK [install web components] ******************************************************************************
fatal: [app01]: FAILED! => {"changed": false, "msg": "Failed to lock apt for exclusive operation"}
ok: [app02] => {"cache_update_time": 1568203558, "cache_updated": false, "changed": false}
PLAY RECAP ******************************************************************************
app01 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
app02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2nd Run
shekhar#control:~/ansible$ ansible-playbook -v playbooks/webservers.yml
Using /home/shekhar/ansible/ansible.cfg as config file
PLAY [webserver] ******************************************************************************
TASK [Gathering Facts] ******************************************************************************
ok: [app01]
ok: [app02]
TASK [install web components] ******************************************************************************
fatal: [app02]: FAILED! => {"changed": false, "msg": "Failed to lock apt for exclusive operation"}
ok: [app01] => {"cache_update_time": 1568203558, "cache_updated": false, "changed": false}
PLAY RECAP ******************************************************************************
app01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
app02 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
The behavior is a bit strange… one succeed, and other failing each time.
My guess is that your app01 and app02 are actually the same host! If so, it sounds normal that the 2 jobs fight against each other.
- hosts: Ebonding
become: yes
become_method: sudo
tasks
- name: Clearing cache of Server4
file: path=/weblogic/bea/user_projects/domains/tmp state=absent
become: yes
become_user: wls10
Ansible version 2.0.0.0 run the above playbook successfully::
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [ggnqinfa2]
TASK [Clearing cache of Server4] ***********************************************
ok: [ggnqinfa2]
PLAY RECAP *********************************************************************
ggnqinfa2 : ok=2 changed=0 unreachable=0 failed=0
But latest version of ansible 2.5.0rc2 encountered below error::
PLAY [Ebonding] *****************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************
ok: [ggnqinfa2]
TASK [Clearing cache of Server4] ************************************************************************************************************************************
fatal: [ggnqinfa2]: FAILED! => {"msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 2, err: chown: /var/tmp/ansible-tmp-1520704924.34-191458796685785/: Not owner\nchown: /var/tmp/ansible-tmp-1520704924.34-191458796685785/file.py: Not owner\n}). For information on working around this, see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user"}
PLAY RECAP **********************************************************************************************************************************************************
ggnqinfa2 : ok=1 changed=0 unreachable=0 failed=1
How can i run this playbook by latest version of ansible successfully?
Chances are the user you're using (wls10) does not have write access to the remote temporary directory /var/tmp.
This can be overridden using ansible.cfg and set via remote_tmp to a directory you have write-access to -- or, a "normal temp directory" (like /tmp) that has the sticky bit set.
For more info, see
http://docs.ansible.com/ansible/latest/intro_configuration.html#remote-tmp