web-dev-qa-db-ja.com

AnsibleでJSONを変更する

仮想環境を制御するためのメンテナンスデータを定義する管理システムがあります。オプションの1つは、VM異なるチームのシャットダウンタイムフレームです。今、新しいときVM VMを中断せずに勤務シフトにシャットダウンできる場合、ユーザーは利用可能なタイムフレームのリストから選択する必要があります。このタイムフレームのリストをデータベースからジョブテンプレートサーベイ。JSONサーベイの変更で行き詰まっています。この投稿を試しました jsonをansibleで変更する最善の方法 ですが、エラーが発生します。

"例外": "ファイル\"/tmp/ansible_1qa8eR/ansible_module_json_modify.py\"、line 38、in main\n res = jsonpointer.resolve_pointer(data、pointer)\ nファイル\"/usr/lib/python2.7/site-packages/jsonpointer.py\"、126行目のresolve_pointer\n return pointer.resolve(doc、default)\ 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 \"に見つかりません\ "%(パーツ、ドキュメント))\ n"、 "msg": "メンバー 'spec'が{'stderr_lines'に見つかりません:[]、 'changed':真、「終わり」

ここに私が変更しようとしている私の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
4
larrybg

modify_jsonのエラーに関する質問への直接の回答ではなく、有効な解決策です。

そのためには jq を使用します。 jqは軽量で柔軟なコマンドラインJSONプロセッサであり、ほぼすべてのLinuxディストリビューションで利用できます。そうでない場合は、依存関係のない prebuilt binaries を使用してください。

ウェブサイトが述べるように:

jqはJSONデータのsedに似ています-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の詳細については、 マニュアルページ を参照してください。

3
JGK

プレイブックにはいくつかの小さな問題があります

  1. ファイルからjsonデータをjson/dictではなく文字列としてロードしています。コマンド/ catタスクの代わりに、これを使用してデータをロードします。

    - set_fact:
        surveySpec: "{{ lookup('file', sharedDataPathFile) | from_json }}"
    
  2. もう1つの問題は、choices dictアイテムではなく、choices値(文字列)だけを更新しようとしていることです。 json_modifyポインタ:

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

    登録:結果

もう1つ、配列のインデックスは6ではなく5です。

1
Matt P