使用类的继承和重载
正如节点可以从其他节点继承一样,这可以为相似的节点复制很多代码, 同样的思想也可以用于类。
例如,假设你有一个管理 Apache Web 服务器的 apache 类, 你想要使用略有不同的配置文件设置一台新的 Apache 机器?—?也许是监听的端口不同。
你可以复制整个 apache 类,除了配置文件。另外,你可以从 apache 类中提取配置文件并创建两个新类,每个新类都包含 apache 基类并添加一个新版本的配置文件。
一个更简洁的做法是从 apache 类继承,而后仅覆盖其配置文件。
准备工作
为新的 apache 模块创建目录结构:
# mkdir /etc/puppet/modules/apache # mkdir /etc/puppet/modules/apache/manifests # mkdir /etc/puppet/modules/apache/files
使用如下代码创建 /etc/puppet/modules/apache/manifests/init.pp 文件:
class apache { package { "apache2-mpm-worker": ensure => installed } service { "apache2": enable => true, ensure => running, require => Package["apache2-mpm-worker"], } file { "/etc/apache2/ports.conf": source => "puppet:///modules/apache/port80.conf.apache", notify => Service["apache2"], } }
若 Apache 软件包还未安装,安装它,复制其包含的文件 ports.conf 到 Puppet:
# apt-get install apache2-mpm-worker # cp /etc/apache2/ports.conf \ /etc/puppet/modules/apache/files/port80.conf.apache
添加 apache 类到一个节点,例如:
node cookbook { include apache }
运行 Puppet 验证配置清单是否正常工作。
操作步骤
创建 port80.conf.apache 文件的一个新版本 port8000.conf.apache,并做如下改动:
NameVirtualHost *:8000 Listen 8000
使用如下内容创建一个新文件 /etc/puppet/modules/apache/manifests/port8000.pp:
class apache::port8000 inherits apache { File["/etc/apache2/ports.conf"] { source => "puppet:///modules/apache/port8000.conf.apache", } }
改变你的节点配置,使其包含 apache::port8000 类而不是 apache 类:
node cookbook { include apache::port8000 }
运行 Puppet 检查它是否会按照要求的那样发生改变:
# puppet agent --test info: Retrieving plugin info: Caching catalog for cookbook.bitfieldconsulting.com info: Applying configuration version '1302970905' --- /etc/apache2/ports.conf 2010-11-18 14:16:23.000000000 -0700 +++ /tmp/puppet-file20110416-6165-pzeivi-0 2011-04-16 10:21:47.204294334 -0600 @@ -5,8 +5,8 @@ # Debian etch). See /usr/share/doc/apache2.2-common/NEWS.Debian.gz and # README.Debian.gz -NameVirtualHost *:80 -Listen 80 +NameVirtualHost *:8000 +Listen 8000 <IfModule mod_ssl.c> # If you add NameVirtualHost *:443 here, you will also have to change info: FileBucket adding /etc/apache2/ports.conf as {md5}38b31d2032 6f3640a8dfbe1ff5d1c4ad info: /Stage[main]/Apache/File[/etc/apache2/ports.conf]: Filebucketed /etc/apache2/ports.conf to puppet with sum 38b31d20326f3640a8dfbe1ff5d1c4ad notice: /Stage[main]/Apache/File[/etc/apache2/ports.conf]/content: content changed '{md5}38b31d20326f3640a8dfbe1ff5d1c4ad' to '{md5}4 1d9d446f779c55f13c5fe5a7477d943' info: /Stage[main]/Apache/File[/etc/apache2/ports.conf]: Scheduling refresh of Service[apache2] notice: /Stage[main]/Apache/Service[apache2]: Triggered 'refresh' from 1 events notice: Finished catalog run in 4.85 seconds
工作原理
让我们再看看这个新类:
class apache::port8000 inherits apache {
File["/etc/apache2/ports.conf"] {
source => "puppet:///modules/apache/port8000.conf.apache",
}
}
你可以从类名后看出,此类继承(inherits)自 apache 类。这将创建一个与 apache 类完全相同的副本,除了跟随其后的变化。
如下的代码片段:
File["/etc/apache2/ports.conf"] {
指定了我们想要改变父类中名为 /etc/apache2/ports.conf 的 file 资源 (注意 File 是首字母大写的,这意味着,我们指的是现有的资源,而不是定义一个新资源)。
如下的代码片段:
source => "puppet:///modules/apache/port8000.conf.apache",
意味着我们将使用一个新的值覆盖父类中 source 资源的参数值。 如果我们复制整个 apache 类的定义并改变资源 source 的值,那么结果将是完全一样的:
class apache {
package { "apache2-mpm-worker": ensure => installed }
service { "apache2":
enable => true,
ensure => running,
require => Package["apache2-mpm-worker"],
}
file { "/etc/apache2/ports.conf":
source => "puppet:///modules/apache/port8000.conf.apache",
notify => Service["apache2"],
}
}
更多用法
首先覆盖被继承的类看上去有些复杂。然而一旦你掌握了这种思想,就会发现这实际上很简单。 这是一种使你的配置清单更具可读性的强大方式,因为这样消除了大量的重复代码, 使你仅专注于编写不同的代码部分。下面给出几种使用覆盖的方法。
取消参数的定义
有时候你不想改变一个参数的值,只是想完全移除它的值。 为了实现这一点,可以使用 undef 值覆盖原有值。 其结果就像是此参数从未在先前定义过一样。
class apache::norestart inherits apache {
File["/etc/apache2/ports.conf"] {
notify => undef,
}
}
使用 +> 操作符添加额外的值
与替换一个值类似,你可能想要在父类定义的基础上添加更多的值。 使用 plusignment 操作符 +> 可以实现这一功能:
class apache::ssl inherits apache {
file { "/etc/ssl/certs/cookbook.pem":
source => "puppet:///modules/apache/cookbook.pem",
}
Service["apache2"] {
require +> File["/etc/ssl/certs/cookbook.pem"],
}
}
操作符 +> 在父类定义的值的基础上添加一个值(或使用方括号括起来的一个数组)。 对于上面的例子,我们最终得到的代码相当于:
service { "apache2":
enable => true,
ensure => running,
require => [ Package["apache2-mpm-worker"], File["/etc/ssl/certs/
cookbook.pem"] ],
}
禁用资源
继承和覆盖最常见的用途之一就是禁用服务或其他资源:
class apache::disabled inherits apache {
Service["apache2"] {
enable => false,
ensure => stopped,
}
}