模块格式和文档
如果您想将您的模块贡献到大多数 Ansible 集合,您必须用 Python 编写您的模块并遵循下面描述的标准格式。(除非您正在编写 Windows 模块,在这种情况下,Windows 指南适用。)除了遵循此格式之外,您还应该查看我们的提交清单、编程技巧和维护 Python 2 和 Python 3 兼容性的策略,以及有关测试的信息,然后您才能打开拉取请求。
每个用 Python 编写的 Ansible 模块都必须以特定顺序以七个标准部分开头,然后是代码。顺序部分是
注意
为什么导入不放在首位?
敏锐的 Python 程序员可能会注意到,与 PEP 8 的建议相反,我们没有将 imports
放在文件顶部。这是因为 DOCUMENTATION
到 RETURN
部分没有被模块代码本身使用;它们本质上是文件的额外文档字符串。将导入放在这些特殊变量之后的原因与 PEP 8 将导入放在介绍性注释和文档字符串之后的原因相同。这将使代码的活动部分保持在一起,而纯粹的资讯部分则分开。将 E402 排除的决定是基于可读性(这也是 PEP 8 的目的)。模块中的文档字符串与模块级别的文档字符串更相似,而不是代码,并且从未被模块本身使用。将导入放在此文档下面,更靠近代码,以一致的方式合并和分组所有相关代码,以提高可读性、调试和理解能力。
警告
谨慎复制旧模块!
一些较旧的 Ansible 模块在文件底部有 imports
、带有完整 GPL 前缀的 Copyright
通知,或 DOCUMENTATION
字段的顺序错误。这些是需要更新的旧文件,不要将它们复制到新模块中。随着时间的推移,我们正在更新和更正旧模块。请遵循本页面的指南!
注意
对于非 Python 模块,您仍然可以为文档目的创建一个 .py
文件。从 ansible-core 2.14 开始,您还可以选择创建一个 .yml
文件,该文件具有相同的数据结构,但使用纯 YAML。使用 YAML 文件,下面的示例很容易使用,只需删除 Python 引号并用 =
替换 :
,例如 DOCUMENTATION = r''' ... '''
到 DOCUMENTATION: ...
并删除结束引号。 相邻的 YAML 文档文件
Python shebang & UTF-8 编码
用 #!/usr/bin/python
开始您的 Ansible 模块 - 此“shebang”允许 ansible_python_interpreter
工作。在 shebang 之后立即添加 # -*- coding: utf-8 -*-
以澄清文件是 UTF-8 编码的。
警告
使用
#!/usr/bin/env
将env
设为解释器,并绕过ansible_<interpreter>_interpreter
逻辑。在 shebang 中传递参数给解释器不起作用(例如,
#!/usr/bin/env python
)。
注意
如果您使用不同的脚本语言开发模块,请相应地调整解释器(#!/usr/bin/<interpreter>
),以便 ansible_<interpreter>_interpreter
可以为该特定语言工作。
注意
二进制模块不需要 shebang 或解释器。
版权和许可
在 shebang 和 UTF-8 编码之后,添加一个版权行,其中包含原始版权持有者和许可声明。许可声明应仅为一行,而不是完整的 GPL 前缀。
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
对模块的添加(例如重写)不允许添加额外的版权行,除非缺少默认版权声明。
# Copyright: Contributors to the Ansible project
任何法律审查都将包括源代码控制历史记录,因此不需要详尽的版权头。请不要包含版权年份。如果现有的版权声明包含年份,请不要编辑现有的版权年份。任何现有的版权头在未经版权作者许可的情况下不得修改。
ANSIBLE_METADATA 块
由于我们迁移到了集合,我们已经弃用了 METADATA 功能,它不再是模块的必需项,但如果存在,它不会破坏任何东西。
DOCUMENTATION 块
在 shebang、UTF-8 编码、版权行和许可证部分之后,是 DOCUMENTATION
块。Ansible 的在线模块文档是从每个模块源代码中的 DOCUMENTATION
块生成的。 DOCUMENTATION
块必须是有效的 YAML。您可能会发现,在将它包含在 Python 文件中之前,先在具有 YAML 语法高亮的编辑器中开始编写您的 DOCUMENTATION
字符串会更容易。您可以通过将我们的示例文档字符串复制到您的模块文件并进行修改来开始。如果您在 YAML 中遇到了语法问题,您可以在 YAML Lint 网站上验证它。
- 模块文档应简要准确地定义每个模块和选项的作用,以及它如何在底层系统中与其他模块协同工作。文档应该为广泛的受众编写,无论专家还是非专家都能阅读。
描述应始终以大写字母开头,并以句号结尾。一致性总是很有帮助的。
验证 doc 和模块规范字典中的参数是否相同。
对于密码/秘密参数,应设置
no_log=True
。对于似乎包含敏感信息但**不**包含秘密的参数,例如“password_length”,请设置
no_log=False
以禁用警告消息。如果某个选项只在某些情况下是必需的,请描述这些条件。例如,“当 I(state=present) 时必需”。
如果您的模块允许
check_mode
,请在文档中反映这一点。
要创建清晰、简洁、一致且有用的文档,请遵循风格指南。
下面描述了每个文档字段。在提交模块文档之前,请在命令行和 HTML 中测试它。
只要您的模块文件 在本地可用,您就可以使用
ansible-doc -t module my_module_name
在命令行中查看您的模块文档。任何解析错误都会很明显 - 您可以在命令中添加-vvv
来查看详细信息。您还应该 测试模块文档的 HTML 输出。
文档字段
DOCUMENTATION
块中的所有字段都为小写。除非另有说明,否则所有字段都是必需的。
- module:
模块名称。
必须与文件名相同,不包括
.py
扩展名。
- short_description:
简短描述,显示在 集合索引 页面和
ansible-doc -l
中。short_description
由ansible-doc -l
显示,没有任何类别分组,因此它需要足够的细节来解释模块的目的,而无需其所在目录结构的上下文。与
description:
不同,short_description
不应有尾随句点/句号。
- description:
详细说明(通常两句或更多句)。
必须用完整的句子编写,换句话说,用大写字母和句点/句号。
不应提及模块名称。
使用多个条目,而不是使用一个长段落。
除非 YAML 要求,否则不要引用完整的值。
- version_added:
添加模块的 Ansible 版本。
这是一个字符串,而不是浮点数,例如
version_added: '2.1'
。在集合中,这必须是模块添加到其中的集合版本,而不是 Ansible 版本。例如,
version_added: 1.0.0
。
- author:
模块作者姓名,格式为
First Last (@GitHubID)
。如果有多个作者,请使用多行列表。
不要使用引号,因为 YAML 不应该需要它。
- deprecated:
标记将在未来版本中删除的模块。另请参阅 Ansible 模块或插件的生命周期。
- options:
选项通常称为“参数”或“参数”。由于文档字段称为
options
,我们将使用该术语。如果模块没有选项(例如,它是一个
_facts
模块),您只需要一行:options: {}
。如果您的模块有选项(换句话说,接受参数),则应详细记录每个选项。对于每个模块选项,包括
- option-name:
声明式操作(不是 CRUD),专注于最终状态,例如
online:
,而不是is_online:
。选项名称应与模块的其余部分以及同一类别中的其他模块保持一致。
如有疑问,请查找其他模块以查找用于相同目的的选项名称,我们希望为用户提供一致性。
(没有显式的字段
option-name
。此条目与options
字典中选项的键有关。)
- description:
详细解释此选项的作用。它应该用完整的句子编写。
第一个条目是选项本身的描述;随后的条目详细介绍了它的使用、依赖项或可能值的格式。
不应列出可能的值(这就是
choices:
的作用,尽管它应该解释这些值的作用,如果它们并不明显)。如果某个选项只在某些情况下是必需的,请描述这些条件。例如,“当 I(state=present) 时必需”。
互斥选项必须在每个选项的最后一句话中进行记录。
- required:
仅在
true
时才需要。如果缺少,我们假设该选项不是必需的。
- default:
如果
required
为 false/缺少,则可以指定default
(如果缺少则假定为 'null')。确保文档中的默认值与代码中的默认值匹配。
默认字段不得列为描述的一部分,除非它需要其他信息或条件。
如果选项是布尔值,则可以使用 Ansible 识别的任何布尔值(例如
true
/false
或yes
/no
)。为了与 ansible-lint 保持一致性和兼容性,将布尔值记录为true
/false
。
- choices:
选项值的列表。
如果为空,则应不存在。
- type:
指定选项接受的数据类型,必须与
argspec
匹配。如果参数为
type='bool'
,则此字段应设置为type: bool
,并且不应指定choices
。如果参数为
type='list'
,则应指定elements
。
- elements:
在
type='list'
的情况下,指定列表元素的数据类型。
- aliases:
可选名称别名的列表。
通常不需要。
- version_added:
仅在初始 Ansible 版本之后扩展此选项时才需要,换句话说,这大于顶层
version_added
字段。这是一个字符串,而不是浮点数,例如
version_added: '2.3'
。在集合中,这必须是选项添加到其中的集合版本,而不是 Ansible 版本。例如,
version_added: 1.0.0
。
- suboptions:
如果此选项采用字典或字典列表,您可以在此处定义结构。
查看 azure.azcollection.azure_rm_securitygroup、azure.azcollection.azure_rm_azurefirewall 和 openstack.cloud.baremetal_node_action 了解示例。
- requirements:
要求列表(如果适用)。
包括最小版本。
- seealso:
其他模块、文档或互联网资源的参考列表
在 Ansible 2.10 及更高版本中,对模块的引用必须使用 FQCN 或
ansible.builtin
(用于ansible-core
中的模块)。自 ansible-core 2.15 起,支持插件引用。
参考可以是以下格式之一
seealso: # Reference by module name - module: cisco.aci.aci_tenant # Reference by module name, including description - module: cisco.aci.aci_tenant description: ACI module to create tenants on a Cisco ACI fabric. # Reference by plugin name - plugin: ansible.builtin.file plugin_type: lookup # Reference by plugin name, including description - plugin: ansible.builtin.file plugin_type: lookup description: You can use the ansible.builtin.file lookup to read files on the control node. # Reference by rST documentation anchor - ref: aci_guide description: Detailed information on how to manage your ACI infrastructure using Ansible. # Reference by rST documentation anchor (with custom title) - ref: The official Ansible ACI guide <aci_guide> description: Detailed information on how to manage your ACI infrastructure using Ansible. # Reference by Internet resource - name: APIC Management Information Model reference description: Complete reference of the APIC object model. link: https://developer.cisco.com/docs/apic-mim-ref/
如果您使用
ref:
链接到与标题不相关的锚点,则必须为该链接添加标题才能使其正常工作。
- attributes:
一个字典,将属性名称映射到描述该属性的字典。
通常,属性由文档片段提供,例如
ansible.builtin.action_common_attributes
及其子片段。模块和插件使用适当的文档片段并填写support
、details
和潜在的特定于属性的其他字段。
- description:
一个字符串或一个字符串列表。每个字符串都是一段。描述是必需的。
解释此属性的作用。它应该用完整的句子编写。
- details:
一个字符串或一个字符串列表。每个字符串都是一段。
描述支持可能无法按用户预期的方式工作。
通常,详细信息是可选的,但如果
support
为partial
,则必须提供详细信息。
- support:
full
、none
、partial
或N/A
之一。这是必需的。指示此模块或插件是否支持此属性。
- membership:
一个字符串或一个字符串列表。
仅可用于属性
action_group
,并且必须始终为该属性指定该属性。列出此模块或操作所属的操作组。
- platforms:
一个字符串或一个字符串列表。
仅可用于属性
platform
,并且必须始终为该属性指定该属性。列出模块或操作支持的平台。
- version_added:
仅当该属性的支持是在模块/插件创建后扩展的,换句话说,如果它大于顶层的
version_added
字段。这是一个字符串,而不是浮点数,例如
version_added: '2.3'
。在集合中,这必须是该属性支持被添加到的集合版本,而不是 Ansible 版本。例如,
version_added: 1.0.0
。
- 备注:
任何不适合以上部分的重要信息细节。
关于
check_mode
或diff
的信息**不**应该列在这里,而应该在attributes
中提到。
模块文档中的链接
您可以使用一些预定义的宏,从模块文档链接到其他模块文档、docs.ansible.com 上的其他资源,以及互联网上的其他资源。这些宏的正确格式为
L()
用于带有标题的链接。例如:See L(Ansible Automation Platform,https://www.ansible.org.cn/products/automation-platform).
从 Ansible 2.10 开始,不要使用L()
用于 Ansible 文档和集合文档之间的相对链接。U()
用于 URL。例如:See U(https://www.ansible.org.cn/products/automation-platform) for an overview.
R()
用于带有标题的交叉引用(在 Ansible 2.10 中添加)。例如:See R(Cisco IOS Platform Guide,ios_platform_options)
. 使用交叉引用的 RST 锚点。有关详细信息,请参阅 添加锚点。M()
用于模块名称。例如:See also M(ansible.builtin.yum) or M(community.general.apt_rpm)
. 必须使用 FQCN,短名称将创建损坏的链接;对于 ansible-core 中的模块,使用ansible.builtin
。P()
用于插件名称。例如:See also P(ansible.builtin.file#lookup) or P(community.general.json_query#filter)
. 这也可以引用角色:P(community.sops.install#role)
. 从 ansible-core 2.15 开始支持此功能。必须使用 FQCN;对于 ansible-core 中的插件,使用ansible.builtin
。
注意
对于模块和集合内文档之间的链接,您可以使用上述任何选项。对于集合之外的链接,如果可用,请使用 R()
。否则,使用 U()
或 L()
以及完整的 URL(而不是相对链接)。对于模块,使用 M()
以及 FQCN 或 ansible.builtin
,如示例所示。如果您正在创建自己的文档站点,则需要使用 intersphinx 扩展 将 R()
和 M()
转换为正确的链接。
注意
要引用集合中的一组模块,请使用 R()
。当集合不是正确的粒度时,请使用 C(..)
Refer to the R(kubernetes.core collection, plugins_in_kubernetes.core) for information on managing kubernetes clusters.
The C(win_*) modules (spread across several collections) allow you to manage various aspects of windows hosts.
注意
因为它更突出,所以使用 seealso
用于一般参考,而不是使用注释或向描述中添加链接。
模块文档中的语义标记
您可以使用语义标记来突出显示选项名称、选项值和环境变量。标记处理器以统一的方式格式化这些突出显示的术语。使用语义标记,我们可以修改输出的外观,而无需更改底层代码。
语义标记的正确格式如下
O()
用于选项名称,无论单独提及还是与值一起提及。例如:Required if O(state=present).
和Use with O(force) to require secure access.
V()
用于单独提及的选项值。例如:Possible values include V(monospace) and V(pretty).
RV()
用于返回值名称,无论单独提及还是与值一起提及。例如:The module returns RV(changed=true) in case of changes.
和Use the RV(stdout) return value for standard output.
E()
用于环境变量。例如:If not set, the environment variable E(ACME_PASSWORD) will be used.
这些格式函数的参数可以使用反斜杠进行转义:V(foo(bar="a\\b"\), baz)
会导致格式化的值 foo(bar="a\b"), baz)
。
使用 O()
和 RV()
的规则非常严格。您必须遵循语法规则,以便文档渲染器可以分别为选项和返回值创建超链接。
允许的语法如下
要引用当前插件/模块的选项,或当前角色的入口点(在角色入口点文档中),请使用
O(option)
和O(option=name)
。要引用角色文档内其他入口点
entrypoint
的选项,请使用O(entrypoint:option)
和O(entrypoint:option=name)
。入口点信息可以被文档渲染器忽略,变成指向该入口点的链接,甚至直接指向该入口点的选项。要引用类型为
type
的另一个插件/模块plugin.fqcn.name
的选项,请使用O(plugin.fqcn.name#type:option)
和O(plugin.fqcn.name#type:option=name)
。对于模块,使用type=module
。FQCN 和插件类型可以被文档渲染器忽略,变成指向该插件的链接,甚至直接指向该插件的选项。要引用另一个角色
role.fqcn.name
的入口点entrypoint
的选项,请使用O(role.fqcn.name#role:entrypoint:option)
和O(role.fqcn.name#role:entrypoint:option=name)
。FQCN 和入口点信息可以被文档渲染器忽略,变成指向该入口点的链接,甚至直接指向该入口点的选项。要引用不存在的选项(例如,在早期版本中已删除的选项),请使用
O(ignore:option)
和O(ignore:option=name)
。文档渲染将不会向用户显示ignore:
部分。
选项名称可以通过列出以点分隔的选项路径来引用子选项。例如,如果您有一个带有子选项 bar
的选项 foo
,那么您必须使用 O(foo.bar)
来引用该子选项。您可以添加类似 O(foo[].bar)
甚至 O(foo[-1].bar)
的数组指示来指示特定的列表元素。[
和 ]
对之间的所有内容将被忽略,以确定选项的实际名称。例如,O(foo[foo | length - 1].bar[])
会产生与 O(foo.bar)
相同的链接,但文本 foo[foo | length - 1].bar[]
会显示而不是 foo.bar
。
相同的语法可用于 RV()
,只是它们将引用返回值名称而不是选项名称;例如 RV(ansible.builtin.service_facts#module:ansible_facts.services)
引用了由 ansible.builtin.service_facts 模块 返回的 ansible_facts.services
事实。
模块文档中的格式宏
虽然可以使用标准的 Ansible 格式化宏来控制模块文档中其他术语的外观,但您应该谨慎使用。
可能的宏包括以下内容
C()
用于monospace
(代码)文本。例如:This module functions like the unix command C(foo).
B()
用于粗体文本。I()
用于斜体文本。HORIZONTALLINE
用于水平线(<hr>
HTML 标签),用于分隔较长的描述。
请注意,C()
、B()
和 I()
**不允许转义**,因此不能包含值 )
,因为它总是结束格式化序列。如果您需要在 C()
中使用 )
,我们建议您使用 V()
;请参见上面关于语义标记的部分。
文档片段
如果您正在编写多个相关的模块,它们可能共享一些通用文档,例如身份验证详细信息、文件模式设置、notes:
或 seealso:
条目。与其在每个模块的 DOCUMENTATION
块中重复这些信息,不如将它们保存为一个 doc_fragment 插件,并在每个模块的文档中使用它。在 Ansible 中,共享文档片段包含在 ModuleDocFragment
类中,位于 lib/ansible/plugins/doc_fragments/ 或集合中的等效目录中。要包含一个文档片段,请在您的模块文档中添加 extends_documentation_fragment: FRAGMENT_NAME
。使用 FRAGMENT_NAME 的完全限定的集合名称(例如,kubernetes.core.k8s_auth_options
)。
模块应该只使用来自文档片段的项目,如果模块将以与导入该片段的现有模块相同的方式实现那里记录的所有接口。目标是,从文档片段导入的项目在用于导入该文档片段的另一个模块时,其行为应该相同。
默认情况下,只有文档片段中的 DOCUMENTATION
属性会被插入到模块文档中。可以定义文档片段中的其他属性,以便仅导入文档片段的某些部分,或根据需要进行混合和匹配。如果属性在文档片段和模块中都定义,则模块值将覆盖文档片段。
这是一个名为 example_fragment.py
的示例文档片段
class ModuleDocFragment(object):
# Standard documentation
DOCUMENTATION = r'''
options:
# options here
'''
# Additional section
OTHER = r'''
options:
# other options here
'''
要插入 OTHER
的内容到模块中
extends_documentation_fragment: example_fragment.other
或者同时使用两者
extends_documentation_fragment:
- example_fragment
- example_fragment.other
版本 2.8 中新增功能。
从 Ansible 2.8 开始,您可以使用 doc_fragments
目录(与 play 或 role 相邻,就像任何其他插件一样)来提供用户提供的 doc_fragments。
例如,所有 AWS 模块应该包含
extends_documentation_fragment:
- aws
- ec2
在集合中使用文档片段 描述了如何在集合中加入文档片段。
EXAMPLES 块
在 shebang、UTF-8 编码、版权行、许可证部分和 DOCUMENTATION
块之后,是 EXAMPLES
块。在这里,您向用户展示您的模块如何使用多行纯文本 YAML 格式的真实示例。最好的示例是用户可以复制粘贴到剧本中的示例。在对模块进行任何更改时,请查看并更新您的示例。
根据剧本最佳实践,每个示例都应该包含一个 name:
行
EXAMPLES = r'''
- name: Ensure foo is installed
namespace.collection.modulename:
name: foo
state: present
'''
name:
行应该大写,并且不包含尾随句点。
将完全限定的集合名称 (FQCN) 作为模块名称的一部分,如上面的示例所示。对于 ansible-core
中的模块,请使用 ansible.builtin.
标识符,例如 ansible.builtin.debug
。
如果您的示例使用布尔选项,请使用 yes/no 值。由于文档将布尔值生成 yes/no,因此在示例中也使用这些值,可以使模块文档更加一致。
如果您的模块返回通常需要的 facts,那么如何使用它们的示例将非常有用。
RETURN 块
在 shebang、UTF-8 编码、版权行、许可证部分、DOCUMENTATION
和 EXAMPLES
块之后,是 RETURN
块。本节记录了模块返回的信息,供其他模块使用。
如果您的模块不返回任何内容(除了标准返回值),则模块的此节应为:RETURN = r''' # '''
否则,对于返回的每个值,请提供以下字段。所有字段都是必需的,除非另有说明。
- return name:
返回字段的名称。
- description:
此值代表内容的详细描述。大写,并包含尾随句点。
- returned:
此值返回时,例如
always
、changed
或success
。这是一个字符串,可以包含任何人类可读的内容。- type:
数据类型。
- elements:
如果
type='list'
,则指定列表元素的数据类型。- sample:
一个或多个示例。
- version_added:
仅在最初的 Ansible 版本发布后扩展了此返回值时才需要,换句话说,它大于顶层的
version_added
字段。这是一个字符串,而不是浮点数,例如,version_added: '2.3'
。- contains:
可选。要描述嵌套返回值,请设置
type: dict
,或type: list
/elements: dict
,或者如果您真的需要,type: complex
,并为每个子字段重复上面的元素。
以下是两个 RETURN
部分示例,一个具有三个简单字段,另一个具有复杂的嵌套字段
RETURN = r'''
dest:
description: Destination file/path.
returned: success
type: str
sample: /path/to/file.txt
src:
description: Source file used for the copy on the target machine.
returned: changed
type: str
sample: /home/httpd/.ansible/tmp/ansible-tmp-1423796390.97-147729857856000/source
md5sum:
description: MD5 checksum of the file after running copy.
returned: when supported
type: str
sample: 2a5aeecc61dc98c4d780b14b330e3282
'''
RETURN = r'''
packages:
description: Information about package requirements.
returned: success
type: dict
contains:
missing:
description: Packages that are missing from the system.
returned: success
type: list
elements: str
sample:
- libmysqlclient-dev
- libxml2-dev
badversion:
description: Packages that are installed but at bad versions.
returned: success
type: list
elements: dict
sample:
- package: libxml2-dev
version: 2.9.4+dfsg1-2
constraint: ">= 3.0"
'''
Python 导入
在 shebang、UTF-8 编码、版权行、许可证以及 DOCUMENTATION
、EXAMPLES
和 RETURN
部分之后,您终于可以添加 Python 导入。所有模块都必须使用以下形式的 Python 导入
from module_utils.basic import AnsibleModule
不再允许使用“通配符”导入,例如 from module_utils.basic import *
。
测试模块文档
要在本地测试 Ansible 文档,请遵循说明。要测试集合中的文档,请参见 使用 antsibull-docs 构建 docsite。