我有一个控制 Playbook,它会在运行时从 API 获取组数据。基于这些组,我想动态地将 Play 添加到运行中(使用不同的主机和变量)。
据我了解,“include”模块就是用来干这个的。但是文档说它已经被弃用了。所以现在我想知道:有什么面向未来的方法可以在运行时动态添加 Play?
“include_tasks” 不起作用,因为包含的任务属于同一个 Play,因此将使用相同的 Hosts。
我有一个控制 Playbook,它会在运行时从 API 获取组数据。基于这些组,我想动态地将 Play 添加到运行中(使用不同的主机和变量)。
据我了解,“include”模块就是用来干这个的。但是文档说它已经被弃用了。所以现在我想知道:有什么面向未来的方法可以在运行时动态添加 Play?
“include_tasks” 不起作用,因为包含的任务属于同一个 Play,因此将使用相同的 Hosts。
master
在这种情况下,我正在尝试弄清楚当特定分支的测试失败时如何立即停止我的剧本。
这是我的 Ansible 代码:
- name: 'Run Tests'
shell: testing.sh | tee "testing.log"
register: testing
- name: 'Show log'
debug:
msg: "{{ testing.stdout_lines }}"
- name: 'Set fact'
set_fact:
tests: >-
{{
testing.stdout_lines | join(' ') | regex_findall('(\d+)\s*failed') | map('int') | max == 0
}}
我正在尝试按照以下代码示例中的“名称”字段正确排序列表:
---
- hosts: localhost
vars:
hosts:
- name: host2
uptime: 1d
- name: host10
uptime: 45d
- name: host1
uptime: 3m
tasks:
- name: version sort host list
debug:
#var: hosts | community.general.version_sort
#var: hosts | dictsort(false, 'value')
var: hosts | sort(attribute='name')
如您所见,它没有正确排序主机名(host2 应该排在 host10 之前)。我查了一下 version_sort 过滤器,但它不支持按属性排序。我知道如果主机名正确填充,就不会出现这种情况。但事实就是如此。我搜索了一下,没有看到有人问这个问题。还有其他建议吗?
TASK [version sort host list] *************************************
ok: [localhost] => {
"hosts | sort(attribute='name')": [
{
"name": "host1",
"uptime": "3m"
},
{
"name": "host10", <-------
"uptime": "45d"
},
{
"name": "host2",
"uptime": "1d"
}
]
}
概括:
感谢@Vladimir Botka提供的所有选项!我整合了第三个选项,并制定了以下方案。注意,我更新了字典列表,使其在使用fqdn时稍微复杂一些。但这个方案确实有效:
- hosts: localhost
vars:
hosts:
- {name: host2.example.com, uptime: 1d}
- {name: host10.example.com, uptime: 45d}
- {name: host1.example.com, uptime: 3m}
- {name: host3.example.com, uptime: 3m}
- {name: host15.example.com, uptime: 45d}
- {name: host20.example.com, uptime: 45d}
tasks:
# - debug:
# msg:
# - "index: {{ hosts | map(attribute='name') | community.general.version_sort }}"
# - "host_indexed: {{ dict(hosts|json_query('[].[name,@]')) }}"
# - "solution: {{ (hosts | map(attribute='name') | community.general.version_sort) | map('extract', dict(hosts|json_query('[].[name,@]'))) }}"
- debug:
var: (hosts | map(attribute='name') | community.general.version_sort) | map('extract', dict(hosts|json_query('[].[name,@]')))
结果如下:
PLAY [localhost] *****************************************************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************************************
ok: [localhost]
TASK [debug] *********************************************************************************************************************************************
[WARNING]: Collection community.general does not support Ansible version 2.14.17
ok: [localhost] => {
"(hosts | map(attribute='name') | community.general.version_sort) | map('extract', dict(hosts|json_query('[].[name,@]')))": [
{
"name": "host1.example.com",
"uptime": "3m"
},
{
"name": "host2.example.com",
"uptime": "1d"
},
{
"name": "host3.example.com",
"uptime": "3m"
},
{
"name": "host10.example.com",
"uptime": "45d"
},
{
"name": "host15.example.com",
"uptime": "45d"
},
{
"name": "host20.example.com",
"uptime": "45d"
}
]
}
PLAY RECAP ***********************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
我有一份如下的字典列表:
myvar:
- host: host1
version: 2
- host: host2
version: 5
- host: host3
version: 4
我正在尝试编写一个断言任务,当任何主机的版本 > 3 时该任务就会失败,并且我还希望失败消息包含所有此类主机。例如:
The following hosts have a version greater than 3: host2, host3
最后一部分是关键。我想显示所有未通过检查的主机,而不仅仅是第一个。谢谢。
通过为特定分支创建的 Ansible 任务,symlink
我发现它在创建的 中添加了空格和引号symlink
。
- name: "Symlink to git branch"
file:
src: "{{ repository }}/{{ application }}"
dest: "/path/to/my/{{ symlink_name }}"
state: link
vars:
symlink_name: >-
{% if git_branch == 'development' %}
my-development
{% elif git_branch == 'master' %}
newest
{% elif git_branch == 'hotfix' %}
my-hotfix
{% endif %}
其结果是:
root# ls -lha
' my-development ' -> /path/to/my/symlink
它基于development
分支。我尝试在不同的标志之前和之后添加symlink_name
,但不幸的是没有成功。
我想用 ansible 运行一个 shell 命令,它的格式如下:
command <item_1> <item_2>
并循环处理多个项目,例如:
实现这一目标的最佳方法是什么?
真挚地
我正在使用嵌套字典,并且有多个具有相同键的字典文件。字典和任务本身正在运行,但我需要添加以下条件。如果子元素的状态 == 不存在,则不要运行任务
我的字典:
qualitygate:
- qualitygate_name: QA-dev
operators:
- metric: coverage
operator: CT
error: 1
state: present
- qualitygate_name: Department-xyc
operators:
- metric: coverage
operator: CT
error: 10
state: absent
- metric: duplicated_lines
operator: GT
error: 5
state: present
使用我的任务:
- ansible.builtin.uri:
url: "{{ protocol }}://{{ server_fqdn }}/api/qualitygates/create_condition"
user: "{{ token }}"
method: POST
body_format: form-urlencoded
body:
error: "{{ item.1.error }}"
metric: "{{ item.1.metric }}"
gateName: "{{ item.0.qualitygate_name }}"
op: "{{ item.1.operator }}"
loop: "{{ qualitygate | subelements('operators', 'skip_missing=True') }}"
when: qualitygate[item]['state'] is match("present")
如何更改过滤器以仅匹配“present”值
请告知如何将一个任务的注册数据用作同一剧本中另一个任务的变量。
剧本:
---
- name: RouterOS test with API
hosts: localhost
vars:
hostname: "some_host"
username: "api"
password: "some_password"
gather_subset: all
module_defaults:
group/community.routeros.api:
hostname: "{{ hostname }}"
password: "{{ password }}"
username: "{{ username }}"
tls: true
force_no_cert: false
validate_certs: false
validate_cert_hostname: false
tasks:
- name: Add wg tuns
ignore_errors: true
community.routeros.api:
path: "interface wireguard"
add: "name={{ item.name }} listen-port={{ item.port }} comment={{ item.comment }}"
loop:
- { name: 'wg1', port: '111', comment: 'com1' }
- { name: 'wg2', port: '222', comment: 'com2' }
- { name: 'wg3', port: '333', comment: 'com3' }
- name: Get wg link-local addrs
community.routeros.api:
path: ipv6 address
extended_query:
attributes:
- address
- interface
where:
- attribute: "interface"
is: "=="
value: "{{ item.name }}"
loop:
- { name: 'wg1' }
- { name: 'wg2' }
- { name: 'wg3' }
register: extended_queryout
- name: Dump "Extended query example" output
ansible.builtin.debug:
msg: '{{ extended_queryout }}'
Playbook 正在创建 3 个(通过循环)Wireguard 接口,我需要使用这些接口的本地链接地址作为变量,如wg1.address、wg2.address、wg3.address。现在我只能看到使用以下命令生成的大量输出:
- name: Dump "Extended query example" output
ansible.builtin.debug:
msg: '{{ extended_queryout }}'
像这样:
TASK [Dump "Extended query example" output] ****************************************************************************************************************************************************************
ok: [localhost] => {
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"add": null,
"ca_path": null,
"cmd": null,
"encoding": "ASCII",
"extended_query": {
"attributes": [
"address",
"interface"
],
"where": [
{
"attribute": "interface",
"is": "==",
"or": null,
"value": "wg1"
}
]
},
"force_no_cert": false,
"hostname": "some_host",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"path": "ipv6 address",
"port": null,
"query": null,
"remove": null,
"timeout": 10,
"tls": true,
"update": null,
"username": "api",
"validate_cert_hostname": false,
"validate_certs": false
}
},
"item": {
"name": "wg1"
},
"msg": [
{
"address": "fe80::caa4:e31c:dd63:7598/64",
"interface": "wg1"
}
]
},
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"add": null,
"ca_path": null,
"cmd": null,
"encoding": "ASCII",
"extended_query": {
"attributes": [
"address",
"interface"
],
"where": [
{
"attribute": "interface",
"is": "==",
"or": null,
"value": "wg2"
}
]
},
"force_no_cert": false,
"hostname": "some_host",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"path": "ipv6 address",
"port": null,
"query": null,
"remove": null,
"timeout": 10,
"tls": true,
"update": null,
"username": "api",
"validate_cert_hostname": false,
"validate_certs": false
}
},
"item": {
"name": "wg2"
},
"msg": [
{
"address": "fe80::c0eb:fadb:2da0:50f5/64",
"interface": "wg2"
}
]
},
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"add": null,
"ca_path": null,
"cmd": null,
"encoding": "ASCII",
"extended_query": {
"attributes": [
"address",
"interface"
],
"where": [
{
"attribute": "interface",
"is": "==",
"or": null,
"value": "wg3"
}
]
},
"force_no_cert": false,
"hostname": "some_host",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"path": "ipv6 address",
"port": null,
"query": null,
"remove": null,
"timeout": 10,
"tls": true,
"update": null,
"username": "api",
"validate_cert_hostname": false,
"validate_certs": false
}
},
"item": {
"name": "wg3"
},
"msg": [
{
"address": "fe80::28d1:7b9b:92:ed43/64",
"interface": "wg3"
}
]
}
],
"skipped": false
}
}
如何设置变量 wg1.address 值 fe80::caa4:e31c:dd63:7598/64、变量 wg2.address 值 fe80::c0eb:fadb:2da0:50f5/64 和 wg3.address 值 fe80::28d1:7b9b:92:ed43/64。
先感谢您。
期望看到变量 wg1.address 值 fe80::caa4:e31c:dd63:7598/64、变量 wg2.address 值 fe80::c0eb:fadb:2da0:50f5/64 和 wg3.address 值 fe80::28d1:7b9b:92:ed43/64。
我有一个默认的目标 Linux 节点umask=0077
。当我运行剧本时
- name: Create folder for app
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: app_user
mode: 0755
with_items:
- "/opt/app/folder1/bin"
- "/etc/program/folder2"
参数“mode”仅适用于最后一个文件夹(bin
和folder2
)。根据 umask,所有父目录都具有严格权限。
如何设置父目录所需的权限(不是全部/opt
或/etc
仅针对链):
/opt
,,,,/opt/app
/opt/app/folder1
/opt/app/folder1/bin
/etc
,,/etc/program
/etc/program/folder2
我有2个包含私钥的jinja模板:
private.key
(加密)private-copy.key
(需包含private.key内容)private.key
文件使用 ansible vault 加密,例如
ansible-vault encrypt --vault-password-file ~/.pass.txt private.key
所以它的内容如下所示:
$ANSIBLE_VAULT;1.1;AES256
123456789[...]
我正在尝试获取解密的内容private.key
-----BEGIN RSA PRIVATE KEY-----
ABCDEfgh[...]
-----END RSA PRIVATE KEY-----
里面private-copy.key
(而不是它的加密值)。
我已经尝试过在里面包含 jinja 语句private-copy.key
:
{% include "private.key" %}
但结果给我的是 的加密值private-copy.key
而不是 的解密内容private.key
。
我还知道我可以使用加密变量并将其放入 private-copy.key 中,而不是包含加密文件。为了简单起见,我想直接使用加密文件(在证书更新时,我们得到一个文件,我只是想直接使用它)。