第一个 CFEngine policy

所有 CFEngine 策略都必须具有一个 control body,其中包含常规配置和执行信息。
唯一必需的元素是 bundlesequence,它告诉 CFEngine 要执行哪个 bundles(promise 的容器)以及执行顺序。

对于我们的示例策略,我们将执行一个 bundle

body common control
{
        bundlesequence => { "edit_motd" };
}

这告诉 CFEngine,这个策略必须运行名为 edit_motdbundle

下面是 edit_motd 的定义:

bundle agent edit_motd 
{
  vars:   
      "motd" string => "/etc/motd";

  files:   
      "$(motd)"
        create => "true",
        edit_line => addmessage;

  reports:   
    cfengine::
      "Hello world!";
}

这个策略部分(the part of the policy)是告诉 CFEngine 要做什么。

edit_modt bundle

下面是它的工作原理:

  • (1)在 CFEngine 中,类型为 agentbundle(通过 bundle agent 关键字声明,后跟任意标识符,在这个例子中为 edit_motd
    • 可以视为等同于函数,并包含 CFEngine evaluates 并根据需要执行的 promises
    • 它被分为不同类型的 promise 部分,以单词开头并以单个冒号(colon)结尾的行。
    • 在这个 bundle 中,我们分为三个部分:vars:files:report:
  • (2)vars: 用于声明变量。
    • CFEngine 具有几种变量类型,包括 stringlistarraynumbers(支持 integerfloting-point)。
    • 在这里,我们声明一个名为 motdstring 值,其中包含我们要编辑的文件的路径。
    • 如果您没有 /etc/motd 文件的权限,则应将此路径更改为可以编辑的某些文件,例如 /tmp/motd

在 CFEngine 策略中,所有内容都表示为承诺(promise),甚至是变量声明。
在这个例子中,"motd" 将是一个包含 "/etc/motd" 值的字符串变量。我们将在策略的后面引用此变量。
在 CFEngine 中,标量变量引用由美元符号表示,后跟变量名称 ${motd}$(motd) 都引用同一个变量。

  • (3)files: 指出我们要执行的与文件相关的操作。
    • 在这种情况下,promiser"$(motd)",它将 motd 变量扩展为其值,因此 promiser 变为 "/etc/motd",告诉 CFEngine 要编辑哪个文件。
    • promise 的其余部分,直到分号(semicolon)为止,都称为承诺的主体(the body of the promise),并由以逗号(comma)分隔的 attribute => value 对组成。
    • 在这个例子中,我们有两个属性规范:create => "true"edit_line => addmessage
      • 前者只是指示如果尚不存在,则需要创建该文件。
      • 后者意味着 /etc/motd 中的行将根据名为 addmessagebundle 定义的操作进行编辑。

将其转换为 CFEngine 术语files: 部分中的所有 promiser 将由 CFEngine 解释为系统上的文件,因此我们的示例策略中的 promise 意味着可以根据主体给出的指令来编辑 /etc/motd 文件的诺言。
edit_line 参数的值是 edit_line bundle 的名称。这意味着它不是一个单一值,而是一个单独的 bundle 的名称,用于指定 edit_line 属性的行为。

下面是 bundle edit_line addmessage 的定义:

bundle edit_line addmessage
{
  insert_lines:
      "This system is managed by CFEngine 3";
}

这是另一个 bundle,这意味着它也是 promise 的容器,并且也分成多个部分。每个 bundle 的类型由其声明中的第二个单词标识(在本例中为 edit_line)。
您可以看到 edit_motd bundle 的类型为 agent,这意味着它是一个可以直接调用执行的 bundle,(在这种例子中,可以从 bundlesequence 声明中调用,尽管还有其他执行 agent bundle 的方法,我们稍后将介绍)。
因此,第一行将类型 edit_line 分配给 addmessage bundle,这意味着 addmessage 只能用作 edit_line 属性的值。另外,bundle 的类型定义了其中有效的部分以及如何解释其中的承诺。

edit_line bundle 必须包含对文件执行编辑的 promise
在这个例子中,它包含一个 insert_lines: 部分,因此,promise 将被解释为要在文件中插入的行。这个 bundle 中唯一的 promise 是一个字符串,其中包含我们要在文件中插入的消息。 此承诺没有主体(字符串本身就是 promiser,并且没有给出其他属性),这意味着该行将始终插入到文件中,除非该行已经存在(这是默认行为)。
总而言之,这意味着给定的行将被插入到 /etc/motd 中(如果尚未存在的话)。

  • (4)reports: 用于在执行策略期间产生输出,指示消息及其处理方式。
    • 默认情况下,承诺的消息将被打印到控制台。
    • 在当前的例子中,每次执行该策略时,我们将打印消息 Hello world! 到控制台。

您可能会注意到在消息之前的 cfengine:: 行。这是一个 class expression,它告诉 CFEngine 在什么条件下遵循它的 promise 将被执行。
在此示例中,cfengine 是一个类,如果 CFEngine 正在执行该策略,则该类将被定义,因此它将始终为 true,并且将始终打印该消息。
但是我们可以使用其他类。例如,如果将 cfengine:: 替换为 Monday::,则消息仅在星期一打印。

CFEngine 定义了许多类,例如一周中的几天,并且策略可以定义任意数量的任意类。

将上述内容(或直接使用 edit_motd_helloworld.cf)其保存到文件,例如保存到 edit_motd_helloworld.cf 文件。
然后可以使用以下命令执行它:

# sudo cf-agent -KI -f ./edit_motd_helloworld.cf
    info: Created file '/etc/motd', mode 0600
    info: Inserted the promised line 'This system is managed by CFEngine 3' into '/etc/motd' after locator
    info: insert_lines promise 'This system is managed by CFEngine 3' repaired
    info: Edited file '/etc/motd'
    info: files promise '/etc/motd' repaired
R: Hello world!
  • -K 选项表示 “忽略执行期间的锁定约束”,实际上表示 “始终执行所有 promise”。
    • 正常情况下,CFEngine 遵守两次相同承诺的连续评估之间的特定时间段,以避免系统过载。
    • -K 选项禁用这些约束,因此对于测试可能连续快速运行几次的策略很有用。
  • -I选项的意思是 “打印有关对系统所做的更改的基本信息”,实际上是告诉 CFEngine 向您显示它正在执行的操作。
    • 如果未指定,CFEngine 的输出将非常简洁,仅限于策略明确打印的报告以及其他一些基本消息。
  • -f 选项告诉 CFEngine 使用指定的文件作为其输入。
    • 否则,它将尝试读取 /var/cfengine/inputs/promises.cf

参考

  • CFEngine 简介和安装
  • Learning CFEngine书上代码
  • 以常规用户身份运行CFEngine

你可能感兴趣的:(第一个 CFEngine policy)