summaryrefslogtreecommitdiff
path: root/doc/todo/info_propigation_out_of_nested_properties.mdwn
blob: b83a862cedaea5121dbc724910fafc861f97a38a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Currently, Info about a Host's Properties is manually gathered and
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!); etc.

This works, but it's error-prone. Consider this example:

	withOS desc $ \o -> case o of
                (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..

One approach might be to make the Propellor monad be able to be run in two
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 consider this example:

	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..