Closed bogen85 closed 2 weeks ago
Here is a more exhaustive/comprehensive repro steps.
Needs to be run on a systemd Linux distro with host python/pip/venv installed.
User needs sudo.
Put these 4 files in your directory and type make basic-prep
after renaming 3 of the files.
requirements.txt Makefile.txt initial_prep.py.txt chroot.py.txt
Rename 3 of the files
mv Makefile.txt Makefile
mv chroot.py.txt chroot.py
mv initial_prep.py.txt initial_prep.py
make basic-prep
# changes have now been made
# make basic-prep again...
make basic-prep
Update: I updated the chroot wrapper (what is above works) chroot.py
#!/usr/bin/python3
# vim: set expandtab tabstop=4 shiftwidth=4 filetype=python3 :
import os, sys
PATH = '/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin'
SHELL = '/bin/sh'
cmd = [
'sudo', 'systemd-nspawn', '--quiet', f'--setenv=PATH={PATH}',
'--setenv=SHELL={SHELL}', '--directory',
]
cmd.extend(sys.argv[1:])
os.execvp(cmd[0], cmd)
From initial_prep.py above:
for runlevel in SERVICES.keys():
links = [x.strip() for x in host.get_fact(FindLinks, f'/etc/runlevels/{runlevel}', quote_path=False)]
for service in SERVICES[runlevel].split():
path, target = f'/etc/runlevels/{runlevel}/{service}', f'/etc/init.d/{service}'
if (path in links) and (host.get_fact(Link, path)["link_target"].strip().removesuffix("'") == target):
session.append(f'\tservice {service} already in runlevel {runlevel}')
else:
files.link(name = f'Add {service} to runlevel {runlevel}', path = path, target = target, force=True)
Notice that I had to clean up the link_target fact for the Link path (there was and extraneous trailing single quote.)
I've not dug into the files.link code, it is possible if it is trying to check, that the check is failing. (As my initial check did as well, until I looked at what was being returned and cleaned it up).
The equivalent in Ansible, while the output is cleaner, required me to removed the soft link of sh to busybox and make it a hard link. Also, I had to run ansible via sudo to get to work with the chroot. With pyinfra because I was able to use a chroot wrapper, so I did not need to run pyinfra via sudo.
Both Ansible and Pyinfra took about the same time. As I initially stated though, Ansible was more "correct" in determining what needed to be done.
That being said, Pyinfra shows a lot of promise and is by far more flexible.
See #732 for discussion of the quoting issue that led the path link fact not being correct.
For #729 @Fizzadar wrote:
@bogen85 Re:
systemd-nspawn
- are you using the@chroot
connector at the moment? There's two approaches here:* A new connector specific for `systemd-nspawn` * Add a configuration field `host.data.X` to change the behaviour of the `@chroot` connector (this is probably nicer?)
Regarding systemd-nspawn, yes, I'm using the @chroot connector along with a chroot wrapper script in my path. (Details already discussed in this issue). I'm open to either (new connector or new configuration field) as long as I have the some functionality I'm getting from the wrapper (systemd-nspawn run with sudo, not all of pyinfra) (with ansible and chroot, all of ansible has to be run as root).
I think this is fixed? At least the init.d operation. Please re-open if not!
Describe the bug
Maybe this the chroot connection, not sure. But facts do work... Anyways, If I use openrc to enable a service in a chroot install, it works (Success). However, if I rerun I don't get "No Changes" I get "Success". So the same it enables or does not already have to enable due already been enabled.
I tried a symlink instead of openrc service enable, as i the end the result is supposed to be the same.
Same behavior, upon making the symlink, "Success". But when rerunning, "Success" (not "No Changes").
I'm use to ansible for these two things. (service enabling and symlinks).
I can collect facts and check them, and only make symlink if it is needed. However, if I have to do this, how is it any better than just running low level "automation" scripts. This is on an initial run (no symlink exists)
If I run it again with no check, then each symlink operation gets still gets "Success" (and I don't know if it had to create the symlink, or if it already existed)
This is on a rerun (symlink already exists) if I check before making the symlink:
To Reproduce
Here is the python deployment script with the fact checking logic in it.
Expected behavior
I should not have to put in a check for an operation. If I enable a service and rerun, it should be "no changes" if no steps are needed to get result. If I create a symlink and rerun, it should be "no changes" if no steps are needed to get result.
Is this valid expected behavior? Am I doing something wrong so I'm not getting "no changes" where applicable?
Meta
Include output of
pyinfra --support
. --> Support information:If you are having issues with pyinfra or wish to make feature requests, please check out the GitHub issues at https://github.com/Fizzadar/pyinfra/issues . When adding an issue, be sure to include the following:
System: Linux Platform: Linux-5.15.11-arch2-1-x86_64-with-glibc2.33 Release: 5.15.11-arch2-1 Machine: x86_64 pyinfra: v1.5 Executable: ./pyvenv/bin/pyinfra Python: 3.10.1 (CPython, GCC 11.1.0)
How was pyinfra installed (source/pip)? Pip in a virtual env
Comments
I like what I see so far of pyinfra, but... It needs a lot of work to replace my use of ansible with it. I like it no python is needed on the target hosts. I like it that the "playbooks" are python source rather than a DSL in yaml.. However, unless I'm doing something wrong in regard to "no changes" vs "success" it is going to be a lot of work to bring pyinfra up to par. (correcting behavior for openrc service enablement and file symlink creation?)