When promises are actuated, a class can be defined based on its result. For example, if a promise modifies a file’s content, you could define a class that indicates it has been repaired. However, did you know that promises can have multiple outcomes concurrently?
That’s right! Native promises (but not custom promises) can have multiple outcomes. For example, a promise can be both kept and repaired at the same time. Let’s take a look.
First, let’s create a policy /tmp/feature-friday-27.cf
to ensure that a file exists with some specific content and use body classes results
from the standard library.
body file control
{
inputs => { "$(sys.libdir)/stdlib.cf" };
}
bundle agent __main__
{
files:
"/tmp/feature-friday-27.txt"
create => "true",
touch => "true",
classes => results( "bundle", "feature_friday_27" );
reports:
"Feature Friday Classes: $(with)"
with => join( ", ", classesmatching( "feature_friday_27.*" ) );
}
Notice how I’ve used body file control
to include the standard library since I am not running this example as part of a larger policy set.1, 2
Next, we have our files promise that explicitly specifies the file should exist with create => "true"
. Furthermore, it specifies that we want to update the “last modified” timestamp for the file using touch => "true"
, and that bundle scoped classes prefixed with feature_friday_27
should be defined.3
Finally, we emit a report listing the classes starting with feature_friday_27
.
Running this policy the first time:
rm -f /tmp/feature-friday-27.txt
cf-agent -KIf /tmp/feature-friday-27.cf
info: Created file '/tmp/feature-friday-27.txt', mode 0600
info: Touched (updated time stamps) for path '/tmp/feature-friday-27.txt'
R: Feature Friday Classes: feature_friday_27_repaired, feature_friday_27_reached
We can see that two classes were defined, feature_friday_27_repaired
and feature_friday_27_reached
.
Running the policy again:
cf-agent -KIf /tmp/feature-friday-27.cf
info: Touched (updated time stamps) for path '/tmp/feature-friday-27.txt'
R: Feature Friday Classes: feature_friday_27_repaired, feature_friday_27_kept, feature_friday_27_reached
We see that this time, three classes were defined, feature_friday_27_repaired
(because the file was touched), feature_friday_27_kept
(because the file already existed), and feature_friday_27_reached
(which is always defined by the results
classes body, no matter the promise-outcome.
It’s even possible to have a promise that is kept, repaired, and not-kept concurrently. For example, we added ownership management:
body file control
{
inputs => { "$(sys.libdir)/stdlib.cf" };
}
bundle agent __main__
{
files:
"/tmp/feature-friday-27.txt"
create => "true",
touch => "true",
perms => owner( "root" ),
classes => results( "bundle", "feature_friday_27" );
reports:
"Feature Friday classes: $(with)"
with => join( ", ", classesmatching( "feature_friday_27.*" ) );
}
But, running unprivileged, cf-agent
fails to change the ownership. As a result, we end up with classes for kept, repaired, and not kept:
cf-agent -KIf /tmp/feature-friday-27.cf
info: Touched (updated time stamps) for path '/tmp/feature-friday-27.txt'
error: Cannot set ownership on file '/tmp/feature-friday-27.txt'. (chown: Operation not permitted)
info: Updated timestamps on '/tmp/feature-friday-27.txt'
info: Touched (updated time stamps) for path '/tmp/feature-friday-27.txt'
error: Cannot set ownership on file '/tmp/feature-friday-27.txt'. (chown: Operation not permitted)
info: Updated timestamps on '/tmp/feature-friday-27.txt'
error: Errors encountered when actuating files promise '/tmp/feature-friday-27.txt'
R: Feature Friday classes: feature_friday_27_denied, feature_friday_27_not_kept, feature_friday_27_error, feature_friday_27_repaired, feature_friday_27_kept, feature_friday_27_reached
In practice, this detail is often not that important. But it is good to understand in cases where you want to construct a class expression that takes these eventualities into consideration.
Happy Friday! 🎉
-
In case you missed it, check out Feature Friday #09: body file control - inputs. ↩︎
-
In case you missed it, check out Feature Friday #25: Unprivileged execution. ↩︎
-
Find the implementation and documentation of the results classes body here. ↩︎