This commit is contained in:
Joey Hess 2014-12-07 18:49:42 -04:00
parent f692e1ceb2
commit 19a1d6b7ed
1 changed files with 50 additions and 21 deletions

View File

@ -1,7 +1,7 @@
Currently, Info about a Host's Properties is manually gathered and
propigated. propertyList combines the Info of the Properties in the list.
propigated. propertyList combines the Info of the Properties in the list;
Docker.docked extracts relevant Info from the Properties of the container
(but not al of it, intentionally!).
(but not al of it, intentionally!); etc.
This works, but it's error-prone. Consider this example:
@ -9,26 +9,55 @@ This works, but it's error-prone. Consider this example:
(Just (System (Debian Unstable) _)) -> ensureProperty foo
_ -> ensureProperty bar
Here, the Info of `foo` is not propigated out. Nor is `bar`'s Info.
Of course, only one of them will be run, and only its info should be propigated
out..
This commonly afflicts eg, privData. For example, `User.hasPassword'`
used to have this problem, which prevented --list-fields from listing privdata
that's not set from that property. (That was worked around.)
Here, the Info of `foo` is not propigated out. Nor is `bar`'s Info. Of
course, only one of them will be run, and only its info should be
propigated out..
One approach might be to make the Propellor monad be able to be run in two
modes. In one mode, it actually perform IO, etc. In the other mode, all
liftIO is a no-op, but all Info encountered is accumulated using a Reader
monad. This might need two separate monad definitions.
modes. In run mode, it actually performs IO, etc. In introspection mode, all
liftIO is a no-op, but all Info encountered is accumulated using a Reader.
This might need two separate monad definitions.
That is surely doable, but the withOS example above shows a problem with it --
the OS is itself part of a Host's info, so won't be known until all its
properties have been examined for info!
That is surely doable, but consider this example:
Perhaps that can be finessed. We don't really need to propigate out OS info.
Just DNS and PrivDataField Info. So info could be collected in 2 passes,
first as it's done now by static propertyInfo values. Then take that
and use it as the Info when running the Properties in the Reader monad.
Combine what the Reader accumulates with the static info to get the full
info.
property "demo" = do
needfoo <- liftIO checkFoo
if needfoo
then ensureProperty foo
else ensureProperty bar
In introspection mode, the liftIO is a no-op, but needs to return a Bool.
That seems unlikely (how to pick which?), but even if some defaulting is
used, only one of foo or bar's info will be seen.
Another approach could be something like this:
withInfoFrom foo $ \callfoo ->
withInfoFrom bar $ \callbar ->
property "demo" = do
needfoo <- liftIO checkFoo
if needfoo
then callfoo
else callbar
Here withInfoFrom is able to add foo and bar's Info to the info of the
property that (may) call them.
This approach is not fully type safe; it would be possible to call
withInfoFrom in a way that didn't let it propigate the info.
Also it has the problem that it doesn't support this:
property "demo" = do
needfoo <- liftIO checkFoo
if needfoo
then do
foop <- liftIO getFooParam
ensureProperty (foo foop)
else ensureProperty bar
----
Currently, ensureProperty detects if it's called on a property with a
non-empty Info, and prints a warning. Would prefer to handle this at the
type level though..