在Ansible中修改JSON

时间:2018-11-29 15:29:22

标签: python json ansible

我有一个管理系统,我们在其中定义维护数据以控制虚拟环境,其中一个选项是不同团队的VM关闭时间范围。 现在,当创建新的虚拟机时,用户应该从可用的时间范围列表中进行选择,以便可以在不中断工作轮班的情况下关闭其虚拟机。 我需要能够将此时间范围列表从数据库同步到作业模板调查。我被困在修改JSON调查。我已经尝试过此帖子best way to modify json in ansible,但收到错误消息:

  

“例外”:“文件   \“ / tmp / ansible_1qa8eR / ansible_module_json_modify.py \”,第38行,在   main \ n res = jsonpointer.resolve_pointer(数据,指针)\ n文件   \“ / usr / lib / python2.7 / site-packages / jsonpointer.py \”,第126行,在   resolve_pointer \ n返回指标。resolve(默认为doc)\ n文件   \“ / usr / lib / python2.7 / site-packages / jsonpointer.py \”,第204行,在   resolve \ n doc = self.walk(doc,part)\ n文件   \“ / usr / lib / python2.7 / site-packages / jsonpointer.py \”,行279,在   walk \ n引发JsonPointerException(\“在%s中找不到成员'%s'\”%   (part,doc))\ n“,” msg“:”在{'stderr_lines'中找不到成员'spec':   [],“更改”:是,“结束”

这是我要修改的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": ""
}

我必须更新时间表(倒数第二个):

  

“选择”:“ 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 个答案:

答案 0 :(得分:2)

不是直接回答有关modify_json的错误的问题,而是有效的解决方案。

为此,我会选择jqjq是一种轻量级且灵活的命令行JSON处理器,几乎可用于所有Linux发行版。否则,请使用没有依赖性的prebuilt binaries

网站指出:

  

jq就像sed一样用于JSON数据-您可以使用sq进行切片,过滤,映射和转换结构化数据,而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的更多信息,请参见manual page

答案 1 :(得分:0)

您的剧本中只有几个小问题

  1. 您正在从文件中以字符串而不是json / dict的形式加载json数据。代替您的命令/猫任务,使用它来加载数据:

    - set_fact:
        surveySpec: "{{ lookup('file', sharedDataPathFile) | from_json }}"
    
  2. 您遇到的另一个问题是您尝试仅更新choices值(即字符串),而不是choices dict项。在您的json_modify指针中只需做一小步改动:

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

    注册:结果

另一件事..数组索引是5,而不是6