根据条件更改默认值


16

是否可以根据某些条件(例如,另一个变量的值)更改角色变量的默认值?

细节

我有两个与命令相关的变量,envcomposer_opts

如果两个都保留为默认值(env = "prod"composer_opts = "--no-dev"),则一切正常。

如果更改envdev,则另一个默认设置将破坏我的命令,因此我总是需要同时设置两者。是否可以通过使用自定义脚本/ if设置条件默认值来避免这种情况?

重要提示:我不想总是设置composer_opts根据该值env的价值。我只想设置尚未设置的值(即动态默认值)。

伪码

我想做这样的事情(以下代码无效,只是伪代码来表达我的需要)

---
# defaults/main.yml

env: prod
composer_opts: 
    when: "{{env}}" = 'prod'
        '--no-dev --optimize-autoloader --no-interaction'
    when: "{{env}}" = 'dev'
        '' 

Answers:


12

我建议这种解决方案:

---
 - set_fact:
     composer_opts: ""
   when: "{{env}}" == 'dev'

当变量等于“ ” 时,它将composer_opts变量设置为字符串。""envdev

这是基于更新的问题的剧本示例:

$ cat test.yml

---
- hosts: 127.0.0.1
  connection: local
  tasks:
  - set_fact:
      composer_opts: "{% if env == 'prod' %} '--no-dev --optimize-autoloader --no-interaction' {% else %} '' {% endif %}"

  - debug: var=composer_opts

样本输出:

sudo ansible-playbook test.yml -e env=dev

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact ] ************************************************************* 
ok: [127.0.0.1]

TASK: [debug var="{{composer_opts}}"] ***************************************** 
ok: [127.0.0.1] => {
    "var": {
        " '' ": " '' "
    }
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0   


sudo ansible-playbook test.yml -e env=prod

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact ] ************************************************************* 
ok: [127.0.0.1]

TASK: [debug var="{{composer_opts}}"] ***************************************** 
ok: [127.0.0.1] => {
    "var": {
        " '--no-dev --optimize-autoloader --no-interaction' ": " '--no-dev --optimize-autoloader --no-interaction' "
    }
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0   

1
这是解决方案的一部分。composer_optsenv为“ dev” 时,它将始终设置为空字符串,覆盖任何实际值集。我认为,有条件的应延长这样的:when: "{{env}}" == 'dev' and "{{composer_opts}}" is undefined。看起来不错吗?您可以相应地提问吗?
Francesco Abeni 2015年

将定义composer_opts,因为它具有默认值。您需要另一个表达式来解决您的任务。例如变量custom_composer_opts。
Navern 2015年

请用伪代码详细说明您要做什么。我将相应地更新我的答案。
Navern 2015年

我已经用其他解释和伪代码示例更新了我的问题。谢谢。
Francesco Abeni 2015年

我已经更新了答案。核实。我相信我了解您的需求。
Navern 2015年

4

尽管@Navern的答案确实起作用,但我发现嵌入的Jinja2表示法("{% if env == 'prod' %} ...)非常容易受到表示法的影响,因此非常脆弱。例如,当包装有问题的行以提高可读性时,例如在此未经测试的代码中

composer_opts: >
               "{% if env == 'prod' %}
                   '--no-dev --optimize-autoloader --no-interaction'
                {% else %}
                   ''
                {% endif %}"

我结束了意想不到的效果,如额外的空格或\ncomposer_opts

我使用的方法笨拙,但也更稳定:

- name: set composer_opts for dev env
  set_fact:
     composer_opts: ''
     when: "{{env}}" == 'dev'

- name: set composer_opts for prod env
  set_fact:
     composer_opts: '--no-dev --optimize-autoloader --no-interaction'
     when: "{{env}}" == 'prod'

我还发现此博客帖子非常有用,基本上遵循相同的方法。


@sec(如果您使用|而不是)>可能没有空格问题。(否则您会得到更多的笑声)
迈克尔(Michael

@sec使用'>-'并签出ansible规范。它具有许多用于正确处理多行字符串的选项。 yaml-multiline.info 特别注意块阻塞指示器。
DylanYoung '19

请注意,此解决方案也有优先权问题。事实不是默认值。
DylanYoung '19

2

Ansible set_fact基于一个衬里的条件:

- name: "set composer_opts based on environment"
  set_fact:
     composer_opts:  "{{ '--no-dev --optimize-autoloader --no-interaction' if (env == 'prod') else '' }}"

与其他解决方案一样,优先级问题相同(事实并非默认值),但是,如果将此条件权放在defaults.yml文件中,则此解决方案将起作用。如果您根据条件设置了多个默认值,它将很快变得非常丑陋
DylanYoung
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.