Cfengine3 - configuration management system

    On Habré several times they wrote about puppet and chef configuration management systems, but for some reason, the pioneer of this topic - cfengine, is deprived of attention, let's understand this gap.

    The first thing to note about cfengine is a declarative framework, not an imperative. We do not describe the detailed sequential steps to achieve the configuration we need, we describe the desired state of the system. For example, “make sure that all web servers with the name web. * Had the nginx package” or “make sure that the bckup.sh script was launched at the 5th hour of the day and * completed * successfully.” Cfengine uses the concept of “promise” (promice), in addition, cfengine will try to “repair” it periodically, and even after a successful recovery, it will check the state and restore again and again in order to achieve convergence configuration. The advantage of this approach is that there is no need to know the current state in order to come to the desired.

    Hopefully enough background information, let's look at examples.
    Installation is simple and does not require much time. For Debian:
    cd /tmp
    wget http://cfengine.com/pub/gpg.key
    apt-key add gpg.key
    rm gpg.key
    echo "deb http://cfengine.com/pub/apt squeeze main" >  \
    /etc/apt/sources.list.d/cfengine-community.list
    apt-get update
    apt-get install cfengine-community
    

    Now create a file containing one simple cfengine bundle and a very
    basic body that imports the standard library.
    cat /var/cfengine/inputs/python_virtualenv.cf:
    body common control 
         {
         bundlesequence => { "python_virtualenv" };
                 inputs => { 
                           "cfengine_stdlib.cf", 
                           };
         }
    bundle agent python_virtualenv {
     vars:
      "package_list" slist => { "virtualenvwrapper", "python-pip" };
      "environments" slist => { "s1.example.com", "s2.example.com" };
     packages:
      "${package_list}"
      package_policy => "add",
      package_method => generic;
     classes:
       "incorrect_$(environments)" not => fileexists("/tmp/$(environments)/bin/python") ;
      reports:
       linux::
       "Virtual environment $(environments) is not installed correctly."
       ifvarclass => canonify("incorrect_$(environments)");
      commands:
        linux::
        "/usr/bin/virtualenv /tmp/$(environments) --no-site-packages"
        ifvarclass => canonify("incorrect_$(environments)");
    }
    

    We declare a bundle of type agent and with the name python_virtualenv, as you might guess, I want to make sure that I have two independent python virtualenv installed, for example, they will be created in /tmp/s1.example.com and /tmp/s2.example.com, previously “promise” variables in slist. Obviously, we need python, which we declare in a promise like packages. Note that cfengine automatically iterates over list, no need to write cycles - we just declare our intention. Next, we declare the class depending on whether there is a specific file or not. I must say that classes are not quite a good name, it would be better to call contexts, and in general they are practically boolean - a class in cfengine or not or not! Next comes the promise of type report, in it we see the so-called hard class linux,/ var / cfengine / bin / cf-agent -v . Promises in reports and commands will only work if the “incorrect _ $ (environments)” class is installed (the canonify option is called because the class may contain illegal characters and the check may fail). We try to run:
    / var / cfengine / bin / cf-agent -K -f /var/cfengine/inputs/python_virtualenv.cf
    We get :
    Q: "...virtualenv /tmp": New python executable in /tmp/s1.example.com/bin/python
    Q: "...virtualenv /tmp": Installing distribute.................................................................................................................................................................................done.
    I: Last 2 quoted lines were generated by promiser "/usr/bin/virtualenv /tmp/s1.example.com --no-site-packages"
    Q: "...virtualenv /tmp": New python executable in /tmp/s2.example.com/bin/python
    Q: "...virtualenv /tmp": Installing distribute.................................................................................................................................................................................done.
    I: Last 2 quoted lines were generated by promiser "/usr/bin/virtualenv /tmp/s2.example.com --no-site-packages"
    R: Virtual environment s1.example.com is not installed correctly.
    R: Virtual environment s2.example.com is not installed correctly
    

    We look in / tmp and make sure that our virtualenv are created.
    Delete rm -rf /tmp/s2.example.com!
    And run / var / cfengine / bin / cf-agent -K -f /var/cfengine/inputs/python_virtualenv.cf
    We see:
    Q: "...virtualenv /tmp": New python executable in /tmp/s2.example.com/bin/python
    Q: "...virtualenv /tmp": Installing distribute.................................................................................................................................................................................done.
    I: Last 2 quoted lines were generated by promiser "/usr/bin/virtualenv /tmp/s2.example.com --no-site-packages"
    R: Virtual environment s2.example.com is not installed correctly.
    

    Cfengine recreated only the remote virtualenv, which is actually what was expected.
    Obviously, cfengine can work both standalone and with a policy hub. Are you intrigued? You can start from here http://cfengine.com/manuals/cf3-quickstart

    Also popular now: