Managing APT sources.lists with Cfengine 3

In one of my previous blog posts I wrote about a very simple package management solution with Cfengine 3.

Of course installing new packages is only one tiny part of really “managing” packages. But even this little step could fail if the according sources.list file is not correct. So todays’s part of the Cfengine 3 blog post series is about ensuring that the sources.list contains the correct APT mirrors.

Writing the script

body common control {
        version         => "1.0";
        inputs          => { "cfengine_stdlib.cf" };
        bundlesequence  => { "manage_sources_list" };
}

bundle agent manage_sources_list {
  vars:
        "apt_mirrors" slist     => {    "deb http://packages.linuxmint.com/ lisa main upstream import",
                                        "deb-src http://packages.linuxmint.com/ lisa main upstream import",
                                        "deb http://archive.ubuntu.com/ubuntu/ oneiric main restricted universe multiverse",
                                        "deb http://archive.ubuntu.com/ubuntu/ oneiric-updates main restricted universe multiverse",
                                        "deb http://security.ubuntu.com/ubuntu/ oneiric-security main restricted universe multiverse",
                                        "deb http://archive.canonical.com/ubuntu/ oneiric partner",
                                        "deb http://packages.medibuntu.org/ oneiric free non-free"
                                   };

  files:
        "/etc/apt/sources.list"
        comment         => "Define APT mirrors",
        create          => "true",
        perms           => mo("644", "root"),
        edit_line       => insert_lines("$(apt_mirrors)");
}

Save the file as “example5.cf” and make sure that it is located in the right directory (e.g. /var/lib/cfengine3/inputs or /etc/cfengine3).
Let’s see if the syntax is correct:

cf-promises -f /var/lib/cfengine/inputs/example5.cf

No errors found? Ok, then let’s continue with the next step:

cf-agent -f /var/lib/cfengine3/inputs/example5.cf

Now look at your new /etc/apt/sources.list file – it contains the given entries.

Analyzing the code snippet
How does it work? Well, the first part “body common control” should be clear to you since you are a regular reader of my blog or already have some Cfengine 3 knowledge.
So let’s jump to the next part:

bundle agent manage_sources_list {
  vars:
        "apt_mirrors" slist     => {    "deb http://packages.linuxmint.com/ lisa main upstream import",
                                        "deb-src http://packages.linuxmint.com/ lisa main upstream import",
                                        "deb http://archive.ubuntu.com/ubuntu/ oneiric main restricted universe multiverse",
                                        "deb http://archive.ubuntu.com/ubuntu/ oneiric-updates main restricted universe multiverse",
                                        "deb http://security.ubuntu.com/ubuntu/ oneiric-security main restricted universe multiverse",
                                        "deb http://archive.canonical.com/ubuntu/ oneiric partner",
                                        "deb http://packages.medibuntu.org/ oneiric free non-free"
                                   };

Here we define a promise of the type “vars”. As you can see, it contains a variable called “apt_mirrors” and simply defines a list of values which will be used later on.

Let’s move to the next promise…

bundle agent manage_sources_list {
  vars:
        "apt_mirrors" slist     => {    "deb http://packages.linuxmint.com/ lisa main upstream import",
                                        "deb-src http://packages.linuxmint.com/ lisa main upstream import",
                                        "deb http://archive.ubuntu.com/ubuntu/ oneiric main restricted universe multiverse",
                                        "deb http://archive.ubuntu.com/ubuntu/ oneiric-updates main restricted universe multiverse",
                                        "deb http://security.ubuntu.com/ubuntu/ oneiric-security main restricted universe multiverse",
                                        "deb http://archive.canonical.com/ubuntu/ oneiric partner",
                                        "deb http://packages.medibuntu.org/ oneiric free non-free"
                                   };

… of the type “files”. We first define the file to be edited and then ensure that it is created if it does not exist. The “perms” attribute takes care of the correct file permissions and the method “edit_line” insert the values of the variable “apt_mirrors” which we defined in the code snippet above.

“insert_lines” is defined in the file cfengine_stdlib.cf and does all the work for us. Let’s have a quick look:

###################################################
# edit_line bundles
###################################################

bundle edit_line insert_lines(lines)
{
insert_lines:

  "$(lines)"
    comment => "Append lines if they don't exist";
}

Summery
Today we have learned how to take care about the source.list file. Together with our knowledge of about how to install new packages, we just moved one tiny step forwards towards real package management.

As usual I uploaded the code snippet of this blog post, you can download it here.
Please do not hesitate to drop me a mail or blog comment if you have some feedback for me!

One thought on “Managing APT sources.lists with Cfengine 3

Comments are closed.