Closed morrison12 closed 2 years ago
So the reason the global arguments are part of the hash is to account for fact results being different depending on them (eg sudo/not sudo). But as you point out this essentially means facts are only good within the context of an operation, they won't correctly invalidate other facts for the same thing called without those arguments.
Perhaps a good fix would be to always use the default set of global arguments in facts, which would address the example above.
Regarding point 2 the args are converted to kwargs, they're only supported for backwards compatibility:
Spotted the kwargs/args here - calling with args/kwargs does indeed generate a different hash because the normalisation I referenced above happens after the hash generation. Fixed in https://github.com/Fizzadar/pyinfra/commit/bc06372d58c5178dd13402f196a3b6b8e84d6e2e.
I have fixed the default arguments thing in https://github.com/Fizzadar/pyinfra/commit/d6c3db64383b0a8f81c3b649d72aa8bcba8999ce, and now the test script above executes as expected.
Fixes are now live in v2.5.2 :)
Describe the bug
It appears different keys into the
host.facts
cache are (sometimes ?) used depending on whether a fact is being retrieved or an operation is trying to update the fact cache withhost.create_fact
.The example below uses permissions on a directory but the behaviour seems to be more general.
From what I can tell, there are couple of items that contribute to the cache keys being different between a 'get' and a 'set':
When
host.create_fact(...)
is called from inside an operation, thekwargs
dict has an entry for each 'global argument' (e.g_su
) whereas whenhost.get_fact(...)
is called from the deploy, thekwargs
dict has only what is passed by the caller (e.g.path
in the case offiles.directory
).Host.create_fact
does not have an*args
parameter whereasHost.get_fact
does. While this might not matter as askwargs
comes afterargs
and it appears only the values are hashed, but there would seem to be a possible ordering problem once (1) is resolved.To Reproduce
The code below checks the permissions on a directory, changes them and then reads back what is expected to be the new value It was run as
rmdir foo && mkdir foo && pyinfra @local ./test.py
Code
test.py
Output
Expected behavior
I expected: a) only one entry in the fact cache at each output (vs. the two that are seen) and b) the permissions to be expected values at each step
Meta
pyinfra
was installed withgit clone ...
,cd pyinfra
andpip install -e '.[dev]'
git describe --tags
gives:v2.3-25-g5fedec46
pyinfra --support
gives: