Как записать переменные / значения жесткого кода во вложенном json в ansible? - PullRequest
0 голосов
/ 30 апреля 2019

Я пытаюсь создать файл json со значениями жестких кодов как вывод во вложенном json. Но при втором воспроизведении перезаписывается первое значение воспроизведения. Так у нас есть какой-нибудь лучший вариант сделать это?

Я попытался с шаблоном to_nice_json скопировать переменную в файл json. Но не удалось сохранить несколько значений переменных в импортированном_параметре для копирования в файл json

---
- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
  - name: load var from file
    include_vars:
      file: /tmp/var.json
      name: imported_var

  - name: Checking mysqld status
    shell: service mysqld status
    register: mysqld_stat
    ignore_errors: true

  - name: Checking mysqld status
    shell: service httpd status
    register: httpd_stat
    ignore_errors: true

  - name: append mysqld status to output json
    set_fact:
     imported_var: "{{ imported_var | combine({ 'status_checks':[{'mysqld_status': (mysqld_stat.rc == 0)|ternary('good', 'bad') }]})}}"

# - name: write var to file
 #   copy:
  #    content: "{{ imported_var | to_nice_json }}"
   #   dest: /tmp/final.json

  - name: append httpd status to output json
    set_fact:
      imported_var: "{{ imported_var| combine({ 'status_checks':[{'httpd_status': (httpd_stat.rc == 0)|ternary('good', 'bad') }]})}}"

 # - debug:
  #    var: imported_var

  - name: write var to file
    copy:
      content: "{{ imported_var | to_nice_json }}"
      dest: /tmp/final.json

Ожидаемый результат:

{
    "status_checks": [
        {
            "mysqld_status": "good"
            "httpd_status": "good"
        }
    ]
}

Фактический результат:

{
    "status_checks": [
        {
            "httpd_status": "good"
        }
    ]
}

1 Ответ

1 голос
/ 30 апреля 2019

Вы пытаетесь выполнить тот вид манипулирования данными, в котором Ansible действительно не так хорош. Каждый раз, когда вы пытаетесь изменить существующую переменную - особенно если вы пытаетесь установить вложенное значение - вы усложняете жизнь. Сказав это, можно делать то, что вы хотите. Например:

---
- hosts: localhost
  gather_facts: false
  vars:
    imported_var: {}

  tasks:
    - name: Checking sshd status
      command: systemctl is-active sshd
      register: sshd_stat
      ignore_errors: true

    - name: Checking httpd status
      command: systemctl is-active httpd
      register: httpd_stat
      ignore_errors: true

    - set_fact:
        imported_var: "{{ imported_var|combine({'status_checks': []}) }}"

    - set_fact:
        imported_var: >-
          {{ imported_var|combine({'status_checks':
          imported_var.status_checks + [{'sshd_status': (sshd_stat.rc == 0)|ternary('good', 'bad')}]}) }}

    - set_fact:
        imported_var: >-
          {{ imported_var|combine({'status_checks':
          imported_var.status_checks + [{'httpd_status': (httpd_stat.rc == 0)|ternary('good', 'bad')}]}) }}

    - debug:
        var: imported_var

В моей системе (которая работает sshd, но не работает httpd, это выдаст:

TASK [debug] **********************************************************************************
ok: [localhost] => {
    "imported_var": {
        "status_checks": [
            {
                "sshd_status": "good"
            }, 
            {
                "httpd_status": "bad"
            }
        ]
    }
}

Вы можете значительно упростить сборник пьес, реструктурировав свои данные. Сделайте status_checks переменной верхнего уровня, и вместо того, чтобы она была списком, пусть это будет словарь, который отображает имя службы в соответствующий статус. Объедините это с некоторыми циклами, и вы получите нечто гораздо более простое:

---
- hosts: localhost
  gather_facts: false

  tasks:

    # We can use a loop here instead of writing a separate task
    # for each service.
    - name: Checking service status
      command: systemctl is-active {{ item }}
      register: services
      ignore_errors: true
      loop:
        - sshd
        - httpd

    # Using a loop in the previous task means we can use a loop
    # when creating the status_checks variable, which again removes
    # a bunch of duplicate code.
    - name: set status_checks variable
      set_fact:
        status_checks: "{{ status_checks|default({})|combine({item.item: (item.rc == 0)|ternary('good', 'bad')}) }}"
      loop: "{{ services.results }}"

    - debug:
        var: status_checks

Выше будет выводиться:

TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "status_checks": {
        "httpd": "bad", 
        "sshd": "good"
    }
}

Если вы действительно хотите добавить эту информацию в imported_var, вы можете сделать это в одной задаче:

- set_fact:
    imported_var: "{{ imported_var|combine({'status_checks': status_checks}) }}"
...