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