Variable in text not replaced and still with braces

huangapple go评论59阅读模式
英文:

Variable in text not replaced and still with braces

问题

Convert to b64 format:

$ cat json | base64 | tr -d "\n"
ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZsIjogIkVOWl9URVNUIHRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K

Extra vars for playbook (additional_variable and json_props):

-e additional_variable=additionaltext -e json_props=ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZsIjogIkVOWl9URVNUIHRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K

Playbook:

---
- hosts: test
  gather_facts: False
  vars:
    props: "{{ json_props | b64decode | from_json }}"
    prop:
      envs: "{{ props.envs }}"
  tasks:
  - debug:
      msg: "{{ additional_variable }}"

  - debug:
      msg: "{{ prop.envs }}"

Output:

TASK [debug] **********************************************************************
ok: [127.0.0.1] => {
    "msg": "additionaltext"
}

TASK [debug] **********************************************************************
ok: [127.0.0.1] => {
    "msg": "ENV_TEST=true ENV_TEXT={{additional_variable}}"
}

How to set variable additional_variable from extra vars to the prop.envs string?

Any ideas?

I expect that output will be "ENV_TEST=true ENV_TEXT=additionaltext"


<details>
<summary>英文:</summary>

There is a json file (this content is transferring as base64 to playbook):

$ cat json
{
"name": "some_value",
"envs": "ENV_TEST=true ENV_TEXT={{additional_variable}}"
}


Convert to b64 format:

$ cat json | base64 | tr -d "\n"
ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZzIjogIkVOVl9URVNUPXRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K


Extra vars for playbook (additional_variable and json_props):

-e additional_variable=additionaltext -e json_props=ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZzIjogIkVOVl9URVNUPXRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K


Playbook:

  • hosts: test
    gather_facts: False
    vars:
    props: "{{ json_props | b64decode | from_json }}"
    prop:
    envs: "{{ props.envs }}"
    tasks:

    • debug:
      msg: "{{ additional_variable }}"

    • debug:
      msg: "{{ prop.envs }}"


Output:

TASK [debug] **********************************************************************
ok: [127.0.0.1] => {
"msg": "additionaltext"
}

TASK [debug] **********************************************************************
ok: [127.0.0.1] => {
"msg": "ENV_TEST=true ENV_TEXT={{additional_variable}}"
}


How to set variable additional_variable from extra vars to the prop.envs string?

Any ideas?

I expect that output will be &quot;ENV_TEST=true ENV_TEXT=additionaltext&quot;

</details>


# 答案1
**得分**: 1

以下是您要翻译的部分:

问题在于变量 *props* 的值已经在表达式中被 '模板化' 了

```yaml
  props: "{{ json_props|b64decode|from_json }}"

你已经发现,在提供了额外的变量之后

shell> cat evars.yml
additional_variable: additionaltext
json_props: ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZzIjogIkVOVl9URVNUPXRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K

这个Playbook

shell> cat pb.yml
- hosts: localhost

  vars:

    props: "{{ json_props|b64decode|from_json }}"

  tasks:

    - debug:
        var: props

会得到

shell> ansible-playbook -e @evars.yml pb.yml

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] => 
  props:
    envs: ENV_TEST=true ENV_TEXT={{additional_variable}}
    name: some_value

变量 additional_variable 没有被替换在属性 envs 中,属性的显式扩展也没有帮助。Ansible 不提供在 vars 中 '模板化' 变量值的工具。但是,你可以自己创建一个自定义过滤器

shell> cat plugins/filter/template.py
from jinja2 import Environment, BaseLoader

def template(my_string, my_vars):
    rtemplate = Environment(loader=BaseLoader).from_string(my_string)
    return(rtemplate.render(my_vars))

class FilterModule(object):

    def filters(self):
        return {
            'template': template,
        }

配置过滤器插件的路径 DEFAULT_FILTER_PLUGIN_PATH。例如,

shell> grep filter ansible.cfg 
filter_plugins = $PWD/plugins/filter

然后使用过滤器 template。作为过滤器的第二个参数,你必须提供一个包含用于替换的变量的字典

  prop:
    envs: "{{ props.envs|template(vars) }}"

会得到你想要的结果

  prop:
    envs: ENV_TEST=true ENV_TEXT=additionaltext

  • 一个用于测试的完整Playbook示例
shell> cat pb.yml
- hosts: localhost

  vars:

    props: "{{ json_props|b64decode|from_json }}"
    prop:
      envs: "{{ props.envs|template(vars) }}"

  tasks:

    - debug:
        var: props
    - debug:
        var: additional_variable
    - debug:
        var: prop

    - set_fact:
        envs: "{{ props.envs|template(my_vars) }}"
      vars:
        my_vars:
          additional_variable: "{{ additional_variable }}"
    - debug:
        var: envs

会得到

shell> ansible-playbook -e @evars.yml pb.yml

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] => 
  props:
    envs: ENV_TEST=true ENV_TEXT={{additional_variable}}
    name: some_value

TASK [debug] **********************************************************************************
ok: [localhost] => 
  additional_variable: additionaltext

TASK [debug] **********************************************************************************
ok: [localhost] => 
  prop:
    envs: ENV_TEST=true ENV_TEXT=additionaltext

TASK [set_fact] *******************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************
ok: [localhost] => 
  envs: ENV_TEST=true ENV_TEXT=additionaltext

PLAY RECAP ************************************************************************************
localhost: ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

  • 一个更简单的选项是传递文件名而不是编码内容。例如,给定文件
shell> cat /tmp/test.json 
{
  "name": "some_value",
  "envs": "ENV_TEST=true ENV_TEXT={{ additional_variable }}"
}

通过 include_vars 将文件中的变量包含到字典中

shell> cat pb.yml
- hosts: localhost

  tasks:

    - include_vars:
        file: "{{ file_json_props }}"
        name: props
    - debug:
        var: props

这样表达式会自动 '模板化'(扩展)

shell> ansible-playbook -e additional_variable=additionaltext -e file_json_props=/tmp/test.json pb.yml

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] => 
  additional_variable: additionaltext

TASK [include_vars] ***************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************
ok: [localhost] => 
  props:
    envs: ENV_TEST=true ENV_TEXT=additionaltext
    name: some_value

PLAY RECAP ************************************************************************************
localhost: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
英文:

The problem is that the value of the variable props have already been 'templated' in the expression

  props: &quot;{{ json_props|b64decode|from_json }}&quot;

You've already found out that given the extra variables

shell&gt; cat evars.yml
additional_variable: additionaltext
json_props: ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZzIjogIkVOVl9URVNUPXRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K

The playbook

shell&gt; cat pb.yml
- hosts: localhost

  vars:

    props: &quot;{{ json_props|b64decode|from_json }}&quot;

  tasks:

    - debug:
        var: props

gives

shell&gt; ansible-playbook -e @evars.yml pb.yml

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  props:
    envs: ENV_TEST=true ENV_TEXT={{additional_variable}}
    name: some_value

The variable additional_variable was not substituted in the attribute envs and explicit expansion of the attribute doesn't help either. Ansible doesn't provide a tool to 'template' a value of a variable in vars. But, you can create a custom filter on your own

shell&gt; cat plugins/filter/template.py
from jinja2 import Environment, BaseLoader


def template(my_string, my_vars):
    rtemplate = Environment(loader=BaseLoader).from_string(my_string)
    return(rtemplate.render(my_vars))


class FilterModule(object):

    def filters(self):
        return {
            &#39;template&#39;: template,
        }

Configure the path to the filter plugins DEFAULT_FILTER_PLUGIN_PATH. For example,

shell&gt; grep filter ansible.cfg 
filter_plugins = $PWD/plugins/filter

and use the filter template. As a second argument of the filter you have to provide a dictionary with the variables the template needs for the substitutions

  prop:
    envs: &quot;{{ props.envs|template(vars) }}&quot;

gives what you want

  prop:
    envs: ENV_TEST=true ENV_TEXT=additionaltext

<hr>

<sup>

  • Example of a complete playbook for testing
shell&gt; cat pb.yml
- hosts: localhost

  vars:

    props: &quot;{{ json_props|b64decode|from_json }}&quot;
    prop:
      envs: &quot;{{ props.envs|template(vars) }}&quot;

  tasks:

    - debug:
        var: props
    - debug:
        var: additional_variable
    - debug:
        var: prop

    - set_fact:
        envs: &quot;{{ props.envs|template(my_vars) }}&quot;
      vars:
        my_vars:
          additional_variable: &quot;{{ additional_variable }}&quot;
    - debug:
        var: envs

gives

shell&gt; ansible-playbook -e @evars.yml pb.yml

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  props:
    envs: ENV_TEST=true ENV_TEXT={{additional_variable}}
    name: some_value

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  additional_variable: additionaltext

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  prop:
    envs: ENV_TEST=true ENV_TEXT=additionaltext

TASK [set_fact] *******************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  envs: ENV_TEST=true ENV_TEXT=additionaltext

PLAY RECAP ************************************************************************************
localhost: ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

<hr>

  • A simpler option is passing the filename instead of the encoded content. For example, given the file
shell&gt; cat /tmp/test.json 
{
  &quot;name&quot;: &quot;some_value&quot;,
  &quot;envs&quot;: &quot;ENV_TEST=true ENV_TEXT={{ additional_variable }}&quot;
}

include the variables from the file into a dictionary by include_vars

shell&gt; cat pb.yml
- hosts: localhost

  tasks:

    - include_vars:
        file: &quot;{{ file_json_props }}&quot;
        name: props
    - debug:
        var: props

This way the expressions are 'templated' (expanded) automatically

shell&gt; ansible-playbook -e additional_variable=additionaltext -e file_json_props=/tmp/test.json pb.yml

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  additional_variable: additionaltext

TASK [include_vars] ***************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************
ok: [localhost] =&gt; 
  props:
    envs: ENV_TEST=true ENV_TEXT=additionaltext
    name: some_value

PLAY RECAP ************************************************************************************
localhost: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

</sup>

huangapple
  • 本文由 发表于 2023年5月10日 18:48:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76217491.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定