Forum: CFEngine Help
Subject: Re: downsizing a huge policy file, sensibly
Author: davidlee
Link to topic: https://cfengine.com/forum/read.php?3,24050,24053#msg-24053

Locally we have several cases where we want to apply different data in 
different environments but in standard ways.  These include setting up one or 
more network interfaces, some of which may be bonded; ensuring that certain 
users are in the passwd file on some (nota all) machines (and some of the 
resulting entries may be stripped-down "+userx:..." for NIS compatibility), etc.

The overall scheme I have used is to separate out the very detailed "vars:" 
data (which is also likely to have high-frequency maintenance) from the more 
general-purpose other things, and to put those other things into a method 
(which, once established, is likely to have low-frequency maintenance).

So whereas you suggest "I was considering to write a module that, depending on 
hostname and location, would return a server list, a peer list, and a key 
list", what I do is "write an appropriate set of '*.cf' caller files that set 
up appropriate 'vars:' data and then do 'usemethod' to a bundle which does all 
the 'files:', 'commands:', etc.".

In both our cases, the complexity lies in constructing our data within each 
environment, that is, in getting a good 'vars:' structure.  Having done that, 
applying the data ('files:', 'commands:', etc.) can be as general purpose as 
reasonably possible.

One technique I find very useful is to put my data into associative arrays in 
the caller and then pass the name of that array as an argument into the method.

Overall something like:

----------

bundle agent caller_1
{
  vars:
    envir_a::
      "user1" string => "username_1";
      "user1" int => "111";
      "user1" int => "1111";

      "user2" string => "username_2";
      "user2" int => "222";
      "user2" int => "2222";

      "userlist" slist => { "user1", "user2" };

   envir_b::
      ### set up different users, say, user3, user4, user5
      ### ending with:
        "userlist" slist => { "user3", "user4", "user5" };      

    any::
      # possible algorithmic data, always applicable to the lists defined above:
      "$(userlist)" string => "/users/$(userlist)";

  methods:
    # Now call a general-purpose bundle with our data.
    # Note that we pass the fully-qualified name of our assoc. array.
    possibly_general::
      "any"
        usebundle => action_user_promise("caller_1.$(userlist)");

}


### This is probably in a different pseudo-library ".cf" file.
# "arr" is an associative array 
bundle agent action_user_promise(arr)
{
  files:
    ### do some file business using vars from 'arr'.
  commands:
    ### do some command business using vars from 'arr'.
}

----------

You can be more subtle.  For instance, given the above example, where the 
usernames are distinct, you could actually define their particular data under 
an "any::" selector, and only apply the "envir_*::" selectors when building the 
"userlist". This would allow you to build hybrid systems:

----------

 vars:
   any::
      "user1" string => "username_1";
      "user1" int => "111";
      "user1" int => "1111";

      ### similarly always set up user2, user3, user4, user5

    ### Then construct per-environment lists of users:
    envir_a::
      "userlist" slist => { "user1", "user2" }; 
    envir_b::
      "userlist" slist => { "user3", "user4", "user5" };   
    envir_hybrid_145::
       "userlist" slist => { "user1", "user4", "user5" }; 
    envir_hybrid_23::
      "userlist" slist => { "user2", "user3" };


----------

You can now imagine expanding that to more than one "caller_1" bundle. Each 
constructs an associative array of data and calls the common method.  So 
"caller_N"  does:

----------

bundle agent caller_N
{
  vars:
      # construct data ending with:
      "userlist" slist => {...};

  methods:
    # Note that we pass the fully-qualified name of our assoc. array.
    possibly_general::
      "any"
        usebundle => action_user_promise("caller_N.$(userlist)");
}

----------

Hope that helps.

_______________________________________________
Help-cfengine mailing list
Help-cfengine@cfengine.org
https://cfengine.org/mailman/listinfo/help-cfengine

Reply via email to