在Ansible中修改JSON

10
我有一个管理系统,我们在其中定义维护数据以控制虚拟环境,其中一个选项是不同团队的虚拟机关闭时间。现在,当创建新的虚拟机时,用户应该从可用的时间列表中选择虚拟机可以在没有工作时间干扰的情况下关闭的时间段。我需要能够将这个时间段列表从我的数据库同步到作业模板调查中。我被修改JSON调查卡住了。我尝试了这篇文章best way to modify json in ansible但是出现了错误:

"exception": " File \"/tmp/ansible_1qa8eR/ansible_module_json_modify.py\", line 38, in main\n res = jsonpointer.resolve_pointer(data, pointer)\n File \"/usr/lib/python2.7/site-packages/jsonpointer.py\", line 126, in resolve_pointer\n return pointer.resolve(doc, default)\n File \"/usr/lib/python2.7/site-packages/jsonpointer.py\", line 204, in resolve\n doc = self.walk(doc, part)\n File \"/usr/lib/python2.7/site-packages/jsonpointer.py\", line 279, in walk\n raise JsonPointerException(\"member '%s' not found in %s\" % (part, doc))\n", "msg": "member 'spec' not found in {'stderr_lines': [], 'changed': True, 'end'

这是我要修改的JSON:
{
  "spec": [
    {
      "question_description": "", 
      "min": 0, 
      "default": "Test text", 
      "max": 4096, 
      "required": true, 
      "choices": "", 
      "variable": "_t", 
      "question_name": "Note", 
      "type": "textarea"
    }, 
    {
      "required": true, 
      "min": null, 
      "default": "", 
      "max": null, 
      "question_description": "appliance id", 
      "choices": "Unconfigured\n600,qvmProcessor/applianceexemptions,all", 
      "new_question": true, 
      "variable": "appid", 
      "question_name": "Appliance ID", 
      "type": "multiplechoice"
    }, 
    {
      "required": true, 
      "min": null, 
      "default": "", 
      "max": null, 
      "question_description": "Select version", 
      "choices": "1.2.3\n1.2.4\n1.2.5", 
      "new_question": true, 
      "variable": "version", 
      "question_name": "App Version", 
      "type": "multiplechoice"
    }, 
    {
      "required": true, 
      "min": 0, 
      "default": "", 
      "max": 1024, 
      "question_description": "", 
      "choices": "", 
      "new_question": true, 
      "variable": "newVMIP", 
      "question_name": "IP for new VM", 
      "type": "text"
    }, 
    {
      "required": true, 
      "min": 0, 
      "default": "", 
      "max": 1024, 
      "question_description": "", 
      "choices": "", 
      "new_question": true, 
      "variable": "requesterEmail", 
      "question_name": "Requester's email", 
      "type": "text"
    }, 
    {
      "required": true, 
      "min": null, 
      "default": "", 
      "max": null, 
      "question_description": "Select the timeframe for automatic VM shutdown. ***NOTE*** EST Time is in 24 hour format", 
      "choices": "23:00-02:00\n02:00-04:00\n04:00-06:00\n00:00-02:00", 
      "new_question": true, 
      "variable": "powerOFF_TimeFrame", 
      "question_name": "Power OFF window", 
      "type": "multiplechoice"
    }, 
    {
      "required": true, 
      "min": 0, 
      "default": 5, 
      "max": 30, 
      "question_description": "The VM will be deleted after # of days specified (default=5).", 
      "choices": "", 
      "new_question": true, 
      "variable": "vmNumReservedDays", 
      "question_name": "Keep VM for # of days", 
      "type": "integer"
    }
  ], 
  "description": "", 
  "name": ""
}

我需要更新时间段(倒数第二个)选项:

"choices": "23:00-02:00\n02:00-04:00\n04:00-06:00\n00:00-02:00",

这是我的代码。我可以直接读取到变量,但现在我只是将JSON保存到文件中:

- name: Sync Power Schedules From Database to Survey Spec
  hosts: awxroot
  gather_facts: no

  vars:
    new_choices: {}

  tasks:

    - name: Set shared directory name
      set_fact: 
        sharedDataPath: /var/tmp/survey

    - name: Set shared file path name
      set_fact: 
        sharedDataPathFile: "{{sharedDataPath}}/s.json"

    - name: Create directory to share data
      file:
        path: "{{ sharedDataPath }}"
        state: directory

    - name: Load Survey Spec to file
      shell: 'tower-cli job_template survey 70 > "{{ sharedDataPathFile }}"'



    - name: Make sure the survey spec file exists
      stat:
        path: "{{ sharedDataPathFile }}"
      register: isFileExists

    - name: Fail if file is not there
      fail:
        msg: "Cannot find survey spec exported file"
      when: isFileExists == False

    - name: Read exception file to a variable
      command: cat "{{ sharedDataPathFile }}"
      register: surveySpec
      when: isFileExists.stat.exists == True


    - name: Setting key
      set_fact:
        choices_key: "choices"

    - name: Setting new values
      set_fact:
        choices_value: "23:00-02:00\n02:00-04:00\n04:00-06:00\n00:00-04:00"

    - name: Create dictionary
      set_fact:
        new_choices: "{{ new_choices | combine({choices_key: choices_value}) }}"


    - json_modify:
        data: "{{ surveySpec }}"
        pointer: "/spec/6/choices"
        action: update
        update: "{{new_choices}}"
      register: result

    - debug:
        var: result.result
2个回答

10

这不是关于modify_json错误的直接回答,而是一个有效的解决方案。

我建议使用jqjq 是一个轻量级灵活的命令行JSON处理器,几乎适用于每个Linux发行版。如果没有,可以使用预构建的二进制文件,不带任何依赖项。

正如该网站所述:

jq像针对文本数据的sed一样针对JSON数据 - 您可以使用它来切片、过滤、映射和转换结构化数据,就像sed、awk、grep和朋友让您处理文本一样轻松。

我缩小了您的操作范围,提供了一个最小可行的解决方案,实现了相同的结果。在运行系统上,jq可执行文件必须在PATH中。请随意定制它以满足您的需求。

---
- name: Sync Power Schedules From Database to Survey Spec
  hosts: localhost
  gather_facts: no

  vars:
    choices_key: ".spec[6].choices"
    choices_value: "23:00-02:00\n02:00-04:00\n04:00-06:00\n00:00-04:00"
    json_file: "{{playbook_dir}}/s.json"

  tasks:

  - name: "modify json"
    command: >
      jq "{{choices_key}}=\"{{choices_value}}\"" "{{json_file}}"
    register: json

  - debug:
      var: json.stdout

我认为这种解决方法更加优雅,不需要使用额外的 json_modify.py 模块。关于 jq 的更多信息,请参见手册页面


1

您的playbook只有一些小问题。

  1. You are loading the json data from the file as a string, rather than json/dict. Instead of your command/cat task, use this to load the data in:

     - set_fact:
         surveySpec: "{{ lookup('file', sharedDataPathFile) | from_json }}"
    
  2. The other problem you would have hit is you are attempting to update just the choices value (i.e. a string), rather than the choices dict item. Just a small change required in your json_modify pointer:

     - json_modify:
         data: "{{ surveySpec }}"
         pointer: "/spec/5"
         action: update
         update: "{{ new_choices }}"
       register: result
    

还有一件事..数组索引是5,不是6


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接