Ansible无法从stdout_lines将字符串转换为字典

时间:2019-07-26 10:10:14

标签: ansible

我正在尝试从字典中获取“计数”值

“ {\” _ id \“:ObjectId(\” 5d3a1643c43c898d01a3c740 \“),\” count \“:2}”

出现在ansible stdout_lines的最后一个元素上。

TASK [version_update : debug] ******************************************************************************************************************************************
ok: [192.168.27.125] => {
    "count_info.stdout": "MongoDB shell version v4.0.6\nconnecting to: mongodb://127.0.0.1:27017/configure-db?gssapiServiceName=mongodb\nImplicit session: session { \"id\" : UUID(\"4bfad3ba-981f-47de-86f9-a1fadbe28e12\") }\nMongoDB server version: 4.0.6\n{ \"_id\" : ObjectId(\"5d3a1643c43c898d01a3c740\"), \"count\" : 2 }"
}

TASK [version_update : debug] ******************************************************************************************************************************************
ok: [192.168.27.125] => {
    "count_info.stdout_lines": [
        "MongoDB shell version v4.0.6",
        "connecting to: mongodb://127.0.0.1:27017/configure-db?gssapiServiceName=mongodb",
        "Implicit session: session { \"id\" : UUID(\"4bfad3ba-981f-47de-86f9-a1fadbe28e12\") }",
        "MongoDB server version: 4.0.6",
        "{ \"_id\" : ObjectId(\"5d3a1643c43c898d01a3c740\"), \"count\" : 2 }"
    ]
}

我尝试了以下两种方法,但没有成功。

- debug:
    msg: "{{ (count_info.stdout_lines[-1] | from_json).count }}"

- name: count value
  debug:
    msg: "{{ count_info.stdout_lines[-1] | json_query('count') }}"

错误日志:

TASK [version_update : debug] ******************************************************************************************************************************************
fatal: [192.168.27.125]: FAILED! => {"msg": "the field 'args' has an invalid value ({u'msg': u'{{ (count_info.stdout_lines[-1] | from_json).count }}'}), and could not be converted to an dict.The error was: No JSON object could be decoded\n\nThe error appears to have been in '/home/admin/playbook-3/roles/version_update/tasks/version_update.yml': line 73, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- debug:\n  ^ here\n"}
        to retry, use: --limit @/home/admin/playbook-3/version_update.retry

TASK [version_update : count value] ************************************************************************************************************************************
ok: [192.168.27.125] => {
    "msg": ""
}

2 个答案:

答案 0 :(得分:0)

输出中的最后一行不是纯json字符串(可能是bson from a your MongoDB output)。您收到的错误实际上是由于过滤器本身未获得正确的输入而导致的。

在使用from_json过滤器之前,您必须将其转换为纯json。有问题的数据是ObjectId(\"5d3a1643c43c898d01a3c740\"),无法由过滤器反序列化。这应该在用于注册变量的任务/命令中更改。您可以在this interesting question上找到有关该主题的许多答案,这些答案可能会为您提供一些线索。

一旦完成,访问数据就变得很容易了,就像您已经知道的那样。这是一个示例,其示例数据经过修改(我认为您应该最终得到它),只是为了确认您在正确的位置上。

- name: Get count in json serialized string
  hosts: localhost
  gather_facts: false

  vars:
    "count_info":
      "stdout_lines": [
        "MongoDB shell version v4.0.6",
        "connecting to: mongodb://127.0.0.1:27017/configure-db?gssapiServiceName=mongodb",
        "Implicit session: session { \"id\" : UUID(\"4bfad3ba-981f-47de-86f9-a1fadbe28e12\") }",
        "MongoDB server version: 4.0.6",
        "{ \"_id\" : \"someDeserializedId\", \"count\" : 2 }"
      ]

  tasks:
    - name: Get count
      debug:
        msg: "{{ (count_info.stdout_lines[-1] | from_json).count }}"

结果

PLAY [Get count in json serialized string] ********************************************************************************************************************************************************************************

TASK [Get count] **********************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "2"
}

答案 1 :(得分:0)

尽管该元素具有字典的结构,但实际上它是一个字符串,我无法使用to_jsonto_nice_json对其进行过滤以将其转换为字典。

使用以下任务序列将获得您想要获取的值,不幸的是,我没有找到一种在一项任务中做到这一点的方法。逻辑如下:

  1. 从列表中获取最后一个元素,并将字符串拆分为键值子字符串,并用,分隔。

  2. 分析此列表并找到包含关键字count的元素(如果您认为count也可能出现在其他行中,则可以在此处进行增强)。然后使用正则表达式从中获取数值。

PB:

---
- hosts: localhost
  gather_facts: false
  vars:
    final_count_value: -1
    count_info:
      stdout_lines:
      - MongoDB shell version v4.0.6
      - 'connecting to: mongodb://127.0.0.1:27017/configure-db?gssapiServiceName=mongodb'
      - 'Implicit session: session { "id" : UUID("4bfad3ba-981f-47de-86f9-a1fadbe28e12")
        }'
      - 'MongoDB server version: 4.0.6'
      - '{ "_id" : ObjectId("5d3a1643c43c898d01a3c740"), "count" : 2 }'

  tasks:
    - name: prepare list var
      set_fact:
        temp_list: "{{ (count_info.stdout_lines | last).split(', ') | list }}"

    - name: find count
      set_fact: 
        final_count_value: "{{ item | regex_replace('\"count\" : ', '') | regex_replace(' }', '') }}"
      when: item is search('count')
      with_items:
      - "{{ temp_list }}"

    - name: print result
      debug:
        var: final_count_value

输出:

PLAY [localhost] *******************************************************************************************************************************************************************************************************

TASK [prepare list var] ************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [find count] ******************************************************************************************************************************************************************************************************
skipping: [localhost] => (item={ "_id" : ObjectId("5d3a1643c43c898d01a3c740")) 
ok: [localhost] => (item="count" : 2 })

TASK [print result] ****************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "final_count_value": "2"
}

更新

要从结果中减去1,应使用:

- name: find count and subtract 1
  set_fact: 
    final_count_value: "{{ item | regex_replace('\"count\" : ', '') | regex_replace(' }', '') | int - 1 }}"
  when: item is search('count')
  with_items:
  - "{{ temp_list }}"

希望有帮助!