原文地址:Module Fundamentals
模块是Puppet自包含的代码和数据集合。绝大多数的清单都可以放到模块中,唯一的例外是主清单site.pp,包含站点级和节点级的代码。
每个Puppet使用者都应该要求自己能够编写一些属于自己的模块:
Puppet能够自动载入在模块中定义的类和函数。在清单或外部节点分类器(external node classifier,ENC)中,类或者函数都可以通过名字的方式被定义:
# /etc/puppetlabs/puppet/site.pp node default { include apache class {'ntp': enable => false; } apache::vhost {'personal_site': port => 80, docroot => '/var/www/personal', options => 'Indexes MultiViews', } }
同样地,Puppet也能够自动地载入在模块中定义的插件(例如自定义的行为和自定义的资源类型)。查阅"使用插件"获取更多的细节。
编写的模块要在Puppet中能够使用,必须将它放在moudlepath配置的一个目录中。
modulepath配置是通过系统路径分隔符连起来的一系列目录。绝大多数情况下是这样的:
/etc/puppetlabs/puppet/modules:/opt/puppet/share/puppet/modules
(针对Puppet企业版本)/etc/puppet/modules:/usr/share/puppet/modules
(针对Puppet开源版本)使用puppet config print modulepath命令可以查看当前的modulepath配置。
使用puppet.conf配置时,如果需要Puppet服务器和代理都能够访问到模块,则modulepath配置必须出现在[main]节。modulepath也可以根据不同的环境设置不同的配置。
使用puppet module命令可以方便地安装其它使用者编写的模块。查阅"安装模块"获取更多的细节。
在磁盘上,一个模块对应一个特殊的目录结构:
例如,一个名为"my_module"的模块,它的目录结构应该是:
manifests目录中的每个清单文件都只能定义一个类或函数,文件名称要与其中定义的类或函数名称对应。
init.pp是特殊的清单文件,包含的类名同模块名。其它清单文件包含的类或函数要满足下面的规则:
模块名 | :: | 其它目录::(如果存在) | 文件名(不包含后缀) |
my_module | :: | other_class | |
my_module | :: | implementation:: | foo |
my_module::other_class必须在
my_module/manifests/other_class.pp文件中定义。
my_module::implementation::foo必须在
my_module/manifests/implementation/foo.pp定义。
类名中间的双冒号(::)被称为命名空间分割符(namespace separator)。
模块名只能包含小写字母、数字和下划线,而且必须以小写字母开头,也就是必须满足正则表达式[a-z][a-z0-9_]*。类名在相同限制上再加上不能包含命名空间分隔符。一些特殊的名称是不允许的,例如:
模块中的静态文件都可以通过file资源类型的source属性访问。每个静态文件都可以映射到一个URL:
协议 | 三个斜杠符号 | “modules”/ | 模块名/ | 文件名 |
puppet: |
/// |
modules/ |
my_module/ |
service.conf |
例如,puppet:///modules/my_module/service.conf对应的文件是
my_module/files/service.conf。
每个ERB模版文件(查阅"模版"获取更多信息)都可以通过template函数被输出。输出的内容是一个简单的字符串,通常作为file资源类型的content属性,或者保存到一个变量。
template函数按照下面的方式定位模版文件:
template函数 | (‘ | 模块名/ | 模版名 | ’) |
template |
(' |
my_module/ |
component.erb |
') |
例如,template('my_module/component.erb')对应的文件是
my_module/templates/component.erb
。
通过上面的讲述,现在我们应该能够编写简单的类和函数了。
一个模块中的类、函数和插件可以是互相关联的。
一个模块中的清单绝不应该引用其它模块中的文件或模块。
如果有模块中的一个类使用了其它模块中的另外一个类,这种情况应该尽可能避免,它会让模块的发布变得非常困难。解决此问题的方法是创建一个包含很多“超级类”的公共模块。