从Ansible中的字典中提取数据。

huangapple go评论62阅读模式
英文:

Extract data from dict in Ansible

问题

我仍然在尝试提取Ansible中的数据方面遇到困难。

我有以下清单:

---
all:
  children:
    vms:
      hosts:
        vm1:
          services:
          - exim
          - apache
        vm2:
          services:
          - exim
          - nginx
        vm2:
          services:
          - exim
          - nginx

我定义了以下变量:

services_parameters:
  nginx:
    log_files:
      - /var/log/nginx/*.log
    fail2ban_rules:
      nginx-limit-req:
      nginx-http-auth:
      nginx-botsearch:
      nginx-bad-request:
  exim:
    log_files:
      - /var/log/exim4/mainlog
    fail2ban_rules:
      exim:
      exim-spam:
  apache:
    log_files:
      - /var/log/apache2/*.log
    fail2ban_rules:
      apache-botsearch:
      apache-auth:
        parameters:
          logpath: /var/log/apache2/*.log
          findtime: 3600
          bantime: 86400
          maxretry: 3
      apache-badbots:

使用以下代码,我自豪地设定了一个事实:

ok: [vm1] => {
    "fail2ban_rules": {
        "apache-auth": {
            "parameters": {
                "logpath": "/var/log/apache2/*.log"
            }
        },
        "apache-badbots": null,
        "apache-botsearch": null,
        "exim": null,
        "exim-spam": null
    }
}
ok: [vm2] => {
    "fail2ban_rules": {
        "exim": null,
        "exim-spam": null,
        "nginx-bad-request": null,
        "nginx-botsearch": null,
        "nginx-http-auth": null,
        "nginx-limit-req": null
    }
}
ok: [vm3] => {
    "fail2ban_rules": {
        "exim": null,
        "exim-spam": null,
        "nginx-bad-request": null,
        "nginx-botsearch": null,
        "nginx-http-auth": null,
        "nginx-limit-req": null
    }
}

现在我努力获取每个主机上与附加服务关联的所有日志文件,类似以下(手动编写,可能包含一些拼写错误):

ok: [vm1] => [
      {"exim": ["/var/log/exim4/mainlog"]},
      {"apache": ["/var/log/apache2/*.log"]}
]
ok: [vm2] => [
      {"exim": ["/var/log/exim4/mainlog"]},
      {"nginx": ["/var/log/nginx/*.log"]}
]
ok: [vm3] => [
      {"exim": ["/var/log/exim4/mainlog"]},
      {"nginx": ["/var/log/nginx/*.log"]}
]

有了这个事实,我将循环遍历服务以生成类似以下的块:

nginx:
  paths:
    - /var/log/nginx/*.log
    - <如果在services_parameters变量中定义,则还有其他路径>

这可能有一个变通方法,但这是我自从使用Ansible以来一直面临的痛苦数据处理的一个很好的示例。

英文:

I'm still struggling with extracting data in Ansible.

I have the following inventory:

---
all:
  children:
vms:
  hosts:
    vm1:
      services:
      - exim
      - apache
    vm2:
      services:
      - exim
      - nginx
    vm2:
      services:
      - exim
      - nginx

I defined the following variable:

services_parameters:
  nginx:
    log_files:
      - /var/log/nginx/*.log
    fail2ban_rules:
      nginx-limit-req:
      nginx-http-auth:
      nginx-botsearch:
      nginx-bad-request:
  exim:
    log_files:
      - /var/log/exim4/mainlog
    fail2ban_rules:
      exim:
      exim-spam:
  apache:
    log_files:
      - /var/log/apache2/*.log
    fail2ban_rules:
      apache-botsearch:
      apache-auth:
        parameters:
          logpath: /var/log/apache2/*.log
          findtime: 3600
          bantime: 86400
          maxretry: 3
      apache-badbots:

With

&quot;{{ hostvars[inventory_hostname].services | map(&#39;extract&#39;, services_parameters, &#39;fail2ban_rules&#39;) | combine }}&quot;

I proudly managed to set a fact:

ok: [vm1] =&gt; {
    &quot;fail2ban_rules&quot;: {
        &quot;apache-auth&quot;: {
            &quot;parameters&quot;: {
                &quot;logpath&quot;: &quot;/var/log/apache2/*.log&quot;
            }
        },
        &quot;apache-badbots&quot;: null,
        &quot;apache-botsearch&quot;: null,
        &quot;exim&quot;: null,
        &quot;exim-spam&quot;: null
    }
}
ok: [vm2] =&gt; {
    &quot;fail2ban_rules&quot;: {
        &quot;exim&quot;: null,
        &quot;exim-spam&quot;: null,
        &quot;nginx-bad-request&quot;: null,
        &quot;nginx-botsearch&quot;: null,
        &quot;nginx-http-auth&quot;: null,
        &quot;nginx-limit-req&quot;: null
    }
}
ok: [vm3] =&gt; {
    &quot;fail2ban_rules&quot;: {
        &quot;exim&quot;: null,
        &quot;exim-spam&quot;: null,
        &quot;nginx-bad-request&quot;: null,
        &quot;nginx-botsearch&quot;: null,
        &quot;nginx-http-auth&quot;: null,
        &quot;nginx-limit-req&quot;: null
    }
}

So I can loop over to generate fail2ban rules.

Now I struggle to get all log_files to follow on each host, associated with the attached service, something like (manually written, may contain some typos):

ok: [vm1] =&gt; [
      {&quot;exim&quot;: [
	    &quot;/var/log/exim4/mainlog&quot;
	    ]
      },
      {&quot;apache&quot;: [
	    &quot;/var/log/apache2/*.log&quot;
	    ]
      }
]
ok: [vm2] =&gt; [
      {&quot;exim&quot;: [
	    &quot;/var/log/exim4/mainlog&quot;
	    ]
      },
      {&quot;nginx&quot;: [
	    &quot;/var/log/nginx/*.log&quot;
	    ]
      }
]
ok: [vm3] =&gt; [
      {&quot;exim&quot;: [
	    &quot;/var/log/exim4/mainlog&quot;
	    ]
      },
      {&quot;nginx&quot;: [
	    &quot;/var/log/nginx/*.log&quot;
	    ]
      }
]

With this fact I will loop over the services to generate block like:

nginx:
  paths:
    - /var/log/nginx/*.log
    - &lt;other paths if defined in services_parameters variable&gt;

There is probably a workaround, but this is a good example of the recurrent painful data manipulation I face since using Ansible.

答案1

得分: 1

以下是翻译好的部分:

---
- 名称: 调试每个主机的服务参数
  主机: vms
  收集事实: false

  变量:
    服务列表: >-
      {{
        services_parameters
        | dict2items(key_name='service_name', value_name='service_parameters')
        | selectattr('service_name', 'in', services)
      }}      

  任务:
    - 名称: 显示每个目标服务器的服务列表
      ansible.builtin.debug:
        var: services_list

    - 名称: 循环遍历每个目标的合并的fail2ban规则列表
      ansible.builtin.debug:
        var: item
      loop: "{{ services_list | map(attribute='service_parameters.fail2ban_rules') | combine | dict2items }}"
      loop_control:
        label: "{{ item.key }}"

    - 名称: 循环遍历每个日志文件,保留相关的服务名称
      ansible.builtin.debug:
        msg: "{{ item.1 }} 是服务 {{ item.0.service_name }} 的日志文件"
      loop: "{{ services_list | subelements('service_parameters.log_files') }}"
      loop_control:
        label: "{{ item.1 }}"

演示运行结果:

$ ansible-playbook -i inventory.yml playbook.yml 

PLAY [Debug service params for each host] *****************************************************************************************************************************************************************

TASK [Show service list for each target server] ***********************************************************************************************************************************************************
ok: [vm1] => {
    "services_list": [
        {
            "service_name": "exim",
            "service_parameters": {
                "fail2ban_rules": {
                    "exim": null,
                    "exim-spam": null
                },
                "log_files": [
                    "/var/log/exim4/mainlog"
                ]
            }
        },
        {
            "service_name": "apache",
            "service_parameters": {
                "fail2ban_rules": {
                    "apache-auth": {
                        "parameters": {
                            "bantime": 86400,
                            "findtime": 3600,
                            "logpath": "/var/log/apache2/*.log",
                            "maxretry": 3
                        }
                    },
                    "apache-badbots": null,
                    "apache-botsearch": null
                },
                "log_files": [
                    "/var/log/apache2/*.log"
                ]
            }
        }
    ]
}
ok: [vm2] => {
    "services_list": [
        {
            "service_name": "nginx",
            "service_parameters": {
                "fail2ban_rules": {
                    "nginx-bad-request": null,
                    "nginx-botsearch": null,
                    "nginx-http-auth": null,
                    "nginx-limit-req": null
                },
                "log_files": [
                    "/var/log/nginx/*.log"
                ]
            }
        },
        {
            "service_name": "exim",
            "service_parameters": {
                "fail2ban_rules": {
                    "exim": null,
                    "exim-spam": null
                },
                "log_files": [
                    "/var/log/exim4/mainlog"
                ]
            }
        }
    ]
}
ok: [vm3] => {
    "services_list": [
        {
            "service_name": "nginx",
            "service_parameters": {
                "fail2ban_rules": {
                    "nginx-bad-request": null,
                    "nginx-botsearch": null,
                    "nginx-http-auth": null,
                    "nginx-limit-req": null
                },
                "log_files": [
                    "/var/log/nginx/*.log"
                ]
            }
        },
        {
            "service_name": "apache",
            "service_parameters": {
                "fail2ban_rules": {
                    "apache-auth": {
                        "parameters": {
                            "bantime": 86400,
                            "findtime": 3600,
                            "logpath": "/var/log/apache2/*.log",
                            "maxretry": 3
                        }
                    },
                    "apache-badbots": null,
                    "apache-botsearch": null
                },
                "log_files": [
                    "/var/log/apache2/*.log"
                ]
            }
        }
    ]
}

TASK [loop over a consolidated list of fail2ban rules for each target] ************************************************************************************************************************************
ok: [vm1] => (item=exim) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "exim",
        "value": null
    }
}
ok: [vm2] => (item=nginx-limit-req) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "nginx-limit-req",
        "value": null
    }
}
ok: [vm1] => (item=exim-spam) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "exim-spam",
        "value": null
    }
}
ok: [vm3] => (item=nginx-limit-req) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "nginx-limit-req",
        "value": null
    }
}
ok: [vm2] => (item=nginx-http-auth) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "nginx-http-auth",
        "value": null
    }
}
ok: [vm1] => (item=apache-botsearch) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "apache-botsearch",
        "value": null
    }
}
ok: [vm3] => (item=nginx-http-auth) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "nginx-http-auth",
        "value": null
    }
}
ok: [vm2] => (item=nginx-botsearch) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "nginx-botsearch",
        "value": null
    }
}
ok: [vm1] => (item=apache-auth) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "apache-auth",
        "value": {
            "parameters": {
                "bantime": 86400,
                "findtime": 3600,
                "logpath": "/var/log/apache2/*.log",
                "maxretry": 3
            }
        }
    }
}
ok: [vm3] => (item=nginx-botsearch) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "nginx-botsearch",
        "value": null
    }
}
ok: [vm1] => (item=apache-badbots) => {
    "ansible_loop_var": "item",
    "item": {
        "key": "apache-badbots",
        "value": null
    }
}
ok: [vm2] => (item=nginx-bad-request) => {
    "ansible_loop_var": "

<details>
<summary>英文:</summary>

Given the following `inventory.yml`
```yaml
---
all:
  vars:
    services_parameters:
      nginx:
        log_files:
          - /var/log/nginx/*.log
        fail2ban_rules:
          nginx-limit-req:
          nginx-http-auth:
          nginx-botsearch:
          nginx-bad-request:
      exim:
        log_files:
          - /var/log/exim4/mainlog
        fail2ban_rules:
          exim:
          exim-spam:
      apache:
        log_files:
          - /var/log/apache2/*.log
        fail2ban_rules:
          apache-botsearch:
          apache-auth:
            parameters:
              logpath: /var/log/apache2/*.log
              findtime: 3600
              bantime: 86400
              maxretry: 3
          apache-badbots:
vms:
  hosts:
    vm1:
      services:
        - exim
        - apache
    vm2:
      services:
        - exim
        - nginx
    vm3:
      services:
        - apache
        - nginx

the following self explanatory playbook.yml contains some data manipulation and possible loops to acheive what you need (from what I understood)

---
- name: Debug service params for each host
  hosts: vms
  gather_facts: false

  vars:
    services_list: &gt;- 
      {{ 
        services_parameters 
        | dict2items(key_name=&#39;service_name&#39;, value_name=&#39;service_parameters&#39;)
        | selectattr(&#39;service_name&#39;, &#39;in&#39;, services)
      }}

  tasks:
    - name: Show service list for each target server
      ansible.builtin.debug:
        var: services_list

    - name: loop over a consolidated list of fail2ban rules for each target
      ansible.builtin.debug:
        var: item
      loop: &quot;{{ services_list | map(attribute=&#39;service_parameters.fail2ban_rules&#39;) | combine | dict2items }}&quot;
      loop_control:
        label: &quot;{{ item.key }}&quot;

    - name: loop over each log file keeping the relevant service name
      ansible.builtin.debug:
        msg: &quot;{{ item.1 }} is a log file of service {{ item.0.service_name }}&quot;
      loop: &quot;{{ services_list | subelements(&#39;service_parameters.log_files&#39;) }}&quot;
      loop_control:
        label: &quot;{{ item.1 }}&quot;

Demo run

$ ansible-playbook -i inventory.yml playbook.yml 
PLAY [Debug service params for each host] *****************************************************************************************************************************************************************
TASK [Show service list for each target server] ***********************************************************************************************************************************************************
ok: [vm1] =&gt; {
&quot;services_list&quot;: [
{
&quot;service_name&quot;: &quot;exim&quot;,
&quot;service_parameters&quot;: {
&quot;fail2ban_rules&quot;: {
&quot;exim&quot;: null,
&quot;exim-spam&quot;: null
},
&quot;log_files&quot;: [
&quot;/var/log/exim4/mainlog&quot;
]
}
},
{
&quot;service_name&quot;: &quot;apache&quot;,
&quot;service_parameters&quot;: {
&quot;fail2ban_rules&quot;: {
&quot;apache-auth&quot;: {
&quot;parameters&quot;: {
&quot;bantime&quot;: 86400,
&quot;findtime&quot;: 3600,
&quot;logpath&quot;: &quot;/var/log/apache2/*.log&quot;,
&quot;maxretry&quot;: 3
}
},
&quot;apache-badbots&quot;: null,
&quot;apache-botsearch&quot;: null
},
&quot;log_files&quot;: [
&quot;/var/log/apache2/*.log&quot;
]
}
}
]
}
ok: [vm2] =&gt; {
&quot;services_list&quot;: [
{
&quot;service_name&quot;: &quot;nginx&quot;,
&quot;service_parameters&quot;: {
&quot;fail2ban_rules&quot;: {
&quot;nginx-bad-request&quot;: null,
&quot;nginx-botsearch&quot;: null,
&quot;nginx-http-auth&quot;: null,
&quot;nginx-limit-req&quot;: null
},
&quot;log_files&quot;: [
&quot;/var/log/nginx/*.log&quot;
]
}
},
{
&quot;service_name&quot;: &quot;exim&quot;,
&quot;service_parameters&quot;: {
&quot;fail2ban_rules&quot;: {
&quot;exim&quot;: null,
&quot;exim-spam&quot;: null
},
&quot;log_files&quot;: [
&quot;/var/log/exim4/mainlog&quot;
]
}
}
]
}
ok: [vm3] =&gt; {
&quot;services_list&quot;: [
{
&quot;service_name&quot;: &quot;nginx&quot;,
&quot;service_parameters&quot;: {
&quot;fail2ban_rules&quot;: {
&quot;nginx-bad-request&quot;: null,
&quot;nginx-botsearch&quot;: null,
&quot;nginx-http-auth&quot;: null,
&quot;nginx-limit-req&quot;: null
},
&quot;log_files&quot;: [
&quot;/var/log/nginx/*.log&quot;
]
}
},
{
&quot;service_name&quot;: &quot;apache&quot;,
&quot;service_parameters&quot;: {
&quot;fail2ban_rules&quot;: {
&quot;apache-auth&quot;: {
&quot;parameters&quot;: {
&quot;bantime&quot;: 86400,
&quot;findtime&quot;: 3600,
&quot;logpath&quot;: &quot;/var/log/apache2/*.log&quot;,
&quot;maxretry&quot;: 3
}
},
&quot;apache-badbots&quot;: null,
&quot;apache-botsearch&quot;: null
},
&quot;log_files&quot;: [
&quot;/var/log/apache2/*.log&quot;
]
}
}
]
}
TASK [loop over a consolidated list of fail2ban rules for each target] ************************************************************************************************************************************
ok: [vm1] =&gt; (item=exim) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;exim&quot;,
&quot;value&quot;: null
}
}
ok: [vm2] =&gt; (item=nginx-limit-req) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-limit-req&quot;,
&quot;value&quot;: null
}
}
ok: [vm1] =&gt; (item=exim-spam) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;exim-spam&quot;,
&quot;value&quot;: null
}
}
ok: [vm3] =&gt; (item=nginx-limit-req) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-limit-req&quot;,
&quot;value&quot;: null
}
}
ok: [vm2] =&gt; (item=nginx-http-auth) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-http-auth&quot;,
&quot;value&quot;: null
}
}
ok: [vm1] =&gt; (item=apache-botsearch) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;apache-botsearch&quot;,
&quot;value&quot;: null
}
}
ok: [vm3] =&gt; (item=nginx-http-auth) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-http-auth&quot;,
&quot;value&quot;: null
}
}
ok: [vm2] =&gt; (item=nginx-botsearch) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-botsearch&quot;,
&quot;value&quot;: null
}
}
ok: [vm1] =&gt; (item=apache-auth) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;apache-auth&quot;,
&quot;value&quot;: {
&quot;parameters&quot;: {
&quot;bantime&quot;: 86400,
&quot;findtime&quot;: 3600,
&quot;logpath&quot;: &quot;/var/log/apache2/*.log&quot;,
&quot;maxretry&quot;: 3
}
}
}
}
ok: [vm3] =&gt; (item=nginx-botsearch) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-botsearch&quot;,
&quot;value&quot;: null
}
}
ok: [vm1] =&gt; (item=apache-badbots) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;apache-badbots&quot;,
&quot;value&quot;: null
}
}
ok: [vm2] =&gt; (item=nginx-bad-request) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-bad-request&quot;,
&quot;value&quot;: null
}
}
ok: [vm3] =&gt; (item=nginx-bad-request) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;nginx-bad-request&quot;,
&quot;value&quot;: null
}
}
ok: [vm2] =&gt; (item=exim) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;exim&quot;,
&quot;value&quot;: null
}
}
ok: [vm3] =&gt; (item=apache-botsearch) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;apache-botsearch&quot;,
&quot;value&quot;: null
}
}
ok: [vm2] =&gt; (item=exim-spam) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;exim-spam&quot;,
&quot;value&quot;: null
}
}
ok: [vm3] =&gt; (item=apache-auth) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;apache-auth&quot;,
&quot;value&quot;: {
&quot;parameters&quot;: {
&quot;bantime&quot;: 86400,
&quot;findtime&quot;: 3600,
&quot;logpath&quot;: &quot;/var/log/apache2/*.log&quot;,
&quot;maxretry&quot;: 3
}
}
}
}
ok: [vm3] =&gt; (item=apache-badbots) =&gt; {
&quot;ansible_loop_var&quot;: &quot;item&quot;,
&quot;item&quot;: {
&quot;key&quot;: &quot;apache-badbots&quot;,
&quot;value&quot;: null
}
}
TASK [loop over each log file keeping the relevant service name] ******************************************************************************************************************************************
ok: [vm1] =&gt; (item=/var/log/exim4/mainlog) =&gt; {
&quot;msg&quot;: &quot;/var/log/exim4/mainlog is a log file of service exim&quot;
}
ok: [vm2] =&gt; (item=/var/log/nginx/*.log) =&gt; {
&quot;msg&quot;: &quot;/var/log/nginx/*.log is a log file of service nginx&quot;
}
ok: [vm1] =&gt; (item=/var/log/apache2/*.log) =&gt; {
&quot;msg&quot;: &quot;/var/log/apache2/*.log is a log file of service apache&quot;
}
ok: [vm2] =&gt; (item=/var/log/exim4/mainlog) =&gt; {
&quot;msg&quot;: &quot;/var/log/exim4/mainlog is a log file of service exim&quot;
}
ok: [vm3] =&gt; (item=/var/log/nginx/*.log) =&gt; {
&quot;msg&quot;: &quot;/var/log/nginx/*.log is a log file of service nginx&quot;
}
ok: [vm3] =&gt; (item=/var/log/apache2/*.log) =&gt; {
&quot;msg&quot;: &quot;/var/log/apache2/*.log is a log file of service apache&quot;
}
PLAY RECAP ************************************************************************************************************************************************************************************************
vm1                        : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
vm2                        : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
vm3                        : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

huangapple
  • 本文由 发表于 2023年7月20日 21:36:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76730467.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定