Alteração possível do valor padrão de acordo com uma condição


16

É possível alterar o valor padrão da variável de função de acordo com alguma condição (ou seja, o valor de outra variável)?

Detalhes

Eu tenho duas variáveis ​​relacionadas para um comando enve composer_opts.

Se ambos forem deixados no padrão ( env = "prod"e composer_opts = "--no-dev") tudo está ok.

Se eu mudar envpara dev, o padrão para o outro interromperá meu comando, portanto, sempre preciso definir os dois. Seria possível evitar isso definindo um valor padrão condicional com um script personalizado / if?

Importante: não quero sempre definir o composer_optsvalor de acordo com o envvalor. Quero defini-lo apenas se ainda não estiver definido (ou seja, um valor padrão dinâmico).

Pseudo-código

Gostaria de fazer algo assim (o código a seguir não é válido, apenas pseudocódigo para expressar minha necessidade)

---
# defaults/main.yml

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

Respostas:


12

Sugiro esta solução:

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

Ele definirá composer_optsvariável como string ""quando a variável envfor igual a ' dev'.

Aqui está um exemplo de manual com base na pergunta atualizada:

$ 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

Saída de amostra:

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
Isso faz parte da solução. Ele sempre será definido composer_optscomo string vazia quando envfor "dev", substituindo qualquer valor real definido. Eu acho que a condicional deve ser alargado como este: when: "{{env}}" == 'dev' and "{{composer_opts}}" is undefined. Parece bom? Você pode atualizar sua pergunta de acordo?
Francesco Abeni

composer_opts será definido porque possui seu valor padrão. Você precisa de outra expressão para resolver sua tarefa. Por exemplo, variável custom_composer_opts.
Navern

Elabore com pseudocódigo o que você deseja fazer. Vou atualizar minha resposta de acordo.
Navern

Atualizei minha pergunta com uma explicação adicional e um exemplo de pseudocódigo. Obrigado.
Francesco Abeni

Eu atualizei minha resposta. Confira. Eu acredito que entendi o que você precisa.
Navern

4

Embora a resposta do @ Navern funcione, achei a notação Jinja2 ( "{% if env == 'prod' %} ...) embutida extremamente sensível à notação e, portanto, bastante frágil. Por exemplo, ao agrupar a linha em questão para melhor legibilidade, como neste código não testado :

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

Acabei com resultados inesperados, como espaço \nem branco adicional ou in composer_opts.

A abordagem que uso é muito mais estúpida, mas também mais estável:

- 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'

Também achei este post útil, o que essencialmente segue a mesma abordagem.


@sec se você usar em |vez de >não ter o problema de espaço em branco. (ou você vai ter mais do mesmo LOL)
Michael

@sec Use '> -' e verifique a especificação ansible. Ele tem muitas opções para manipular corretamente seqüências multilinhas. yaml-multiline.info Observe, em particular, o indicador de chomping de bloco.
DylanYoung

Observe que esta solução também teve problemas de precedência. Um fato não é um padrão.
DylanYoung

2

Ansible set_fact com base na condição em um liner:

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

Os mesmos problemas de precedência que as outras soluções (um fato não é um padrão); no entanto, se você colocar esse direito condicional em seu arquivo defaults.yml, essa solução funcionará. Fica muito rápido muito feia se você tem um número de defaults dependente da condição
DylanYoung
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.