pytest-testinfra
pytest-testinfra copied to clipboard
Service is_enabled KO
Hi
I'm testing a salt formula via kitchen, installing and enabling caddy service. As you can see, the service is enabled
kitchen@74cb1d70442b:~$ sudo su
root@74cb1d70442b:/home/kitchen# systemctl status caddy
● caddy.service - Caddy HTTP/2 web server
Loaded: loaded (/lib/systemd/system/caddy.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2019-03-19 10:45:59 UTC; 32min ago
Docs: https://caddyserver.com/docs
Main PID: 3042 (caddy)
Tasks: 10 (limit: 4915)
CGroup: /docker/74cb1d70442be3231e88e77c241e11f01e3af60b87eeb25c89df9140535eaa55/system.slice/caddy.service
└─3042 /usr/bin/caddy -log stdout -agree=true -email [email protected] -conf=/etc/caddy/Caddyfile -root=/var/tmp
But testinfra thinks otherwise
============================= test session starts ==============================
platform linux2 -- Python 2.7.13, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
rootdir: /var/lib/jenkins/workspace/salt-formula-caddy/test, inifile: pytest.ini
plugins: testinfra-1.19.0, metadata-1.8.0, html-1.20.0
collected 6 items
test/integration/test_caddy.py ....FF [100%]
=================================== FAILURES ===================================
_ test_service[docker://74cb1d70442be3231e88e77c241e11f01e3af60b87eeb25c89df9140535eaa55] _
host = <testinfra.host.Host object at 0x7ffb77697710>
def test_service(host):
s = host.service("caddy")
assert s.is_running
> assert s.is_enabled
E assert False
E + where False = <service caddy>.is_enabled
Here's the kitchen verifier command if that might help
verifier:
name: shell
remote_exec: false
command: pytest --junitxml=test/${KITCHEN_INSTANCE}_test_report.xml --html=test/${KITCHEN_INSTANCE}_test_report.html --self-contained-html --color=yes --host="docker://root@${KITCHEN_CONTAINER_ID}" "test/integration/"
Hi,
You can run py.test with -vvs
flags to enable debug output and see what command is actually run by testinfra.
In this case I think testinfra run systemctl is-enabled caddy
what is the output of this command ?
Ok, I found why. https://github.com/philpep/testinfra/blob/master/testinfra/modules/service.py#L54
We are running tests in a docker container and systemd is lauched by docker, so there is no /sbin/init link and testinfra fallback to SysVinit which can't work.
I got around by adding the missing link in our containers.
Maybe we should look for /proc/1/exe instead of /sbin/init That being said, IIRC, some commands work with systemd not being pid 1 (like systemctl is-enabled).
That's also an issue I get with a container based on Archlinux.
The link /sbin/init
doesn't exist and Testinfra falls back to SysVinit.
cat
ing /proc/1/comm
seems to give good results (here are some tests I did on vagrant boxes):
- Gentoo :
init
(+rc-service
exists) =>OpenRCService
; - Ubuntu 14.04 :
init
(+initctl
exists) =>UpstartService
; - Ubuntu 19.04 :
systemd
=>SystemdService
; - Debian Stretch :
systemd
=>SystemdService
; - Archlinux :
systemd
=>SystemdService
.
Also, wouldn't it be a better idea to fall back to SystemdService
?
I'm volunteering to write a PR if the above sounds OK to you :-)
Ok, I found why. https://github.com/philpep/testinfra/blob/master/testinfra/modules/service.py#L54
We are running tests in a docker container and systemd is lauched by docker, so there is no /sbin/init link and testinfra fallback to SysVinit which can't work.
I got around by adding the missing link in our containers.
I have this exact same problem when running tests using a systemd-enabled Debian 9 image. In my case, though, I'm running systemd inside of a Docker container, and so my systemd process is not PID 1.
Ok, I found why. https://github.com/philpep/testinfra/blob/master/testinfra/modules/service.py#L54 We are running tests in a docker container and systemd is lauched by docker, so there is no /sbin/init link and testinfra fallback to SysVinit which can't work. I got around by adding the missing link in our containers.
I have this exact same problem when running tests using a systemd-enabled Debian 9 image. In my case, though, I'm running systemd inside of a Docker container, and so my systemd process is not PID 1.
In case anyone else encounters this issue when exercising testinfra via molecule, I was able to get around it by creating molecule/default/prepare.yml
with the following content:
- name: Group hosts by OS distribution
hosts: all
tasks:
- name: Group hosts by OS distribution
group_by:
key: os_{{ ansible_facts['distribution'] }}
- name: Install init (Debian)
hosts: os_Debian
tasks:
- name: Install init (Debian)
package:
name:
- init
Hi, it seems that adding the systemd-sysv
package to docker resolves the problem.
See: https://github.com/geerlingguy/docker-debian10-ansible/pull/4
So I can confirm that testinfra (3.4.0) test now passes with those services:
assert host.service("postfix").is_enabled
assert host.service("mariadb").is_enabled
assert host.service("nftables").is_enabled
assert host.service("ntp").is_enabled
assert host.service("rsync").is_enabled
assert host.service("ssh").is_enabled
assert host.service("zabbix-agent").is_enabled