Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在ansible中编写嵌套json中的变量/硬代码值?_Ansible_Jinja2 - Fatal编程技术网

如何在ansible中编写嵌套json中的变量/硬代码值?

如何在ansible中编写嵌套json中的变量/硬代码值?,ansible,jinja2,Ansible,Jinja2,我正在尝试创建一个json文件,将硬代码值作为嵌套json中的输出。但是第二个播放正在覆盖第一个播放值。那么我们有没有最好的选择来实现这一点 我尝试使用to_nice_json模板将变量复制到json文件中,但无法在导入的_var中保留多个变量值以复制到json文件中 --- - hosts: localhost connection: local gather_facts: false tasks: - name: load var from file include

我正在尝试创建一个json文件,将硬代码值作为嵌套json中的输出。但是第二个播放正在覆盖第一个播放值。那么我们有没有最好的选择来实现这一点

我尝试使用to_nice_json模板将变量复制到json文件中,但无法在导入的_var中保留多个变量值以复制到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"
        }
    ]
}

您正在尝试执行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"
            }
        ]
    }
}
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "status_checks": {
        "httpd": "bad", 
        "sshd": "good"
    }
}
通过重组数据,您可以大大简化剧本。将
status\u 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] => {
    "imported_var": {
        "status_checks": [
            {
                "sshd_status": "good"
            }, 
            {
                "httpd_status": "bad"
            }
        ]
    }
}
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "status_checks": {
        "httpd": "bad", 
        "sshd": "good"
    }
}
如果确实要将此信息添加到导入的
变量中,可以在单个任务中完成:

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

问题是,我不仅要检查服务,还要检查其他事情,比如oracle数据库状态……等等,所以我必须在systemctl中使用其他命令。基本上,我这样做是为了比较操作系统升级前和升级后的结果,我想看一下操作系统升级后哪些东西坏了,然后把它们拉出来差异。建议我哪一个适合这个目标。我认为这个答案提供了你所要求的一切。你可以使用这里演示的相同技术编写多个任务,而不是依赖循环。