在Ansible

时间:2019-05-27 09:46:45

标签: json loops ansible

如果键的值与变量(字符串)匹配,我将无法获得特定的json对象。

我的json文件如下:

    "totalRecordsWithoutPaging": 1234,
    "jobs": [
        {
            "jobSummary": {

                "totalNumOfFiles": 0,
                "jobId": 8035,
                "destClientName": "BOSDEKARLSSP010",
                "destinationClient": {
                    "clientId": 10,
                    "clientName": "BOSDEKARLSSP010"
                }
            }
        },
        {
            "jobSummary": {
                "totalNumOfFiles": 0,
                "jobId": 9629,
                "destClientName": "BOSDEKARLSSP006",
                "destinationClient": {
                    "clientId": 11,
                    "clientName": "BOSDEKARLSSP006"
                }
            }
        },
                .....
    ]
}

我用result: "{{ lookup('file','CVExport-short.json') | from_json }}"读取了这个json,使用以下代码只能得到destClientName键的一个值:

- name: Iterate JSON
  set_fact:
    app_item: "{{ item.jobSummary }}"
  with_items: "{{ result.jobs }}"
  register: app_result

- debug:
    var: app_result.results[0].ansible_facts.app_item.destClientName

我的目标是如果jobId的值与任何destClientName中的其他变量或字符串匹配,则获取jobSummary的值。 我对Ansible的了解还不多。因此,我们将不胜感激。

更新

好的,我找到了一个解决方案。

- name: get job ID
  set_fact: 
    job_id: "{{ item.jobSummary.jobId }}"
  with_items: "{{ result.jobs}}"
  when: item.jobSummary.destClientName == '{{ target_vm }}'

- debug: 
    msg: "{{job_id}}"

但是我认为可能有比这更好的解决方案。知道如何吗?

1 个答案:

答案 0 :(得分:2)

Ansible的json_query过滤器使您可以通过应用JMESPath表达式对JSON文档进行复杂的过滤。无需遍历结果中的作业,您只需一步即可获取所需的信息。

我们要查询所有destClientNametarget_vm中的值匹配的作业。使用文字值,产生该作业列表的表达式如下所示:

jobs[?jobSummary.destClientName == `BOSDEKARLSSP006`]

将其应用于样本数据的结果将是:

[
  {
    "jobSummary": {
      "totalNumOfFiles": 0,
      "jobId": 9629,
      "destClientName": "BOSDEKARLSSP006",
      "destinationClient": {
        "clientId": 11,
        "clientName": "BOSDEKARLSSP006"
      }
    }
  }
]

您要从此结果中提取jobId,因此我们将表达式重写为:

jobs[?jobSummary.destClientName == `BOSDEKARLSSP006`]|[0].jobSummary.jobId

哪个给了我们

9629

要在剧本中使用此功能,您需要使用target_vm变量的值替换此表达式中的文字主机名。这是一本完整的剧本,演示了解决方案:

---
- hosts: localhost
  gather_facts: false

  # This is just the sample data from your question.
  vars:
    target_vm: BOSDEKARLSSP006
    results:
      totalRecordsWithoutPaging: 1234
      jobs:
      - jobSummary:
          totalNumOfFiles: 0
          jobId: 8035
          destClientName: BOSDEKARLSSP010
          destinationClient:
            clientId: 10
            clientName: BOSDEKARLSSP010
      - jobSummary:
          totalNumOfFiles: 0
          jobId: 9629
          destClientName: BOSDEKARLSSP006
          destinationClient:
            clientId: 11
            clientName: BOSDEKARLSSP006

  tasks:
    - name: get job ID
      set_fact:
        job_id: "{{ results|json_query('jobs[?jobSummary.destClientName == `{}`]|[0].jobSummary.jobId'.format(target_vm)) }}"

    - debug:
        var: job_id

更新回复:您的评论

表达式中的{}是Python字符串格式化序列, 通过调用.format(target_vm)来填充。在Python中, 表达式:

'The quick brown {} jumped over the lazy {}.'.format('fox', 'dog')

将评估为:

The quick brown fox jumped over the lazy dog.

这正是我们在set_fact表达式中所做的事情。一世 可以这样写:

job_id: "{{ results|json_query('jobs[?jobSummary.destClientName == `' ~ target_vm ~ '`]|[0].jobSummary.jobId') }}"

(其中~是Jinja字符串连接操作符)