CFEngine: little insert_lines annoyance fixed

Sometimes, crontab entries are preferable over CFEngine internal scheduling when jobs have special scheduling requirements. I have one example where a job must absolutely be started every 2 minutes. (03:20, 03:22, 03:24 and so on)

By default cf-execd is started every 5 minutes, it is ok for 03:20 with Min00, but Min22 and Min24 hard classes will never be defined while cf-execd is running, and some job occurrences never started. Cf-execd can be launched every minute, but by reducing this interval you may have to deal with lock issues. (long splaytime ?)

Read more...

CFEngine: bash-completion settings

You can now get completion for cf-* commands if you are using Bash and bash-completion helper

Simply put contrib/cfengine-completion.bash into your bash_completion.d directory:

# wget  https://raw.github.com/cfengine/core/master/contrib/cfengine-completion.bash -O -|sudo tee /etc/bash_completion.d/cfengine

Restart your shell, and enjoy:

$ cf-promises --<tab><tab>
--bundlesequence        --diagnostic            --full-check            --negate                --verbose               
--debug                 --dry-run               --help                  --policy-output-format  --version               
--define                --file                  --inform                --reports               
$ ~/.cfagent/bin/cf-promises --bundl<tab>
$ ~/.cfagent/bin/cf-promises --bundlesequence
Read more...

CFEngine: getting mac addresses on BSD systems

It is now possible to retrieve mac addresses under BSD operating systems. (merged into master branch, not yet released)

As far as I know, at least FreeBSD, NetBSD and OpenBSD don’t implement the SIOCGIFHWADDR ioctl, so a getifaddrs() fallback was needed.

Before, only mac_unknown hard class was reported:

# cf-promises -v|hcgrep mac
mac_unknown

Now:

# cf-promises -v|hcgrep mac
mac_08_00_d5_84_88_00

Of course, sys.hardware_addresses and [sys.hardware_macinterface_name] variables are populated.

what is hcgrep?

Read more...

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...