Resolvido: defina condicionalmente variáveis ​​no arquivo vars se uma determinada condição for atendida


19

Dependendo do valor (Verdadeiro / Falso) de uma variável definida no group_vars, estou tentando definir algumas variáveis ​​em um arquivo vars. Seu valor depende do valor do grupo var.

Meu arquivo var atual é assim:

{% if my_group_var %}
test:
   var1: value
   var2: value
   ...
   varn: value
{% else %}
test:
   var1: other_value
   var2: other_value
   ...
   varn: other_value
{% endif %}

Para cada uma das minhas funções, estou usando uma variável definida neste arquivo.

Meu manual de teste é exibido abaixo:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/test_vars.yml
  roles: blabla 

O erro que estou recebendo após executar o playbook é:

{% if my_group_var %}
 ^ here

exception type: <class 'yaml.scanner.ScannerError'>
exception: while scanning for the next token
found character that cannot start any token
  in "<unicode string>"

Estou fazendo algo estúpido aqui ou isso nem é suportado? Tentei encontrar outra maneira de definir esses vars (eu tenho muitos), mas não consegui algo funcional aqui. Alguma sugestão?


Onde esses vars acabam sendo usados? Isso pode ser desnecessário se tudo o que você usará for parte de uma templatechamada de módulo.
84104

Se testfor dependente do grupo, ele deve ser colocado em group_vars.
Konstantin Suvorov

Infelizmente, o teste não depende do grupo. Conforme mencionado na descrição, o teste depende do valor de uma variável group_var.
pandoJohn

Respostas:


11

Eu não acho que você possa, normalmente crio arquivos separados para armazenar coleções de variáveis ​​condicionais e uso uma whencláusula para incluí-los em uma condição específica:

- include_vars: test_environment_vars.yml
  when: global_platform == "test"

- include_vars: staging_environment_vars.yml
  when: global_platform == "staging"

- include_vars: prod_environment_vars.yml
  when: 
    - global_platform != "test" 
    - global_platform != "staging" 

2
Isso é algo que eu estava tentando evitar. Não quero usar include vars ou definir 2 arquivos var adicionais para minhas tarefas.
pandoJohn

Eu não entendi .. quando é possível usar include_vars com condição, por que não variável pode ser definida com condição?
GP92

10

O Ansible permite que um dos seguintes formulários defina a variável condicionalmente:

    test:
      var1: "{% if my_group_var %}value{% else %}other_value{% endif %}"
      var2: "{{'value' if (my_group_var) else 'other_value'}}"

Combinando a sintaxe acima com a pesquisa de vars, podemos carregar vars complexos (lista neste caso):

test_value_when_my_group_var_is_true:
   var1: value
   var2: value

test_value_when_my_group_var_is_false:
   var1: other_value
   var2: other_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_true') if (my_group_var) else lookup('vars','test_value_when_my_group_var_is_false')}}"

Há outra maneira de fazer o carregamento de árvore condicional com pesquisa de vars. Dessa forma, é útil quando você precisa implementar a lógica de caso (ou seja, a variável de condição possui mais de dois valores possíveis):

test_value_when_my_group_var_is_foo:
   var1: value
   var2: value

test_value_when_my_group_var_is_bar:
   var1: other_value
   var2: other_value

test_value_when_my_group_var_is_baz:
   var1: yet_another_value
   var2: yet_another_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_' + my_group_var) }}"

2

Apesar de ser bom, receio que seu caminho não seja possível (ou não estou ciente do caminho certo).

Eu sugiro que primeiro prepare o arquivo vars do modelo jinja e depois inclua-o no include_vars. Veja o exemplo do manual:

---
- name: -Test-
  hosts: local
  vars:
    my_group_var: False
#    my_group_var: True

  tasks:

  - name: Prepare vars file from template.
    template: src=/tmp/vars.yaml.j2
              dest=/tmp/vars.yaml

  - name: Include vars
    include_vars: "/tmp/vars.yaml"

O conteúdo do modelo jinja de exemplo /tmp/vars.yaml.j2 é:

{% if my_group_var %}                                                                                                                                                                                             
test:                                                                                                                                                                                                             
   var1: value                                                                                                                                                                                                    
   var2: value                                                                                                                                                                                                    
{% else %}                                                                                                                                                                                                        
test:                                                                                                                                                                                                             
   var1: other_value                                                                                                                                                                                              
   var2: other_value                                                                                                                                                                                              
{% endif %}

Eu gosto disso, mas o problema é que, depois de gerar o arquivo .yml a partir do modelo jinja, ele não está disponível para as tarefas subseqüentes do meu manual.
pandoJohn

Por quê? Quando tentei estender o manual de teste com a tarefa de depuração, - debug: var=testposso ver que existem dois test.var1e test.var2com os valores esperados. Portanto, você deve poder usar essas variáveis ​​em outras tarefas do manual.
Jaroslav Kucera

0

AFAIK, isso {} está tentando nos modelos Jinja2 e não nos arquivos yml. A partir da documentação :

ansible permite loops e condicionais Jinja2 em modelos, mas em playbooks, não os usamos.

Você pode preparar um arquivo .yml separado com uma reprodução que configure as variáveis ​​necessárias usando as cláusulas when e depois importá-las (ou incluí-las) em seu playbook principal. Dessa forma, você pode ter todos os vars definidos condicionalmente em um único arquivo.

OU: Use funções. Acho que os papéis são a abordagem mais adequada para resolver seu problema.


0

O que eu fiz no final foi criar 2 arquivos var separados - vamos chamá-los type_a.ymle type_b.yml- e eu defini uma variável de grupo que indica qual arquivo usar - algo assim type_of_file: a. É assim que o meu manual se parece agora:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/type_{{ type_of_file }}.yml
  roles: blabla

Obrigado por todas as respostas. Eu os acho realmente úteis.


0

Espero que o seguinte trecho (retirado da Ansible Documentation ) faça uma adição útil às contribuições úteis de outras pessoas acima.

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename
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.