首页 > 解决方案 > 带有 JSON 到 powershell 的 Ansible win_shell,其他方式也可以正常工作

问题描述

我不知道如何让 win_shell 将 JSON 发送到 Windows 服务器上的 powershell 脚本。如果我运行这个:

vm:
  annotation: This is a VM
  cdrom:
    type: client
    iso_path: ''
    controller_type: ''
    state: ''
  cluster: ''
- name: "Run script '.ps1'"
    win_shell: D:\scripts\outputValues.ps1 -vm "{{vm}}"
    register: result
  - name: Process win_shell output
    set_fact:
      fullResult: "{{ result.stdout | from_json }}"

我把这个字符串变成了我什至无法转换为 JSON 的 powershell:

{u'cdrom': {u'controller_type': u'', u'state': u'', u'type': u'client', u'iso_path': u''}, u'cluster': u'', u'annotation': u'This is a VM'}

如果我用这个运行脚本:

win_shell: D:\scripts\outputValues.ps1 -vm "{{vm | to_json}}"

我得到的只是一个打开的大括号'{'进入powershell。

它确实以另一种方式工作。作为测试,如果我从 win_shell 调用相同的 powershell 脚本并忽略 powershell 中的输入并简单地创建一个这样的对象并将其发送回 ansible,它工作正常。为什么我可以以一种方式发送 JSON 而不能以另一种方式发送?我试过 vm|to_json 等。

#Powershell
$vmAttribs = @{"type" = "client"; "iso_path" = ""; "controller_type" =""; "state" =""}
$vmObject = New-Object psobject -Property @{
    annotation = 'This is a VM'
    cdrom = $vmAttribs
    cluster = ""
}
$result = $vmObject | ConvertTo-Json -Depth 8
Write-Output $result

ansible 得到:

{
    "msg": {
        "cdrom": {
            "controller_type": "",
            "state": "",
            "type": "client",
            "iso_path": ""
        },
        "cluster": "",
        "annotation": "This is a VM"
    },
    "changed": false,
    "_ansible_verbose_always": true,
    "_ansible_no_log": false
}

标签: jsonpowershellvariablesansible

解决方案


您所看到的是一个 Python 结构,它使用 Unicode 字符串(例如u'my string value')表示 JSON 符号。显然,这并不能完全移植到Powershell等其他运行时,并且会导致字符串无效。

阅读Ansible 过滤器,您将希望使用它{{ vm | to_json }}来确保将数据结构正确地字符串化为 JSON。

解决方法

我想强调的是,这不是从 Ansible 中获取 JSON 对象的理想方式,并且不涉及从 JSON 字符串中删除 Unicode 标识符的适当解决方案对此是可取的。

我对 Ansible 知之甚少,不知道为什么{在管道vm到时字符串会变成这样to_json,但这里有一个解决方法可以让你继续前进,直到其他人可以在此处插入 Ansible 的过滤所发生的事情。

在您的.ps1脚本中,您可以使用以下内容在字符串之前-replace删除这些u字符:

$vm = $vm -replace "u(?=([`"']).*\1)"

您可以通过在交互式终端中运行以下命令来测试:

"{u'cdrom': {u'controller_type': u'', u'state': u'', u'type': u'client', u'iso_path': u''}, u'cluster': u'', u'annotation': u'This is a VM'}" -replace "u(?=([`"']).*\1)"

该模式匹配u紧接在单引号或双引号之前的字符,后跟任意数量的字符(包括无字符),后跟另一个单引号或双引号,以第一次匹配的为准。-replace如果您用空字符串替换模式,则不需要第二个参数。


推荐阅读