大约一个月前,我有一个选择:是将用于puppet的模块“写到表中”(即用于内部基础结构)还是使其具有通用性,请打开源并将其发布在puppet forge上 。 当然,为自己快速绘制2-3个等级并冷静下来会更快,更轻松,但是在模块发布期间获得的经验很有价值,我想分享一下。 在RuNet中,没有有关使用up开发工具包(以下简称PDK )的信息,因此您可以考虑将其视为一种教程。
这篇文章是关于什么的
在开发模块(或两个模块)的过程中,我发现了PDK,它极大地促进了模块的开发和维护。 即:
- 最后更新时自动格式化
metadata.json
- 可以执行以下操作的各种CI系统的配置生成:
- 使用rubocop linter检查ruby代码
- 运行单元测试
- 在某些情况下-自动填写人偶伪造工作代码
- 使用码在注释中生成基于标签的文档
- 木偶锻件上的模块板
[PDK]
。 小事,但很好!
全部感兴趣 我要一只猫!
举个例子
如果您想在阅读过程中观察和感觉到什么,可以打开提到的两个模块之一(或两个): clickhouse和xmlsimple 。 两者都是使用PDK和本文中描述的其他工具开发的。
目录内容
什么是PDK
根据官方文档:
创建一个包含类,定义的类型和任务的完整模块,并在进行过程中测试和验证您的工作。 PDK提供了完整的模块结构,类模板,定义的类型和任务以及测试基础结构。 您可以针对各种操作系统和多个Puppet版本验证和测试模块。
在我的免费翻译中:
允许您创建具有类,类型,任务和测试的完整模块,以验证模块的操作。 PDK为上述所有内容提供了完整的结构和模板。 使用此工具,可以检查各种版本的puppet以及不同操作系统中模块的运行情况。
听起来不错吗? 好吧,这就是事实。 直到开始研究该模块(决定立即为开放源代码编写)的那一刻,我才开始怀疑这个工具,现在我打算转移整个内部基础结构以使用PDK。
我将描述如何放置它,以及包含的工具和命令。
安装方式
官方安装页面 。 使用此链接,几乎可以保证您找到在主机上安装PDK的正确方法。 如果由于某种原因您不走运,并且您的操作系统不存在,则始终存在一个环形交叉口:
gem install pdk
实际上,PDK只是一个宝石,它就是这样设置的。
PDK内容
通常,PDK只是一组促进模块开发的宝石。 它包含以下工具:
效用 | 内容描述 |
---|
元数据json-lint | 检查metadata.json是否有匹配的木偶样式指南 |
包 | 通过命令行生成和测试模块及其内容(类,类型等)的工具 |
木偶绒 | 检查人偶代码中的人偶语言样式指南 |
木偶语法 | 验证清单的语法 |
puppetlabs_spec_helper | 提供Rake类,方法和任务,用于人偶代码的规范测试 |
木偶 | 在将清单编译到资源目录(?)时测试p行为 |
rspec-puppet-facts | 允许您使用用户指定的事实来运行rspec-puppet |
创建一个模块
已安装PDK,现在就可以玩了。 最简单的pdk help
命令pdk help
显示可用命令。 假设我们位于您拥有所有其他模块的文件夹中。 然后让我们创建一个新的:
$ pdk new module --template-url=https://github.com/puppetlabs/pdk-templates.git *** We need to create the metadata.json file for this module, so we're going to ask you 5 questions. *** [Q 1/5] If you have a name for your module, add it here. --> dummy [Q 2/5] If you have a Puppet Forge username, add it here. --> felixoid [Q 3/5] Who wrote this module? --> Mikhail f. Shiryaev [Q 4/5] What license does this module code fall under? --> MIT [Q 5/5] What operating systems does this module support? --> RedHat based Linux, Debian based Linux, Windows Metadata will be generated based on this information, continue? Yes pdk (INFO): Module 'dummy' generated at path '/tmp/dummy', from template 'https://github.com/puppetlabs/pdk-templates.git'.
该实用程序会问一些问题以填写metadata.json文件,并且输出的内容与所显示的完全一样:从git模板编译的模块和辅助文件。
简短说明-要素经常更改,包括一些最近已修复的严重错误。 因此,最好不要使用已安装的PDK中的默认值,而应使用最新版本。 没错,这是有--template-url
:当使用--template-url
参数时,PDK将此参数添加到~.pdk/cache/answers.json
并根据进一步执行任何pdk
命令的延迟判断,它尝试下载它们。 因此,请从answers.json
删除此参数,或者在创建模块时不要使用它,并在metadata.json
对其进行更改。
让我们看一下可以使用PDK执行的其他步骤。
新班
$ pdk new class dummy::class pdk (INFO): Creating '/tmp/dummy/manifests/class.pp' from template. pdk (INFO): Creating '/tmp/dummy/spec/classes/class_spec.rb' from template. $ cat manifests/class.pp # A description of what this class does # # @summary A short summary of the purpose of this class # # @example # include dummy::class class dummy::class { } $ cat spec/classes/class_spec.rb require 'spec_helper' describe 'dummy::class' do on_supported_os.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } it { is_expected.to compile } end end end
此命令创建2个文件:类的清单本身和用于测试的规范文件。 稍后,我将详细介绍用于文档的标签。
新的defined_type
$ pdk new defined_type type pdk (INFO): Creating '/tmp/dummy/manifests/type.pp' from template. pdk (INFO): Creating '/tmp/dummy/spec/defines/type_spec.rb' from template.
都一样:资源类型和规范文件的清单。
新提供者和任务
PDK也可以创建一个新的提供程序或任务,但是我没有与他们紧密合作,因此,老实说,最好在必要时更深入地研究该主题。
用p字符串生成文档
我真的不明白为什么puppet strings
不属于PDK工具包的一部分,但这只是一个事实。 如果在开发过程中正确放置了院子的标签 ,那么有两种主要方法可以为用户提供文档:
- 将其生成为HTML / Markdown / JSON,并将其放在代码旁边。 这是通过使用
puppet string generate [--format FORMAT]
命令完成的,该格式可以省略,也可以设置为json
/ markdown
。
- 通常,将存储库根目录中的
REFERENCE.md
文件作为文档标准,该文件标准由puppet strings generate --format markdown
。
- 使用代码(假设它在github上)发布到存储库github-pages。 这很简单,您需要3个命令:
似乎没有什么魔术,但是在输出处,我们有一个带有指令的模块。 优点是,即使不使用@param
标记描述每个参数,输出仍将是类/类型/函数,并带有对类型和默认值的最小描述。 以我的愚见,即使这总比没有好,而且会使模块的使用更具吸引力。
当然,所有这些都可以自动化并作为CI阶段添加。 那将是完美的。 我的手还没有伸手,但积压的灰尘正在积.。 如果突然有人在这个话题上有话要说-我将不胜感激。 思路:至少添加一个检查,查看运行木偶字符串后REFERENCE.md是否更改。 如果是这样,请考虑测试失败。
模板定制
模板的文档位于pdk-templates存储库中。 简而言之,所有内容都使用模块根目录中的.sync.yml
文件进行配置,而更改则使用pdk update
命令应用。 该文件的每个参数都是模块目录中另一个文件的名称,必须以一种或另一种方式进行更改。 每个模板的大多数参数我都必须“通过触摸”来选择,经常查看源代码-反复试验。 此处的文档有时会远远落后。 不幸的是,除了给您自己的存储库中的示例提供链接之外,几乎没有什么可说的了。
我将快速描述上例中使用.sync.yml
更改的一些参数:
Gemfile
:在不同的组中添加了两个Gemfile
作为依赖项:开发组中的pdk; 依赖组中的xml-simple。 开始测试时,未安装system_tests组,因此我将依赖项添加到另一个组。spec/spec_helper.rb
:更改了修改方法,已添加了最小测试覆盖率阈值,在该阈值以下,测试被视为失败。.travis.yml
:此文件已被抛光很长时间,因为它用于检查代码库并将完成的模块加载到puppet-forge上。 变化:
- 用于在puppet-forge上填充模块的用户名和加密密码。 您可以在此处阅读有关使用Travis部署puppet-forge的更多信息。
- 创建了一系列测试→部署,只有在成功进行测试的情况下才启动后者。
- 添加了将模块部署到puppet-forge的阶段,条件是从标记中以字符“ v”开头的CI启动CI。
Rakefile
:为Rakefile
添加了一些例外。
运行各种CI
这里的一切都很简单。 使用PDK生成模块后,立即在appveyor,travis和gitlab-ci中开始验证。 要运行测试,一切.sync.yml
准备就绪, .sync.yml
相同的.sync.yml
进行调整。 我没有特别的偏好,因此我不会推荐任何东西。 只需使用更方便的方式即可。
奖励:我们为类,类型和函数编写单元测试
这一点超出了我计划描述的基本材料,但是对我来说似乎非常有用。
因此,我们有一个带有清单的模块和一个库,该库又包含类,类型和函数(我们也不会忘记任务和提供者,但我在这一部分没有任何专业知识)。 由于存在任何出于更改目的的代码,所以很显然,将其与测试覆盖起来以确保两件事是很不错的:
- 更改不会破坏当前行为(或测试更改行为)
- 您的清单完全符合您的期望,并使用所有期望的资源。
Puppetlabs提供了rspec框架的扩展,称为puppet-rspec 。 链接到有关测试类 , 类型和功能的文档。 不要太懒,不能仔细观察,还有其他章节。
开始使用它非常简单,甚至都不知道红宝石。 如上所示,如果使用pdk new <thing>
创建了类或类型,则*_spec.rb
文件也已存在。 因此,假设我们有一个dummy::class
。 要对其进行测试,必须创建具有以下内容的spec/classes/class_spec.rb
文件:
require 'spec_helper' describe 'dummy::class' do on_supported_os.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } it { is_expected.to compile } end end end
您可以通过从模块的根目录运行pdk test unit
来进行验证。
这几乎是我们所需要的。 现在剩下class_spec.rb
是用适当的条件class_spec.rb
必要的is_expected
来补充class_spec.rb
。 例如,要检查该类是否包含具有某些参数的file {'/file/path': }
资源,可以执行以下操作:
it do is_expected.to contain_file('/file/path').with( 'ensure' => 'file', 'mode' => '0644' ) end
您可以使用let(:params) { {'param1' => 'value'} }
来设置类参数,可以通过将每个参数放在context 'some description' {}
的选定部分中来在各种输入条件下进行测试。 可以检查资源之间以及类之间的依赖关系:例如,如果假设类声明包含inherits
,则可以将is_expected.to contain_class('parent_class_name')
添加到is_expected.to contain_class('parent_class_name')
。 需要检查不同操作系统的行为吗? 这也是可能的:我们仅在单独的上下文中指出必要的事实:
context 'with Debian' do let(:facts) do { os: { architecture: 'amd64', distro: { codename: 'stretch', id: 'Debian', release: { full: '9.6', major: '9', minor: '6', }, }, family: 'Debian', name: 'Debian', release: { full: '9.6', major: '9', minor: '6', }, selinux: { enabled: false, }, }, osfamily: 'Debian', } end it { is_expected.to something } end
通常,就我在编写测试过程中注意到的而言,该框架使您可以检查几乎所有需要的东西。 当某些参数从子类移到模块的顶级类时,测试的存在曾经帮助过我:它们表明重构不会破坏任何内容,整个模块的行为也不会改变。
代替输出
从本文的一般语气中已经可以理解,Puppet在使用模块方面的工作量大大增加了,这使我感到非常鼓舞。 常规操作是自动进行的,尽可能使用模板,开箱即用地提供流行CI的配置。 这似乎是一种开销,并且使用可能无法带来预期的效果,但是绝对值得。 如果比较如何在不使用PDK和使用PDK的情况下开发模块,那么对我来说,它看起来像这样:
没有发展 胡须 PDK | PDK开发 |
---|
 |  |
尝试一下,为自己和您的同事简化生活。 我很乐意回答潜在的问题。
愿雾化与我们同在!