企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### 使用类的继承和重载 正如节点可以从其他节点继承一样,这可以为相似的节点复制很多代码, 同样的思想也可以用于类。 例如,假设你有一个管理 Apache Web 服务器的 apache 类, 你想要使用略有不同的配置文件设置一台新的 Apache 机器?—?也许是监听的端口不同。 你可以复制整个 apache 类,除了配置文件。另外,你可以从 apache 类中提取配置文件并创建两个新类,每个新类都包含 apache 基类并添加一个新版本的配置文件。 一个更简洁的做法是从 apache 类继承,而后仅覆盖其配置文件。 #### 准备工作 1. 为新的 apache 模块创建目录结构: ``` # mkdir /etc/puppet/modules/apache # mkdir /etc/puppet/modules/apache/manifests # mkdir /etc/puppet/modules/apache/files ``` 2. 使用如下代码创建 /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"], } } ``` 3. 若 Apache 软件包还未安装,安装它,复制其包含的文件 ports.conf 到 Puppet: ``` # apt-get install apache2-mpm-worker # cp /etc/apache2/ports.conf \ /etc/puppet/modules/apache/files/port80.conf.apache ``` 4. 添加 apache 类到一个节点,例如: ``` node cookbook { include apache } ``` 5. 运行 Puppet 验证配置清单是否正常工作。 #### 操作步骤 1. 创建 port80.conf.apache 文件的一个新版本 port8000.conf.apache,并做如下改动: ``` NameVirtualHost *:8000 Listen 8000 ``` 2. 使用如下内容创建一个新文件 /etc/puppet/modules/apache/manifests/port8000.pp: ``` class apache::port8000 inherits apache { File["/etc/apache2/ports.conf"] { source => "puppet:///modules/apache/port8000.conf.apache", } } ``` 3. 改变你的节点配置,使其包含 apache::port8000 类而不是 apache 类: ``` node cookbook { include apache::port8000 } ``` 4. 运行 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, } } ``` #### 参见本书 * 第 4 章的 [使用节点继承](#ch04sec04) 一节 * 第 4 章的 [给类传递参数](#ch04sec06) 一节 * 第 3 章的 [使用标准的命名规范](#ch03sec03) 一节