### 使用类的继承和重载
正如节点可以从其他节点继承一样,这可以为相似的节点复制很多代码, 同样的思想也可以用于类。
例如,假设你有一个管理 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) 一节
- Puppet 2.7 Cookbook 中文版
- 中文翻译版
- 译者序
- 项目缘起
- 翻译方法
- 社区链接
- 社区建议
- 贡献者
- 原书版权页
- 关于作者
- 前言
- 本书内容
- 阅读前提
- 适用读者
- 格式约定
- 读者反馈
- 客户支持
- 下载案例代码
- 勘误表
- Puppet 基础设施
- 使用版本控制
- 使用提交钩子
- 使用 Rake 部署变更
- 配置 Puppet 的文件服务器
- 从 cron 运行 Puppet
- 使用自动签名
- 预签名证书
- 从 Puppet 的 filebucket 检索文件
- 使用 Passenger 扩展 Puppet 的部署规模
- 创建去中心化的分布式 Puppet 架构
- 监控、报告和排错
- 生成报告
- 通过 Email 发送包含特定标签的日志信息
- 创建图形化报告
- 自动生成 HTML 文档
- 绘制依赖关系图
- 测试你的 Puppet 配置清单
- 执行模拟运行
- 检测编译错误
- 理解 Puppet 的错误信息
- 显示命令的输出结果
- 输出调试信息
- 检查配置设置
- 使用标签
- 使用运行阶段
- 使用不同的环境
- Puppet 语言及其写作风格
- 使用 Puppet 社区规范
- 使用模块
- 使用标准的命名规范
- 使用嵌入式 Ruby 代码
- 使用纯 Ruby 代码书写配置清单
- 遍历多个项目
- 书写强大的条件语句
- 在 if 语句中使用正则表达式
- 使用选择器和 case 语句
- 检测字符串中是否包含指定的值
- 使用正则表达式替换
- 书写更优质的配置清单
- 使用资源的数组
- 使用 define 资源
- 指定资源的依赖关系
- 使用节点继承
- 使用类的继承和重载
- 给类传递参数
- 书写可重用的跨平台配置清单
- 获得系统的环境信息
- 导入动态信息
- 从 CSV 文件导入数据
- 给 Shell 命令传递参数
- 使用文件和软件包
- 为配置文件添加配置行
- 使用 Augeas 自动修改配置文件
- 使用配置片段构建配置文件
- 使用 ERB 模板
- 在模板中遍历数组
- 从第三方仓库安装软件包
- 配置 APT 软件仓库
- 配置 GEM 仓库
- 从源码包自动构建软件
- 比较软件包的版本
- 用户和虚拟资源
- 使用虚拟资源
- 使用虚拟资源管理用户
- 管理用户基于密钥的 SSH 访问
- 管理用户的自定义文件
- 有效地分发 cron 任务
- 当文件更新时运行命令
- 使用主机资源
- 为文件资源指定多个源
- 使用文件资源递归地分发整个目录树
- 清理过期的旧文件
- 使用日程表资源
- 资源的审计
- 临时禁用资源
- 管理时区
- 应用程序
- 管理 Apache 服务
- 创建 Apache 虚拟主机
- 创建 Nginx 虚拟主机
- 创建 MySQL 数据库及用户
- 管理 Drupal 站点
- 管理 Rails 应用程序
- 服务器和云基础设施
- 部署 Nagios 监控服务器
- 使用 Heartbeat 构建高可用服务
- 管理 NFS 服务和文件共享
- 使用 HAProxy 为多个 web 服务器实现负载均衡
- 使用 iptables 管理防火墙
- 管理 Amazon 的 EC2 实例
- 使用 Vagrant 管理虚拟机
- 外部工具和 Puppet 生态环境
- 创建 Facter 的自定义 fact
- 在运行 Puppet 之前和之后执行命令
- 从 Shell 会话生成 Puppet 配置清单
- 从运行的系统上生成 Puppet 配置清单
- 使用 Puppet Dashboard
- 使用 Foreman
- 使用 MCollective
- 使用公共模块
- 使用外部节点分类器
- 创建自定义的资源类型
- 创建自定义的提供者