Question

I have to create one CFENGINE 3 Policy which should take input from defined input list and then want to perform some bunch of commands on that set one by one.

For Eg:

For only one Package here I have the example:

bundle agent test_tester_install

{

commands:

    "/usr/bin/wget  http://something.example.com/perl-modules/Test-Tester-0.104.tar.gz;
    /usr/bin/gunzip Test-Tester-0.104.tar.gz;
    tar -xf Test-Tester-0.104.tar;
    cd Test-Tester-0.104;
    /usr/bin/perl Makefile.PL;
    /usr/bin/make;
    /usr/bin/make install"


    contain =>  standard,
            classes => satisfied("Test-Tester Installed");
     }
body contain standard

{

    useshell => "true";
    exec_owner => "root";
}

body classes satisfied(new_class)


{

    promise_repaired => { "$(new_class)" };
}

But I am not sure that how to do it if I want to do the same for 100 packages. I think "slist would do this but how exactly i need to draft that policy i am not sure"

This is very similar to applying "for" loop in bash shell where we iterate input one by one and perform some operations

Experts Please help

Was it helpful?

Solution

The way to do something like this is to use CFEngine's implicit looping. You store the values in a list, and then iterate over them in the promises. For your example, it would be something like this:

bundle agent install

{
vars:
    "packages" slist => { "Test-Tester-0.104", "Foo-Bar-1.001" }; # etc.
commands:
    "/usr/bin/wget  http://something.example.com/perl-modules/$(packages).tar.gz;
    /usr/bin/gunzip $(packages).tar.gz;
    tar -xf $(packages).tar;
    cd $(packages);
    /usr/bin/perl Makefile.PL;
    /usr/bin/make;
    /usr/bin/make install"
            contain =>  standard,
            classes => satisfied(canonify("$(packages)-installed"));
     }

Note that I'm using $(package) whenever you previously had Test-Tester-0.104. Of course this only works if all the names are consistent in this respect. To add more, you'd only need to add the names to the packages variable. Not also that I used canonify() to make the string that gets passed to the satisfied() body a valid class name.

Now, if you are going to be doing a lot of installs like this, what I would suggest is defining a new package_method definition, which takes care of following the right steps internally, so that in your policy you can have something much cleaner, like this:

vars:
    "packages" slist => { "Test-Tester-0.104", "Foo-Bar-1.001" }; # etc.
packages:
    "$(packages)"
       package_policy => "add",
       package_method => perlsrcpkg;  # or whatever you call your new package_method

You can find the documentation for packages promises here: http://cfengine.com/docs/3.5/reference-promise-types-packages.html#packages, and a bunch of package_method definition examples in the CFEngine Standard Library: https://github.com/cfengine/masterfiles/blob/master/lib/3.5/packages.cf

Finally, if the packages you are installing are from CPAN, you could just use the Packages::Installed::cpanm sketch from the Design Center: https://cfengine.com/cfengine-design-center/sketches/packages-cpan-cpanm

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top