> How do I know if vars or classes come first during cfengine evaluation?

Read the documentation on Normal Order

There is a wealth of information on docs.cfengine.com. Find documentation about the order of agent promise evaluation (Normal Order) in the Language Concepts section of the Reference manual.

Run the agent with –verbose or -v and grep for pass 1.

Write a test policy that has both vars and classes promises.

1
2
3
4
5
6
7
8
  bundle agent main
  {
   vars:
      "question" string => "What comes first, vars or classes?";
  
   classes:
      "grep_verbose_output_for_pass_1" expression => "any";
  }
/tmp/test.cf

Grep the verbose output.

1
2
  chmod 600 /tmp/test.cf 
  cf-agent -Kvf /tmp/test.cf | grep "pass 1"
 verbose: V: BEGIN variables (pass 1)
 verbose: C: BEGIN classes / conditions (pass 1)
Grepping for promises that run on the frist pass

Write policy that tells you

This policy uses conditionals to determine if classes are evaluated before variables, or if variables are evaluated first. It shows the determination using reports guarded on the class that describes which is evaluated first.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
  bundle agent main
  #@ brief Demonstrate if vars or classes come first
  {
    classes:
        "classes_are_first" expression => not( isvariable( "main.classes_are_first" ) );
        "vars_are_first" expression => isvariable( "main.vars_are_first" );

    vars:
        "classes_are_first" string => "Classes come first";
        "vars_are_first" string => "Vars come first", if => not( "vars_are_first" );

    reports:
      "CFEngine $(sys.cf_version)";

      "$(classes_are_first)"
        if => "classes_are_first";

      "$(vars_are_first)"
        if => "vars_are_first";

  }
Policy to demonstrate evaluation order in cfengine 3
R: CFEngine 3.11.0
R: Vars come first
R: Without intermediary vars: ifelse: Vars come first
Output of policy to demonstrate evaluation order in cfengine 3

You can use the with attribute and ifelse() to reduce the policy a bit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    bundle agent main
    #@ brief Demonstrate if vars or classes come first
    {
      classes:
          "classes_are_first" expression => not( isvariable( "main.variable" ) );
          "vars_are_first" expression => isvariable( "main.vars_are_first" );

      vars:
          "classes_are_first" string => "Classes come first";
          "vars_are_first" string => "Vars come first", if => not( "vars_are_first" );

      reports:
        "CFEngine $(sys.cf_version)";
      
        "Without intermediary vars: $(with)"
          with => ifelse( classes_are_first, "ifelse: Classes come first",
                          vars_are_first, "ifelse: Vars come first",
                          "Logic Error" );

    }
Policy to demonstrate evaluation order in cfengine 3
R: CFEngine 3.11.0
R: Without intermediary vars: ifelse: Classes come first
Output of policy using with and ifelse() to demonstrate evaluation order in cfengine 3