使用 ansible 从 env 文件中读取多个值并将它们存储为事实

Reading multiple values from an env file with ansible and storing them as facts

我有以下代码,它从环境 (.env) 文件中读取值并将它们存储为事实:

- name: Read values from environment
  shell: "source {{ env_path }}; echo $DB_PASSWORD"
  register: output
  args:
    executable: /bin/bash
  changed_when: false

- name: Store read password
  set_fact:
    db_password: "{{ output.stdout }}"
  when:
    - db_password is undefined
  changed_when: false

- name: Read values from environment
  shell: "source {{ env_path }}; echo $DB_USER"
  register: output
  args:
    executable: /bin/bash
  changed_when: false

- name: Store read user
  set_fact:
    db_user: "{{ output.stdout }}"
  when:
    - db_user is undefined
  changed_when: false

- name: Read values from environment
  shell: "source {{ env_path }}; echo $DB_NAME"
  register: output
  args:
    executable: /bin/bash
  changed_when: false

- name: Store read db_name
  set_fact:
    db_name: "{{ output.stdout }}"
  when:
    - db_name is undefined
  changed_when: false

- name: Container environment loaded; the following facts are now available for use by ansible
  debug: "var={{ item }}"
  with_items:
    - db_name
    - db_user
    - db_password

它非常笨重。我想这样写,但我不知道怎么写:

vars:
    values:
       - db_name
       - db_password
       - db_user
tasks:
- name: Read values from environment
  shell: "source {{ env_path }}; echo {{ item|upper }}"
  register: output
  with_items: values
  args:
    executable: /bin/bash
  changed_when: false

- name: Store read value
  set_fact:
    "{{ item.0 }}": "{{ item.1.stdout }}"
  when:
    - item.0 is undefined
  with_together:
    - values
    - output.results
  changed_when: false

相反,我得到了这个输出:

ok: [default] => (item=values) => {"changed": false, "cmd": "source /var/www/mydomain.org/.env; echo VALUES", "delta": "0:00:00.002240", "end": "2017-02-15 15:25:15.338673", "item": "values", "rc": 0, "start": "2017-02-15 15:25:15.336433", "stderr": "", "stdout": "VALUES", "stdout_lines": ["VALUES"], "warnings": []}

TASK [sql-base : Store read password] ******************************************
skipping: [default] => (item=[u'values', u'output.results'])  => {"changed": false, "item": ["values", "output.results"], "skip_reason": "Conditional check failed", "skipped": true}

当然,如果有一个我忽略的 ansible 模块允许我从环境文件加载值,那就更理想了。

通常我会把我的变量本身放入清单文件中,或者将它们转换为 yml 格式并使用 include_vars 模块(您可以 运行 sed 将环境文件动态转换为 yml 的脚本)。在使用下面的代码之前,请确保您确实需要使用这些环境文件,并且您不能轻易使用其他一些机制,例如:

  • 带有 include_vars 模块的 YAML 文件
  • 将配置放入清单(不需要模块)
  • 将配置放入 ansible vault 文件(不需要模块,但您需要将解密密钥存储在某处)
  • 使用其他一些安全存储机制,例如 Hashicorp 的保管库(带有 https://github.com/jhaals/ansible-vault 之类的插件)

回到你的代码,它实际上几乎是正确的,你从读取任务中漏掉了一美元,并且从条件中漏掉了一些大括号:

test.env

DB_NAME=abcd
DB_PASSWORD=defg
DB_USER=fghi

注意:确保此文件符合 sh 标准,这意味着您不要在 = 符号周围放置空格。像 DB_NAME = abcd 这样的东西会失败

play.yml

- hosts: all
  connection: local
  vars:
      env_path: 'test.env'
      values:
         - db_name
         - db_password
         - db_user
  tasks:
  - name: Read values from environment
    shell: "source {{ env_path }}; echo ${{ item|upper }}"
    register: output
    with_items: "{{ values }}"
    args:
      executable: /bin/bash
    changed_when: false

  - name: Store read value
    set_fact:
      "{{ item.0 }}": "{{ item.1.stdout }}"
    when: '{{ item.0 }} is undefined'
    with_together:
      - "{{ values }}"
      - "{{ output.results }}"
    changed_when: false

  - name: Debug
    debug:
      msg: "NAME: {{db_name}} PASS: {{db_password}} USER: {{db_user}}"

运行 ansible-playbook -i 127.0.0.1, play.yml:

TASK [Debug] *******************************************************************
ok: [127.0.0.1] => {
    "msg": "NAME: abcd PASS: defg USER: fghi"
}