CFEngine: new ifelse() function

A multi-level if-else like statement.

Example reproduced below:

body common control

{
bundlesequence => { "example" };
}

###########################################################

bundle agent example

{
  classes:
      "myclass" expression => "any";
      "myclass2" expression => "any";
      "secondpass" expression => "any";
  vars:
      # result: { "1", "single string parameter", "hardclass OK", "bundle class OK", "5 parameters OK" }

      # we need to use the secondpass class because on the first pass,
      # myclass and myclass2 are not defined yet

    secondpass::
      "mylist" slist => {
                          ifelse(1),
                          ifelse("single string parameter"),
                          ifelse("cfengine", "hardclass OK", "hardclass broken"),
                          ifelse("myclass.myclass2", "bundle class OK", "bundle class broken"),
                          ifelse("this is not true", "5 parameters broken",
                                 "this is also not true", "5 parameters broken 2",
                                 "5 parameters OK"),
                        };

  reports:
      "ifelse result list: $(mylist)";
}

Output

Read more...

CFEngine: new maparray() function

From an array and a string template, maparray() will generate a slist of strings expanded from the template, with the possibility for each array element, to use its key and its value(s).

Example reproduced below:

body common control
{
      bundlesequence => { run };
}

bundle agent run
{
  vars:
      "todo[1]" string => "2";
      "todo[one]" string => "two";
      "todo[3999]" slist => { "big", "small" };
      "map" slist => maparray("yes $(this.k) $(this.v)", "todo");

  reports:
    cfengine::
      "Hello $(map)";
}

Output:

R: Hello yes 1 2
R: Hello yes one two
R: Hello yes 3999 big
R: Hello yes 3999 small

Here is another example based on DNS entries:

Read more...

CFEngine: new classesmatching() function

Get an slist of defined classes matching a given unanchored regular expression.

Example reproduced below:

body common control
{
      bundlesequence => { run };
}

bundle agent run
{
  vars:
      "c" slist => classesmatching(".*");
  reports:
    cfengine::
      "Classes matching = $(c)";
}

Will output all classes matching “.*” pattern, so all of them:

Running full policy integrity checks
R: Classes matching = Sunday
R: Classes matching = compiled_on_linux_gnu
R: Classes matching = cpu_high_normal
R: Classes matching = cfengine_3_5_0b2
R: Classes matching = linux_2_6_32_358_el6_x86_64
R: Classes matching = ssh_in_high
R: Classes matching = 192_168_2_104
R: Classes matching = ipv4_192_168_2_104
R: Classes matching = redhat
(...)

In addition to handle custom classes, it may be used to spot abnormal node behavior thanks to classes defined by cf-monitord.

Read more...

CFEngine: new filestat() function

This is an implementation of the system stat() function, which makes it easy to retrieve file metadata like filesize, mode, modification time and so on.

No need to fork an additional stat process anymore :)

Example reproduced below:

body common control
{
      bundlesequence => { run };
}

bundle agent run
{
  vars:
      "f" string => "/etc/passwd";
      "fields" slist => splitstring("size,gid,uid,ino,nlink,ctime,atime,mtime,mode,modeoct,permstr,permoct,type,devno,dev_minor,dev_major", ",", 999);
      "stat[$(fields)]" string => filestat($(f), $(fields));
  reports:
    cfengine::
      "$(f) $(fields) = $(stat[$(fields)])";
}

Output:

R: /etc/passwd size = 2157
R: /etc/passwd gid = 0
R: /etc/passwd uid = 0
R: /etc/passwd ino = 8269902
R: /etc/passwd nlink = 1
R: /etc/passwd ctime = 1359415340
R: /etc/passwd atime = 1363224601
R: /etc/passwd mtime = 1359415340
R: /etc/passwd mode = 33188
R: /etc/passwd modeoct = 100644
R: /etc/passwd permstr = -rw-r--r--
R: /etc/passwd permoct = 644
R: /etc/passwd type = regular file
R: /etc/passwd devno = 2049
R: /etc/passwd dev_minor = 1
R: /etc/passwd dev_major = 8

Moreover, {c,a,m}time fields can be transformed into human-readable form thanks to the also recently merged strftime() function:

Read more...

CFEngine: new strftime() function

2013-06-11: Links to documentation updated

An implementation of strftime() has just been merged into the master branch

Full documentation is provided, as well as an example reproduced below:

body common control

{
bundlesequence => { "example" };
}

###########################################################

bundle agent example

{
  vars:
      "time" int => now();
      "now" string => strftime("localtime", "%F %T", now());
      "then" string => strftime("localtime", "%F %T", 0);

      "gmt_now" string => strftime("gmtime", "%F %T", now());
      "gmt_then" string => strftime("gmtime", "%F %T", 0);

  reports:
    cfengine::
      "time $(time); now $(now); then $(then)";
      "time $(time); GMT now $(now); GMT then $(then)";
}

Output:

Read more...

CFEngine: Stuck cf-execd processes

Upgrading to cfengine-3.4.x branch, and getting stuck cf-execd processes?

The behavior of -F flag has changed from 3.3.x to 3.4.x branch:


    Changed functionality:
    
    - cf-execd -F switch no longer implies 'run once'. New -O/--once
    option is added to achieve this behaviour. This makes cf-execd
    easier to run from systemd, launchd and other supervision
    systems.

So you need to update your crontab promises to add *-O* flag to *cf-execd -F*, to get the old (and correct for crontab) behavior:

    */5 * * * * root /var/cfengine/bin/cf-execd -FO
Read more...

Managing Yum software groups with CFEngine

With its group commands (groupinstall, groupremove, …), Yum is able to install a set of packages to quickly set up a system for a specific task.

This blog post is a great introduction to Yum software groups

In CFEngine, it is now possible (feature merged in master, but not yet released) to handle such groups through yum_group package_method.

Some examples:

  • Installing perl-runtime and basic-desktop groups:
body common control {
  bundlesequence => { "foo" };
  inputs  =>  { "/var/cfengine/inputs/libraries/cfengine_stdlib.cf" };
}

bundle agent foo {

  vars:
    "packages"      slist   =>      { "perl-runtime", "basic-desktop" };

  packages:
    "$(packages)"
      package_policy        =>      "add",
      package_method        =>      yum_group;
}
  • Removing debugging group:
body common control {
  bundlesequence => { "foo" };
  inputs  =>  { "/var/cfengine/inputs/libraries/cfengine_stdlib.cf" };
}

bundle agent foo {

  vars:
    "packages"  slist   =>  { "debugging" };

  packages:
    "$(packages)"
      package_policy    =>  "delete",
      package_method    =>  yum_group;
}

You can find here a full example (with runtime output), and here the body of the yum_group package_method

Read more...

CFEngine: Easy hard classes grepping

Update 2013-03-20: hcgrep has been merged into CFEngine design center

Because cf-promises -v displays hard classes as a single line, it requires a thorough read to determine if a specific hard class is defined, and grep did not help much because they are returned as a single line:

(wrapped for lisibility)

# cf-promises -v|grep freebsd
cf3> Operating System Type is freebsd
cf3> Using internal soft-class freebsd for host bsd82.local
cf3> Additional hard class defined as: freebsd_8_2_RELEASE_p4
cf3> Additional hard class defined as: freebsd_amd64
cf3> Additional hard class defined as: freebsd_amd64_8_2_RELEASE_p4
cf3> GNU autoconf class from compile time: compiled_on_freebsd8_2
cf3>  -> Hard classes = { 172_16_100_1 172_16_2_1 192_168_2_14 1_cpu 64_bit Afternoon Day17 GMT_Hr12 Hr13 Hr13_Q1 Lcycle_0 March Min00
 Min00_05 PK_MD5_e964d2ce7a4dd7887a7374142cff1fb7 Q1 Sunday Yr2013 amd64 any bsd82 bsd82_local cfengine cfengine_3 cfengine_3_5
cfengine_3_5_0a2 common community_edition compiled_on_freebsd8_2 freebsd freebsd_8_2 freebsd_8_2_RELEASE_p4 freebsd_amd64
freebsd_amd64_8_2_RELEASE_p4 ipv4_172 ipv4_172_16 ipv4_172_16_100 ipv4_172_16_100_1 ipv4_172_16_2 ipv4_172_16_2_1 ipv4_192
ipv4_192_168 ipv4_192_168_2 ipv4_192_168_2_14 local mac_unknown net_iface_em0 net_iface_gif0 net_iface_le0 verbose_mode }

Awk can help to split each hard class over separate lines, to render them prettier:

Read more...

Critique du livre 'Practical Vim: Edit Text at the Speed of Thought'

practival vim Publié en octobre 2012, “Practical Vim: Edit Text at the Speed of Thought” est un livre de 311 pages écrit par Drew Neil, déjà connu pour ses screencasts sur Vim.

Ce livre fait parti des rares ouvrages entièrement consacrés à Vim, plus précisément à la version 7.3.

Pas de longues digressions sur l’historique des vi, nvi et autres elvis (un seul encadré page 53), mais juste les références historiques nécessaires à la compréhension de comportements hérités de vi.

Read more...