从Ansible中的YAML文件加载环境变量(使用include_vars)



我正在尝试从YAML文件加载变量,以便在同一剧本的后续任务中用作环境变量。这就是我正在做的:

  1. YAML格式的模板主机变量:
- name: builtin | template | template host variables file
ansible.builtin.template:
src: templates/django/hostvars.j2
dest: "host_vars/{{ inventory_hostname_short }}.yml"
mode: 0640
output_encoding: "utf-8"
delegate_to: localhost

这将生成以下文件:

--
# Host variables to be set as environment variables in tasks that need it
POSTGRES_PASSWORD: "<password>"
POSTGRES_USER: "dbuser"
POSTGRES_DB: "dbname"
POSTGRES_HOST: "dbhost"
POSTGRES_PORT: 5432
POSTGRES_SSLMODE: "verify-full"
POSTGRES_SSLCA: "/etc/ssl/certs/ISRG_Root_X1.pem"
POSTGRES_APPNAME: "myproject"
DJANGO_SITE_NAME: "mysite"
DJANGO_SITE_PASSWORD: "mypassword"
DJANGO_SITE_USER: "myuser"
DJANGO_SITE_ID: 2
DJANGO_SECRET_KEY: "<very-long-and-random-secret>"
[..]
  1. 使用include_vars将变量加载到剧本中:
- name: builtin | include_vars | load host vars
ansible.builtin.include_vars:
file: "host_vars/{{ inventory_hostname_short }}.yml"
name: envvars
  1. 稍后在剧本中,检查变量是否存在:
- name: builtin | debug | print variable 'envvars'
ansible.builtin.debug:
var: envvars

这正在按预期工作(显然(,并且正在打印KEY:value变量列表,例如:

TASK [builtin | debug | print variable 'envvars'] ***************************************************************
ok: [django1.mydomain.com] => {
"envvars": {
"DJANGO_DEBUG": 0,
"DJANGO_LOGS_DIR": "/opt/django/logs",
"DJANGO_MEDIA_BASE": "/opt/django/media",
"DJANGO_SECRET_KEY": "<very-long-and-random-secret>",
[..]
  1. 使用django_manage更新数据库架构:
- name: community.general | django_manage | update database schema
community.general.django_manage:
command: migrate
settings: myproject.settings
project_path: "/opt/django/src"
virtualenv: "/opt/django/venv"
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"

不幸的是,这是失败的。Django抱怨找不到SECRET_KEY环境变量,它应该基于上述列表中的一个变量(特别是DJANGO_SECRET_KEY(来构建该环境变量。

顺便说一句,如果我运行以下任务,则不会打印出任何内容:

- name: print environment variables
ansible.builtin.command: env
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"

我不明白为什么。我尝试过使用-vvv进行调试,它们是由Ansible通过SSH连接发送的(至少看起来是这样(。

有没有迹象表明我做错了什么?

编辑1

我已经将使用django_manage的任务列表文件更改为以下代码:

- name: builtin | shell | capture DJANGO_ environment variables
debugger: on_failed
ansible.builtin.shell:
cmd: "env | grep DJANGO_"
register: out
environment: "{{ envvars }}"
become: true
become_user: django
become_method: su
- name: builtin | debug | pinrt content of out.stdout
ansible.builtin.debug:
var: out.stdout
- name: builtin | debug | print variable 'envvars'
ansible.builtin.debug:
var: envvars
- name: community.general | django_manage | populate the static subdirectory
community.general.django_manage:
command: collectstatic
clear: yes
project_path: "/opt/django/src"
virtualenv: "/opt/django/venv"
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"

第二个和第三个任务都打印变量的值(第一个来自通过shell发送的env | grep DJANGO_命令,第二个是通过environment:指令发送的envvars变量的值

这是最后一个任务的错误:

TASK [builtin | shell | capture DJANGO_ environment variables] *************************************************************************************************************
changed: [django1.donmain.com]
TASK [builtin | debug | pinrt content of out.stdout] ***********************************************************************************************************************
ok: [django1.django.com] => {
"out.stdout": "DJANGO_SITE_USER=mysitenDJANGO_MEDIA_BASE=/opt/django/medianDJANGO_SITE_NAME=mysitenDJANGO_SITE_ID=2nDJANGO_SECRET_KEY=<very-secret-key>nDJANGO_LOGS_DIR=/opt/django/logsnDJANGO_SETTINGS_MODULE=myproject.settings.productionnDJANGO_DEBUG=0nDJANGO_STATIC_BASE=/opt/django/staticnDJANGO_SITE_PASSWORD=mypasswordnDJANGO_SITE_VERSION=57a2f3c168d86243f03809e5d02a0f50a8fa892e"
}
TASK [builtin | debug | print variable 'envvars'] **************************************************************************************************************************
ok: [django1.domain.com] => {
"envvars": {
"DJANGO_DEBUG": 0,
"DJANGO_LOGS_DIR": "/opt/django/logs",
"DJANGO_MEDIA_BASE": "/opt/django/media",
"DJANGO_SECRET_KEY": "<very-secret-key>",
"DJANGO_SETTINGS_MODULE": "myproject.settings.production",
"DJANGO_SITE_ID": 2,
"DJANGO_SITE_NAME": "mysite",
"DJANGO_SITE_PASSWORD": "mypassword",
"DJANGO_SITE_USER": "myuser",
[..]
}
}
TASK [community.general | django_manage | populate the static subdirectory] ************************************************************************************************
fatal: [django1.domain.com]: FAILED! => {"changed": false, "cmd": ["./manage.py", "collectstatic", "--noinput", "--clear"], "msg": "n:stderr: Traceback (most recent call last):n  File "/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 204, in fetch_commandn    app_name = commands[subcommand]nKeyError: 'collectstatic'nnDuring handling of the above exception, another exception occurred:nnTraceback (most recent call last):n  File "/opt/django/src/./manage.py", line 22, in <module>n    execute_from_command_line(sys.argv)n  File "/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_linen    utility.execute()n  File "/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 375, in executen    self.fetch_command(subcommand).run_from_argv(self.argv)n  File "/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 211, in fetch_commandn    settings.INSTALLED_APPSn  File "/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py", line 57, in __getattr__n    self._setup(name)n  File "/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py", line 44, in _setupn    self._wrapped = Settings(settings_module)n  File "/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py", line 107, in __init__n    mod = importlib.import_module(self.SETTINGS_MODULE)n  File "/usr/lib/python3.9/importlib/__init__.py", line 127, in import_modulen    return _bootstrap._gcd_import(name[level:], package, level)n  File "<frozen importlib._bootstrap>", line 1030, in _gcd_importn  File "<frozen importlib._bootstrap>", line 1007, in _find_and_loadn  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlockedn  File "<frozen importlib._bootstrap>", line 680, in _load_unlockedn  File "<frozen importlib._bootstrap_external>", line 790, in exec_modulen  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removedn  File "/opt/django/src/black_pearl/settings/production.py", line 3, in <module>n    from black_pearl.settings.common import *n  File "/opt/django/src/black_pearl/settings/common.py", line 301, in <module>n    path_app = import_module(app).__path__n  File "/usr/lib/python3.9/importlib/__init__.py", line 127, in import_modulen    return _bootstrap._gcd_import(name[level:], package, level)nModuleNotFoundError: No module named 'None'n", "path": "/opt/django/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "syspath": ["/tmp/ansible_community.general.django_manage_payload_l53eeo4g/ansible_community.general.django_manage_payload.zip", "/usr/lib/python39.zip", "/usr/lib/python3.9", "/usr/lib/python3.9/lib-dynload", "/usr/local/lib/python3.9/dist-packages", "/usr/lib/python3/dist-packages"]}
PLAY RECAP *****************************************************************************************************************************************************************
django1.domain.com    : ok=14   changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

提前谢谢。

Q:"没有打印出任何内容">

A: 如果你想看到输出,请注册它。例如

- hosts: localhost
tasks:
- command: echo $DJANGO_DEBUG
register: out
environment:
DJANGO_DEBUG: 0
- debug:
var: out.stdout

给出(节略(

out.stdout: '0'

这应该对你有用。逐步增加代码的复杂性并隔离问题。例如,下面的剧本应该显示远程主机的环境

- hosts: test_11
vars:
env:
DJANGO_DEBUG: 0
DJANGO_SITE_NAME: mysite
DJANGO_SITE_PASSWORD: mypassword
DJANGO_SITE_USER: myuser
DJANGO_SITE_ID: 2
tasks:
- shell: env | grep DJANGO_
register: out
environment: "{{ env }}"
- debug:
var: out.stdout