A recent change in the Masterfiles Policy Framework (MPF) is renaming bundle agent main
to bundle agent mpf_main
.
This change is intended to make it easier to run individual parts of your policy leveraging the library main bundle functionality (bundle agent __main__
).
Library main bundles were first introduced in CFEngine 3.12.0. The functionality allows for the definition of bundle agent __main__
. When this bundle definition is present in the policy entry (the first policy file that CFEngine reads) the bundle is understood to be used as the default bundlesequence.
This example illustrates the behavior:
bundle agent __main__
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
When we run the policy without providing a bundlesequence (the --bundlesequence
or -b
option to cf-agent
), and since body common control
is absent, not defining bundlesequence
, the __main__
bundle is used in the place of main
.
cf-agent --no-lock --file /tmp/example-0.cf
R: Hello World, from /tmp/example-0.cf
We can see that if we instead define the bundle as main
:
bundle agent main
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
The behavior is identical when the policy is executed:
cf-agent --no-lock --file /tmp/example-1.cf
R: Hello World, from /tmp/example-1.cf
So, why are we renaming bundle agent main
in services/main.cf
to bundle agent mpf_main
?
We are renaming it because you will get errors if you execute a policy entry that has bundle agent __main__
and there also exists bundle agent main
within the inputs of that policy execution.
For example, if we place both bundle agent main
and bundle agent __main__
in the same file:
bundle agent main
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
bundle agent __main__
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
When executing, we get an error about duplicate definition of bundle.
cf-agent --no-lock --file /tmp/example-2.cf | head -n 2
/tmp/example-2.cf:1:0: error: Duplicate definition of bundle main with type agent
/tmp/example-2.cf:6:0: error: Duplicate definition of bundle main with type agent
error: There are syntax errors in policy files
error: Policy failed validation with command '"/home/nickanderson/.cfagent/bin/cf-promises" -c "/tmp/example-2.cf"'
This error is emitted because bundle agent __main__
is internally translated to bundle agent main
and since there already exists a bundle agent main
it’s seen as a duplicate.
The same thing happens if there is bundle agent __main__
in the policy entry and bundle agent main
in another file added to inputs. In this example, /tmp/example-3.cf
(which has bundle agent __main__
) loads /tmp/example-4.cf
(which has bundle agent main
) as part of it’s inputs.
body file control
{
inputs => { "example-4.cf" };
}
bundle agent __main__
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
bundle agent main
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
Again, we see that running /tmp/example-3.cf
as the policy entry results in duplicate definition of bundle errors:
cf-agent --no-lock --file /tmp/example-3.cf | head -n 2
/tmp/example-3.cf:5:0: error: Duplicate definition of bundle main with type agent
/tmp/example-4.cf:1:0: error: Duplicate definition of bundle main with type agent
error: Policy failed validation with command '"/home/nickanderson/.cfagent/bin/cf-promises" -c "/tmp/example-3.cf"'
error: CFEngine was not able to get confirmation of promises from cf-promises, so going to failsafe
Note, it’s not a problem in the other direction.
If you have bundle agent main
in your policy entry that loads another file to inputs which has bundle agent __main__
, there is no error since bundle agent __main__
in the non policy entry file is not internally translated to bundle agent main
.
In this example we reverse the previous example so that the policy entry file contains bundle agent main
and bundle agent __main__
is present in a file loaded to inputs.
body file control
{
inputs => { "example-5.cf" };
}
bundle agent main
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
bundle agent __main__
{
reports:
"Hello World, from $(sys.policy_entry_filename)";
}
When executing we can see that no errors are emitted.
cf-agent --no-lock --file /tmp/example-5.cf
R: Hello World, from /tmp/example-5.cf
So, we are renaming bundle agent main
to bundle agent mpf_main
so that you can run some arbitrary policy file which itself somehow includes services/main.cf
.
What do I need to do?
Upgrade your policy framework as usual just be sure that you don’t ignore the upstream change to services/main.cf
. If you have variables (e.g. main.myvar
, default:main.my_var
) or methods promises ( usebundle => main
, usebundle => default:main
you should update them to mpf_main
.
This change comes with policy from the upcoming 3.20.0 release, it’s backwards compatible, so it’s perfectly safe to run new policy with this change on binaries prior to 3.20.0.