Forum: Cfengine Help
Subject: Re: I'm exploiting usemodule. There has got to be a better way to 
define global classes?
Author: msvob...@linkedin.com
Link to topic: https://cfengine.com/forum/read.php?3,18623,18688#msg-18688

I spent 3 days trying to get this to work.  This policy will execute within 
Cfengine, but something is maintaining state within the loop...  If you can get 
this to work, then you are a true Cfengine Ninja and I owe you a beer.

It seems on the first pass through the policy, policy1:CoreGuppyMachines is 
defined correctly.  On the 2nd pass, when it is looking at policy2, it doesn't 
descend into bundle agent define_guppied_class.

We also define the wrong global classes for policy3.  


The only other way I could think of getting this policy to work correctly is in 
promises.cf to execute

process_single_bundle(policy1)
process_single_bundle(policy2)
...
......

And instead of looping through a text file, I would explicitly require it to be 
called in promises.cf.   I'd rather not do that if its possible to only call it 
once and define all the global classes I need.  I just couldn't get it to work.




This policy is the first in my bundlesequence.  The global is to parse a file, 
central_guppy_config.txt, to determine if it should be executing as designed by 
defining global class (policy)_weapons_free, or if it should be restricted by 
defining global class (policy_guppy

$ cat central_guppy_config.txt 
# This file is split by policyname:filename.  The filename is assumed to live 
under /var/cfengine/inputs and contains a list of machines
# which we want to define for the guppy class of that specific policy.
# To define "WeaponsFree" means to apply the policy to all hosts.

policy1:CoreGuppyMachines
policy2:CoreGuppyMachines
policy3:WeaponsFree
policy4:WeaponsFree




$ cat bundle_guppy_test.cf 
bundle agent bundle_guppy_test
{
vars:
        # array_length -- the total amount of policies we found in 
central_guppy_config.txt
        #               we really dont use array length, but the 
readstringarray function which populates 
        #               policy_guppies (which we need) returns an int, so this 
variable is more or less a throw away.
        # policy_guppies -- an array of strings that contain :
        # specific_policy -- the index of policy_guppies.  This contains the 
actual policy names so something like
        #               cfengine_automated_execution gets defined here, which 
is a reference to a line in 
        #               central_guppy_config.txt.. like saying policy_guppies 
to refer to a line.
        # $(policy_guppies[$(policies_defined)][1] -- the 2nd value of the 
line.  These are separated by colons.  This is the 
        #               text file which contain the list of hostnames that we 
want to define as guppies for this policy.

        # We pass all this crap to another bundle below.  This is how cfengine 
handles loops.  Refering to this as a single
        # variable using $ instead of an array of @ loops through every policy 
in the file central_guppy_config.txt...

        "array_length"                          int     =>
                
readstringarray("policy_guppies","/var/cfengine/inputs/central_guppy_config.txt","#[^\n]*",":",99999999,99999999);

        "specific_policy"                       slist   =>      
getindices("policy_guppies");

methods:
        # This descends to the bundle below passing the policy name and the 
filename of the policy which contains
        # all the hosts the policy should be applied on.  If the filename is 
the phrase "WeaponsFree" then we 
        # define a global class for normal operation and stop processing.  If 
we find a filename, we decend further.
        "any" usebundle         =>
                
process_single_bundle("$(specific_policy)","$(policy_guppies[$(specific_policy)][1])");
}
##############################################
bundle agent process_single_bundle(policy_name, 
hostlist_guppy_file_for_this_policy)
{
classes:
        "weapons_free"          expression      =>      
strcmp("WeaponsFree","$(hostlist_guppy_file_for_this_policy)");

methods:
        # If we've defined weapons free for this policy, then define the global 
class and exit.
        # Example class that would be defined: 
cfengine_automated_execution_weapons_free.
        # In the policy cfengine_automated_execution, then write that specific  
policy using the class to determine if we are 
        # restricted.  The policies themselves have to be written to take 
advantage of this.  We also abort execution
        # of the policy if we dont find _weapons_free or _guppy defined.

        !weapons_free::
                "any"                           usebundle       =>      
define_guppied_class;

        weapons_free::
                "any"                           usebundle       =>      
add_global_class("$(policy_name)_weapons_free");

reports:
        !weapons_free::
                "The policy $(policy_name) has been guppied.";
        weapons_free::
                "The policy $(policy_name) is weapons free.";
}
#######################################################################################################
bundle agent define_guppied_class
{
vars:
        # Pull the policy name we are operating on for local scope.
        "policy_name_to_make_guppied_global"            string          =>      
"$(process_single_bundle.policy_name)";
        
        # Pull in the file for the policy. We know this isn't weapons free.
        "restricted_policy_hostlist_file"               string          =>      
"$(process_single_bundle.hostlist_guppy_file_for_this_policy)";


        # Populate slist arrays with the contents of the 3 files.
        "core_guppy_machines"   slist   =>
                       { 
readstringlist("/var/cfengine/inputs/CoreGuppyMachines","#[^\n]*","[\n]",99999999,99999999)
 };

        "db_guppy_machines"     slist   =>      
                      { 
readstringlist("/var/cfengine/inputs/DBGuppyMachines","#[^\n]*","[\n]",99999999,99999999)
 };

        "app_guppy_machines"    slist   =>      
                      { 
readstringlist("/var/cfengine/inputs/AppGuppyMachines","#[^\n]*","[\n]",99999999,99999999)
 };

classes:
        # Interate over the list and look for my hostname.  If I find my 
hostname in the list, then I belong in
        # the guppy class for this policy.
        "core_guppy"                    expression      =>
                
strcmp("$(restricted_policy_hostlist_file)","CoreGuppyMachines");
        "db_guppy"                      expression      =>
                strcmp("$(restricted_policy_hostlist_file)","DBGuppyMachines");
        "app_guppy"                     expression      =>
                strcmp("$(restricted_policy_hostlist_file)","AppGuppyMachines");

        "core_guppy_me"                 expression      =>      
reglist("@(core_guppy_machines)","$(sys.host)");
        "db_guppy_me"                   expression      =>      
reglist("@(db_guppy_machines)","$(sys.host)");
        "app_guppy_me"                  expression      =>      
reglist("@(app_guppy_machines)","$(sys.host)");
methods:
        # Since we determined that I am a guppy for this policy, we define a 
global class with the 
        # _guppy which we then key off of during execution of the policy itself.

        any::
                "any" usebundle         =>      
remove_global_class("weapons_free");
        core_guppy.core_guppy_me::
                "any" usebundle         =>      
add_global_class("$(policy_name_to_make_guppied_global)_guppy");
        db_guppy.db_guppy_me::
                "any" usebundle         =>      
add_global_class("$(policy_name_to_make_guppied_global)_guppy");
        app_guppy.app_guppy_me::
                "any" usebundle         =>      
add_global_class("$(policy_name_to_make_guppied_global)_guppy");

reports:
        # Report back that I've been included as a guppy in this policy.
        
((core_guppy.core_guppy_me)|(db_guppy.db_guppy_me)|(app_guppy.app_guppy_me))::
                "This host $(sys.host) has been included as a guppy in 
$(policy_name_to_make_guppied_global) in 
$(global.inputs)/$(process_single_bundle.hostlist_guppy_file_for_this_policy)";
}



Execution of the policy shows the following below.  Policy1 and policy2 should 
have contained the host in CoreGuppyMachines.  Policy3 and policy4 should have 
been weapons free.

$ /var/cfengine/bin/cf-agent -I -K
R: The policy policy4 is weapons free.
R: This host testmachine has been included as a guppy in policy2 in 
/var/cfengine/inputs/CoreGuppyMachines
R: The policy policy2 has been guppied.
R: The policy policy3 has been guppied.
R: The policy policy1 has been guppied.

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

Reply via email to