小技巧 - 處理 JSON 檔案

現在有不少服務都是使用 JSON 作為設定檔,所以常常會需要讀取 JSON 格式的設定檔,修改內容值後再寫回,那麼用 Ansible 的話,該怎麼做呢?

在 Ansible 裡,我們可以使用 filter 來處理,主要有這三個 filter :

  • from_json
  • to_json
  • combine

from_json,是解析 JSON 格式字串,並轉換為變數。像下面這樣寫,就可以將 JSON 格式字串轉為變數,放到 server_conf 變數裡。

- set_fact:
    server_conf: "{{ json_string | from_json }}"

to_json 是將變數轉換為 JSON 格式的字串。像下面這樣寫,就可以將變數轉為 JSON 格式的字串,並寫到 /tmp/foo.json

- copy:
    content: "{{ server_conf | to_json }}"
    dest: "/tmp/foo.json"

combine 則是跟變數做合併。

- name: Combine example
  vars:
    foo_data:
      id: 100
      name: "John Doe"
  set_fact:
    foo_data: '{{ foo_data | combine({"age":25,"name":"Mary Jane"}) }}'

以上面的例子來說,foo_data 的內容會變為

foo_data:
  id: 100
  name: "Mary Jane"
  age: 25

除了多了 age 之外,name 也變為 Mary Jane 。

下面就來看看怎麼使用。

先說明一下環境:

  • 連線主機上有 /etc/server.json 檔案
  • /etc/server.json 裡的內容是
{
    "foo": "2021-04-10T08:04:12Z",
    "force": true,
    "id": 1,
    "name": "server.json"
}

完整的 Playbook 範例如下:

---
- name: 讀取連線主機上的 server.json,讀取指定內容值、修改後寫回
  hosts: all

  vars:
    server_conf_file: "/etc/server.json"

  tasks:
    - name: Read {{ server_conf_file }}
      shell: cat {{ server_conf_file }}
      register: shell_result

    - name: Parase JSON text to a variable
      set_fact:
          server_conf: "{{ shell_result.stdout | from_json }}"

    - name: Display variable
      debug:
        var: server_conf

    - name: Modify "foo" in server_conf
      set_fact:
        server_conf: '{{ server_conf | combine({"foo":ansible_date_time.iso8601}) }}'

    - name: Display variable again
      debug:
        var: server_conf

    - name: Write back
      copy:
        content: "{{ server_conf | to_json }}"
        dest: "{{ server_conf_file }}"

    - name: Display file content
      shell: cat {{ server_conf_file }}
      register: shell_result

    - name: Display shell_result
      debug:
        var: shell_result.stdout

看完這個例子,相信你已經學會怎麼處理 JSON 格式的檔案了。

附帶一提,YAML 格式也可以用相同的方式來處理,因為有 from_yaml 跟 to_yaml 這兩個 filter,把 from_json / to_json 替換為 from_yaml / to_yaml 就可以啦。

參考資料: