ansible - Docker 容器中环境变量的 json 模板

ansible - Docker 容器中环境变量的 json 模板

我正在尝试将一行 JSON 字符串分配给 Docker 容器中的环境变量。JSON 如下所示:

{"ip_access": {"IP_whitelist": {"192.168.99.19/32": "grafana/status (Provider)"}}, "vhosts": {"prometheus1": {"dns_names": ["prometheus1.company.internal"], "add_lines_443": ["include IP_whitelist;", "set $prometheus http://prometheus:9090;", "location / { proxy_pass $prometheus; }"], "options": {"cert_path": "/etc/ssl/certs/prometheus1.crt", "key_path": "/etc/ssl/private/prometheus1.key"}}}}

因此,["prometheus1.company.internal"]我想要的是["{{ inventory_hostname }} .company.internal"](并且也想要的其他实例)prometheus1

我正在使用docker_container,如下所示:

- name: create nginx reverse proxy container
  docker_container:
    image: registry.company.com/devops/nginx-reverseproxy:{{ nginx_version }}
    name: nginx-reverseproxy
    labels:
      role=metrics
    volumes:
      - /etc/ssl/certs/{{ inventory_hostname }}.crt:/etc/ssl/certs/{{ inventory_hostname }}.crt
      - /etc/ssl/private/{{ inventory_hostname }}.key:/etc/ssl/private/{{ inventory_hostname }}.key
    container_default_behavior: compatibility
    networks_cli_compatible: yes
    network_mode: default
    purge_networks: yes
    networks:
      - name: metrics-net
      - name: proxy-net
    env:
      STAGING_ENVIRONMENT: 'production'
      NGINX_VHOSTS_JSON: '{{ lookup("template", "rproxy/nginx_vhosts_prometheus_develop.j2") }}'

不幸的是,我不断收到:

TASK [prometheus : create nginx reverse proxy container] **********************************************
fatal: [prometheus_vag]: FAILED! => {"changed": false, "msg": "Non-string value found for env option. Ambiguous env options must be wrapped in quotes to avoid them being interpreted. Key: NGINX_VHOSTS_JSON"}

奇怪的是,如果我只是使用模板模块,它就会按预期工作:

  template:
    src: rproxy/nginx_vhosts_prometheus_develop.j2
    dest: /tmp/tempo.json
  when: "prometheus_host in inventory_hostname"
  tags:
    - copytmp

inventory_hostname将被清单中的实际值替换,我得到了正确的结果。此外,如果我将此精确结果粘贴到剧本中作为 yaml 剧本中 NGINX_VHOSTS_JSON 的值,它也可以正常工作。

但查找模板似乎没有提供预期的字符串。

有什么想法可以解决这个问题吗?

答案1

当事物看起来像结构的字符串表示时,Ansible 的模板通常会自动将其转换为数据结构。

在这种情况下,您可以通过在需要时将其明确转换为 JSON 来避免这种情况:

NGINX_VHOSTS_JSON: '{{ lookup("template", "rproxy/nginx_vhosts_prometheus_develop.j2") | to_json }}'

就我个人而言,我会采用更人性化的表示形式(例如 YAML)对其进行模板化,然后将其转换为 JSON:

test.j2

ip_access:
  IP_whitelist:
    192.168.99.19/32: grafana/status (Provider)
vhosts:
  {{ inventory_hostname }}.company.internal:
    add_lines_443:
    - include IP_whitelist;
    - set $prometheus http://prometheus:9090;
    - location / { proxy_pass $prometheus; }
    dns_names:
    - {{ inventory_hostname }}.company.internal
    options:
      cert_path: /etc/ssl/certs/{{ inventory_hostname }}.company.internal.crt
      key_path: /etc/ssl/private/{{ inventory_hostname }}.company.internal.key

test.yml

- hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: "{{ lookup('template', 'test.j2') | from_yaml | to_json }}"

结果:

ok: [localhost] => {
    "msg": "{\"ip_access\": {\"IP_whitelist\": {\"192.168.99.19/32\": \"grafana/status (Provider)\"}}, \"vhosts\": {\"localhost.company.internal\": {\"add_lines_443\": [\"include IP_whitelist;\", \"set $prometheus http://prometheus:9090;\", \"location / { proxy_pass $prometheus; }\"], \"dns_names\": [\"localhost.company.internal\"], \"options\": {\"cert_path\": \"/etc/ssl/certs/localhost.company.internal.crt\", \"key_path\": \"/etc/ssl/private/localhost.company.internal.key\"}}}}"
}

答案2

我最终通过将其转换为 json 解决了这个问题,如下所示:

NGINX_VHOSTS_JSON: '{{ lookup("template", "rproxy/nginx_vhosts_prometheus_develop.j2") | to_json }}'

我不需要改变任何其他东西。

相关内容