semaphoreui / semaphore

Modern UI and powerful API for Ansible, Terraform, OpenTofu, PowerShell and other DevOps tools.
https://semaphoreui.com
MIT License
10.58k stars 1.07k forks source link

semaphore + ansible without venv #1075

Open soda-pop-ice-cream opened 2 years ago

soda-pop-ice-cream commented 2 years ago

Hi there! Looks like i having same issue like this one ModuleNotFoundError: No module named 'ansible' #714. I tried installing .deb + python3 -m pip install --user ansible on clean debian 10,11,12, different python, pip and ansible versions and always had same result in semaphore:

7:39:24 PM Task 5 added to queue
7:39:28 PM Preparing: 5
7:39:28 PM Prepare TaskRunner with template: some_name
7:39:28 PM Updating Repository file:///home/ansible/ansible-stuff
7:39:28 PM From file:///home/ansible/ansible-stuff
7:39:28 PM * branch main -> FETCH_HEAD
7:39:28 PM Already up to date.
7:39:28 PM Get current commit hash
7:39:28 PM Get current commit message
7:39:28 PM installing static inventory
7:39:28 PM No collections/requirements.yml file found. Skip galaxy install process.
7:39:28 PM No roles/requirements.yml file found. Skip galaxy install process.
7:39:33 PM Started: 5
7:39:33 PM Run TaskRunner with template: some_name
7:39:33 PM Traceback (most recent call last):
7:39:33 PM File "/home/ansible/.local/bin/ansible-playbook", line 34, in
7:39:33 PM from ansible import context
7:39:33 PM ModuleNotFoundError: No module named 'ansible'
7:39:33 PM Running playbook failed: exit status 1

Yes, i can create venv, start semaphore with ampersand and it'll work, but i want use systemd-unit (which not so friendly with venv's) in case of server reboot/process stop/kill/fault ampersand won't restart semaphore.

And so, my question is: is semaphore doesn't work with ansible installed without venv?

nlvw commented 2 years ago

I've deployed Semaphore with both a VENV and using a container. The trick is for your systemd unit file use a shell script to launch semaphore. In that shell script you can source your VENV activate script. Super simple.

soda-pop-ice-cream commented 2 years ago

That's cool, but still doesn't explains why it can't work without venv.

nlvw commented 2 years ago

Post a copy of your systems unit file that is not working. VENV is not a requirement, it is just the most convenient method. Usually errors like this are due to systemd stripping environment variables or forgetting to set the correct user in the unit file.

jrglynn2 commented 1 year ago

I just installed semaphore, and am getting the same error - {Edited to add more lines of error}

1:44:01 PM
File "/home/ec2-user/.local/bin/ansible-playbook", line 5, in
1:44:01 PM
from ansible.cli.playbook import main
1:44:01 PM
ModuleNotFoundError: No module named 'ansible'
1:44:01 PM
Running playbook failed: exit status 1

I do not use venv for either semaphore or ansible. Running ansible commands from the command line works fine, but it seems like Semaphore doesn't see ansible for some reason. ETA: you can see that it finds ansible-playbook, but ansible-playbook then can't seem to find ansible.

Here is my systemd service file. I tried adding the Environment line, which is a copy of my normal path, and ec2-user is the user we use to run ansible commands from server command line.

[Unit]
Description=Semaphore Ansible
Documentation=https://github.com/ansible-semaphore/semaphore
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
Environment="PATH=/home/ec2-user/.local/bin:/home/ec2-user/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin"
User=ec2-user
Group=ec2-user
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/bin/semaphore service --config=/opt/semaphore/config/config.json
SyslogIdentifier=semaphore
Restart=always

[Install]
WantedBy=multi-user.target
jrglynn2 commented 1 year ago

I found a solution for my version of this issue.

Ansible for me was installed as a user (executable location = /home/ec2-user/.local/bin/ansible) . For some reason using ec2-user as User & Group in the service file wasn't enough, so I had to add a PYTHONPATH variable (https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPATH).

In order to get the proper path to use for PYTHONPATH, I ran python -c "import site; print(site.USER_SITE)" when logged in as ec2-user.

So, I ended up adding this line to my service file: Environment=PYTHONPATH=/home/ec2-user/.local/lib/python3.9/site-packages

steadfasterX commented 1 year ago

For my specific issue the PYTHONPATH set by Environment alone did not solve it (while it is required, thx @jrglynn2 ). I was still not able to get e.g. the python-gitlab module working when using semaphore (installed as "--user" by pip). It worked fine when executed on the CLI so it was clear it is systemd or semaphore related.

Finally found a fix for my situation:

My systemd user has a different home then the semaphore setting for tmp_path in config.json. It seems semaphore uses tmp_path as home when running playbooks. the systemd service must point to that directory as well, which also should include (if you have any non-default settings) your .ansible.cfg (yes, dotansible.cfg). As said this dir will be treated as the home dir.

So I had to add the WorkingDirectory key which must point to the defined tmp_path in config.json.

Final result:

my setup:
    User semaphore's regular home: /home/semaphore
    tmp_path in config.json: /opt/data/semaphore/plays
   .ansible.cfg: /opt/data/semaphore/plays/.ansible.cfg

systemd service:

[Unit]
Description=Ansible Semaphore
Documentation=https://docs.ansible-semaphore.com/
Wants=network-online.target
After=network-online.target
ConditionPathExists=/usr/bin/semaphore
ConditionPathExists=/etc/semaphore/config.json

[Service]
User=semaphore
Group=semaphore
ExecStart=/usr/bin/semaphore service --config /etc/semaphore/config.json
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=20s
# to auto-upgrade python modules at service startup
ExecStartPre=/bin/bash -c 'python3.11 -m pip install --upgrade --user -r /etc/semaphore/python-requirements.txt'
# so the executables are found
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:~/.local/bin"
# to fix "python module not found" issues, the following WorkingDirectory must point to the same
# directory as ` tmp_path`  variable in your semaphore config.json
# if using non-default ansible.cfg params, it also should contain your `.ansible.cfg` (yes, `dot`ansible.cfg)
WorkingDirectory=/opt/data/semaphore/plays
# besides the WorkingDirectory we need to tell systemd where to find your pip installed libs:
# to find out the user's as $User exec: python -c "import site; print(site.USER_SITE)"
Environment="PYTHONPATH=/home/semaphore/.local/lib/python3.11/site-packages"

[Install]
WantedBy=multi-user.target