将角色迁移到 Galaxy 上集合中的角色
您可以将任何现有的独立角色迁移到集合中,并将该集合托管在 Galaxy 上。使用 Ansible 集合,您可以在一个可重用自动化的单一、凝聚的单元中分发多个角色。在一个集合内,您可以跨集合中的所有角色共享自定义插件,而不是在每个角色的 library/`
目录中重复它们。
如果您想将角色作为经过认证的 Ansible 内容进行分发,则必须将角色迁移到集合。
注意
如果您想将您的集合导入 Galaxy,则需要一个 Galaxy 命名空间.
有关集合的详细信息,请参阅 开发集合.
比较独立角色和集合角色
独立角色 具有以下目录结构
role/
├── defaults
├── files
├── handlers
├── library
├── meta
├── module_utils
├── [*_plugins]
├── tasks
├── templates
├── tests
└── vars
当您迁移到基于集合的角色时,上面突出显示的目录将发生变化。集合目录结构包含一个 roles/
目录
mynamespace/
└── mycollection/
├── docs/
├── galaxy.yml
├── plugins/
│ ├── modules/
│ │ └── module1.py
│ ├── inventory/
│ └── .../
├── README.md
├── roles/
│ ├── role1/
│ ├── role2/
│ └── .../
├── playbooks/
│ ├── files/
│ ├── vars/
│ ├── templates/
│ └── tasks/
└── tests/
将角色迁移到集合后,您需要使用完全限定的集合名称 (FQCN) 来使用角色和插件。FQCN 是集合 namespace
、集合 name
和您引用的内容项的组合。
例如,在上面的集合中,访问 role1
的 FQCN 为
mynamespace.mycollection.role1
一个集合可以在 roles/
目录中包含一个或多个角色,这些角色几乎与独立角色相同,只是您需要将插件移出各个角色,并在某些地方使用 FQCN,如下一节所述。
注意
在独立角色中,一些插件目录以复数形式引用了它们的插件类型;在集合中并非如此。
将角色迁移到集合
要从不包含插件的独立角色迁移到集合角色
创建一个本地
ansible_collections
目录,并cd
到这个新目录。创建一个集合。如果您想将此集合导入 Ansible Galaxy,则需要一个 Galaxy 命名空间.
$ ansible-galaxy collection init mynamespace.mycollection
这将创建集合目录结构。
将独立角色目录复制到集合的
roles/
子目录中。集合中的角色在角色名称中不能包含连字符。将所有此类角色重命名为使用下划线代替。
$ mkdir mynamespace/mycollection/roles/my_role/
$ cp -r /path/to/standalone/role/mynamespace/my_role/\* mynamespace/mycollection/roles/my_role/
更新
galaxy.yml
以包含任何角色依赖项。更新集合 README.md 文件以添加指向任何角色 README.md 文件的链接。
将包含插件的角色迁移到集合
要从包含插件的独立角色迁移到集合角色
创建一个本地
ansible_collections directory
并cd
到这个新目录。创建一个集合。如果您想将此集合导入 Ansible Galaxy,则需要一个 Galaxy 命名空间.
$ ansible-galaxy collection init mynamespace.mycollection
这将创建集合目录结构。
将独立角色目录复制到集合的
roles/
子目录中。集合中的角色在角色名称中不能包含连字符。将所有此类角色重命名为使用下划线代替。
$ mkdir mynamespace/mycollection/roles/my_role/
$ cp -r /path/to/standalone/role/mynamespace/my_role/\* mynamespace/mycollection/roles/my_role/
将所有模块移到
plugins/modules/
目录。
$ mv -r mynamespace/mycollection/roles/my_role/library/\* mynamespace/mycollection/plugins/modules/
将所有其他插件移到相应的
plugins/PLUGINTYPE/
目录。有关可能需要的其他步骤,请参阅 将其他角色插件迁移到集合.更新
galaxy.yml
以包含任何角色依赖项。更新集合 README.md 文件以添加指向任何角色 README.md 文件的链接。
更改对角色的任何引用,以使用 FQCN.
---
- name: example role by FQCN
hosts: some_host_pattern
tasks:
- name: import FQCN role from a collection
import_role:
name: mynamespace.mycollection.my_role
您可以选择使用 collections
关键字来简化此操作
---
- name: example role by FQCN
hosts: some_host_pattern
collections:
- mynamespace.mycollection
tasks:
- name: import role from a collection
import_role:
name: my_role
将其他角色插件迁移到集合
要将其他角色插件迁移到集合
将每个非模块插件移到相应的
plugins/PLUGINTYPE/
目录。该mynamespace/mycollection/plugins/README.md
文件解释了集合可以在可选创建的子目录中包含的插件类型。
$ mv -r mynamespace/mycollection/roles/my_role/filter_plugins/\* mynamespace/mycollection/plugins/filter/
更新文档以使用 FQCN。使用
doc_fragments
的插件需要使用 FQCN(例如,mydocfrag
变为mynamespace.mycollection.mydocfrag
)。更新集合中的相对导入以从句点开始。例如,
./filename
和../asdfu/filestuff
可以工作,但filename
在同一个目录中必须更新为./filename
。
如果您有自定义 module_utils
或从 __init__.py
导入,您还必须
更改自定义
module_utils
的 Python 命名空间以使用 FQCN 以及ansible_collections
约定。有关更多详细信息,请参阅 更新 module_utils.更改从
__init__.py
导入的方式。有关更多详细信息,请参阅 从 __init__.py 导入.
更新 module_utils
如果您的任何自定义模块使用自定义模块实用程序,那么迁移到集合后,您就无法在顶层 ansible.module_utils
Python 命名空间中引用该模块实用程序。Ansible 不会将集合中的内容合并到 Ansible 内部 Python 命名空间中。将自定义内容迁移到集合时,更新引用自定义模块实用程序的任何 Python 导入语句。有关更多详细信息,请参阅 集合中的 module_utils.
在集合中使用 module_utils
进行编码时,Python 导入语句需要考虑 FQCN 以及 ansible_collections
约定。生成的 Python 导入类似于以下示例
from ansible_collections.{namespace}.{collectionname}.plugins.module_utils.{util} import {something}
注意
您需要遵循相同的规则来更改路径并使用子类插件的命名空间名称。
以下示例代码片段显示了使用默认 Ansible module_utils
和集合提供的 module_utils
的 Python 和 PowerShell 模块。在此示例中,命名空间为 ansible_example
,集合为 community
。
在 Python 示例中,module_utils
是 helper
,FQCN 是 ansible_example.community.plugins.module_utils.helper
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible_collections.ansible_example.community.plugins.module_utils.helper import HelperRequest
argspec = dict(
name=dict(required=True, type='str'),
state=dict(choices=['present', 'absent'], required=True),
)
module = AnsibleModule(
argument_spec=argspec,
supports_check_mode=True
)
_request = HelperRequest(
module,
headers={"Content-Type": "application/json"},
data=data
)
在 PowerShell 示例中,module_utils
是 hyperv
,FQCN 是 ansible_example.community.plugins.module_utils.hyperv
#!powershell
#AnsibleRequires -CSharpUtil Ansible.Basic
#AnsibleRequires -PowerShell ansible_collections.ansible_example.community.plugins.module_utils.hyperv
$spec = @{
name = @{ required = $true; type = "str" }
state = @{ required = $true; choices = @("present", "absent") }
}
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
Invoke-HyperVFunction -Name $module.Params.name
$module.ExitJson()
从 __init__.py 中导入
由于 CPython 解释器导入的方式以及 Ansible 插件加载器的工作方式,如果您的自定义嵌入式模块或插件需要从 __init__.py
文件中导入某些内容,那么它也会成为您集合的一部分。您可以将内容起源于独立角色,或在 Python 导入语句中使用文件名。以下示例是 __init__.py
文件,它是名为 ansible_example.community
的集合中找到的回调插件的一部分。
from ansible_collections.ansible_example.community.plugins.callback.__init__ import CustomBaseClass
示例:将带有插件的独立角色迁移到集合
在这个例子中,我们有一个名为 my-standalone-role.webapp
的独立角色,用于模拟包含名称中带破折号的独立角色(这在集合中无效)。这个独立角色包含一个名为 manage_webserver
的自定义模块,位于 library/
目录中。
my-standalone-role.webapp
├── defaults
├── files
├── handlers
├── library
├── meta
├── tasks
├── templates
├── tests
└── vars
创建一个新的集合,例如
acme.webserver
$ ansible-galaxy collection init acme.webserver
- Collection acme.webserver was created successfully
$ tree acme -d 1
acme
└── webserver
├── docs
├── plugins
└── roles
在集合内创建
webapp
角色,并将独立角色的所有内容复制到其中
$ mkdir acme/webserver/roles/webapp
$ cp my-standalone-role.webapp/* acme/webserver/roles/webapp/
将
manage_webserver
模块移动到它在acme/webserver/plugins/modules/
中的新位置
$ cp my-standalone-role.webapp/library/manage_webserver.py acme/webserver/plugins/modules/manage.py
注意
这个例子将原始源文件 manage_webserver.py
更改为目标文件 manage.py
。这是可选的,但 FQCN 提供了 webserver
上下文,作为 acme.webserver.manage
。
在角色中的
tasks/
文件(例如my-standalone-role.webapp/tasks/main.yml
)中,将manage_webserver
更改为acme.webserver.manage
,以及对原始模块名称的任何使用。
注意
此名称更改仅在您更改原始模块名称时才需要,但说明了 FQCN 引用的内容可以提供上下文,进而可以使模块和插件名称更短。如果您预计在独立于角色的情况下使用这些模块,请保留原始命名约定。用户可以在他们的剧本中添加 集合关键字。通常角色是一个抽象层,用户不会独立使用角色的组件。
示例:在后端 RPM 中支持独立角色和迁移后的集合角色
独立角色可以与它的集合角色对应物共存(例如,作为产品支持生命周期的一部分)。这应该只在过渡时期进行,但这两者可以在后端软件包(如 RPM)中存在。例如,RHEL 系统角色可以与 RHEL 系统角色集合示例 共存,并提供与后端 RPM 的向后兼容性。
本节将逐步介绍在后端 RPM 中创建这种共存的示例,这需要 Ansible 2.9.0 或更高版本。
要将角色同时作为独立角色和集合角色进行交付
将集合放在
/usr/share/ansible/collections/ansible_collections/
中。将集合内角色的内容复制到以独立角色命名的目录中,并将独立角色放在
/usr/share/ansible/roles/
中。
独立角色中先前捆绑的所有模块和插件现在都由 FQCN 引用,因此即使它们不再嵌入,也可以从集合内容中找到它们。这是一个示例,说明集合中的内容是一个独特的实体,不必绑定到角色或其他任何内容。您也可以创建两个独立的集合:一个用于模块和插件,另一个用于要迁移的独立角色。该角色必须使用模块和插件作为 FQCN。
以下是一个使用此示例内容完成此操作的 RPM 规范文件示例
Name: acme-ansible-content
Summary: Ansible Collection for deploying and configuring ACME webapp
Version: 1.0.0
Release: 1%{?dist}
License: GPLv3+
Source0: acme-webserver-1.0.0.tar.gz
Url: https://github.com/acme/webserver-ansible-collection
BuildArch: noarch
%global roleprefix my-standalone-role.
%global collection_namespace acme
%global collection_name webserver
%global collection_dir %{_datadir}/ansible/collections/ansible_collections/%{collection_namespace}/%{collection_name}
%description
Ansible Collection and standalone role (for backward compatibility and migration) to deploy, configure, and manage the ACME webapp software.
%prep
%setup -qc
%build
%install
mkdir -p %{buildroot}/%{collection_dir}
cp -r ./* %{buildroot}/%{collection_dir}/
mkdir -p %{buildroot}/%{_datadir}/ansible/roles
for role in %{buildroot}/%{collection_dir}/roles/*
do
cp -pR ${role} %{buildroot}/%{_datadir}/ansible/roles/%{roleprefix}$(basename ${role})
mkdir -p %{buildroot}/%{_pkgdocdir}/$(basename ${role})
for docfile in README.md COPYING LICENSE
do
if [ -f ${role}/${docfile} ]
then
cp -p ${role}/${docfile} %{buildroot}/%{_pkgdocdir}/$(basename ${role})/${docfile}
fi
done
done
%files
%dir %{_datadir}/ansible
%dir %{_datadir}/ansible/roles
%dir %{_datadir}/ansible/collections
%dir %{_datadir}/ansible/collections/ansible_collections
%{_datadir}/ansible/roles/
%doc %{_pkgdocdir}/*/README.md
%doc %{_datadir}/ansible/roles/%{roleprefix}*/README.md
%{collection_dir}
%doc %{collection_dir}/roles/*/README.md
%license %{_pkgdocdir}/*/COPYING
%license %{_pkgdocdir}/*/LICENSE
使用 ansible.legacy
从基于集合的角色访问本地自定义模块
集合中的一些角色使用 本地自定义模块,这些模块本身并不属于集合。如果自定义模块简称与集合模块名称之间存在冲突,则需要指定任务调用的模块。您可以更新任务,将 local_module_name
更改为 ansible.legacy.local_module_name
,以确保您使用的是自定义模块。