I don't know why such a basic function doesn't work and is not pretty usable.
pyinfra v0.16.2
pyinfra -v @local tt.py
tt.py:
from pyinfra import host
SUDO = True
assert host.fact.linux_name is not None
Outcome:
--> Loading config...
--> Loading inventory...
--> Connecting to hosts...
[@local] Connected
--> Preparing operations...
Loading: tt.py
Loaded fact linux_distribution
--> An unexpected exception occurred:
File "tt.py", line 6, in <module>
assert host.fact.linux_name is not None
AssrtionError
Which Linux Distribution the above run host has?
It is Ubuntu 20.04. But other than linux_name, every other attributes are None as well. Like host_names, etc.
@FooBarQuaxx @Fizzadar Looks like this is a bug. This is because of the line SUDO = True; without this line it works correctly. Or when --sudo is passed. I can also reproduce in the latest master 1.0.dev1.
@wookayin yes a verbose run of pyinfra -vv --debug @local tt.py gives something similar to this:
...
[pyinfra.api.connectors.local] --> Running command on localhost: sudo -H -n sh -c 'cat /etc/*-release'
[@local] >>> sudo -H -n sh -c 'cat /etc/*-release'
[@local] sudo: a password is required
...
Edit: With a regular use, I don't thing you needed a SUDO run for all types of invocations.
I see, thanks! This is because all sudo commands fail. Could we have better error handling in gathering facts? Throwing error should be more intuitive than having facts being None.
So this is a bit more involved - v1 implements fact failure, but only where we don't expect facts to fail (ie deb_packages is expected to fail on some systems, so we return the default).
I agree when sudo password request is in the output pyinfra should make it explicitly obvious why the fact failed (and the need to pass use_sudo_password=True. Slightly related: https://github.com/Fizzadar/pyinfra/issues/359
Currently planning to properly review the facts api for v1.1.
This is now covered by https://github.com/Fizzadar/pyinfra/commit/d8e97d36243be8d78a29e419afb33abad38332b5, which will print out the sudo password required error.
FYI: one of the examples doesn't work.
examples/docker_ce,py fails quietly - the command runs but nothing is executed. It seems host.fact.linux becomes None and skips the conditional block containing the commands.
Bypassing that, another problem: an error is thrown at the second apt.packages command, requiring a password, but none was asked. I tried the following but nothing works:
> pyinfra @local /path/to/docker_ce.py
> pyinfra @local /path/to/docker_ce.py use_sudo_password=true
> pyinfra @local /path/to/docker_ce.py --use_sudo_password
A third issue: later host.fact.command("apt-key list") complains that no such fact exists.
UPDATE: the second issue regarding passwords was somewhat resolved adding use_sudo_password=True into the appropriate operation function (in code, not the terminal). See also more insight on env vars in config.py.
apt.key, isn't adding new gpgs when apt-key list is called.
Can confirm other facts are returning None, e.g. linux_id and code_name
The other issues remain.
Nice spot @pylang! I've added https://github.com/Fizzadar/pyinfra/issues/408 to track this.