Qual é a diferença entre padrões e vars em um papel Ansible?

151

Ao criar uma nova função Ansible, o modelo cria a varse um defaultsdiretório com um main.ymlarquivo vazio . Ao definir minha função, posso colocar definições de variáveis ​​em qualquer uma delas e elas estarão disponíveis em minhas tarefas.

Qual é a diferença entre colocar as definições em defaultse vars? O que deve entrar defaultse o que deve entrar vars? Faz sentido usar os dois para os mesmos dados?

Sei que há uma diferença de precedência / prioridade entre os dois, mas gostaria de entender o que deve ir aonde.

Digamos que minha função criaria uma lista de diretórios no sistema de destino. Gostaria de fornecer uma lista de diretórios padrão a serem criados, mas gostaria de permitir que o usuário os substitua ao usar a função.

Aqui está como isso seria:

---
- directories:
  - foo
  - bar
  - baz

Eu poderia colocar isso no defaults/main.ymlou no vars/main.yml, de uma perspectiva de execução, não faria diferença - mas para onde deveria ir?

nwinkler
fonte

Respostas:

113

A documentação Ansible sobre precedência variável resume este niceley:

Se várias variáveis ​​com o mesmo nome são definidas em locais diferentes, elas vencem em uma determinada ordem, que é:

  • Vars extras (-e na linha de comando) sempre vencem
  • então vem as variáveis ​​de conexão definidas no inventário (ansible_ssh_user, etc)
  • depois vem "quase tudo o resto" (opções de linha de comando, vars em jogo, vars incluídos, vars de função etc.)
  • depois vem o restante das variáveis ​​definidas no inventário
  • depois vem fatos descobertos sobre um sistema
  • depois, os "padrões de função", que são os mais "padrão" e perdem prioridade em tudo.

Portanto, suponha que você tenha uma função "tomcat" usada para instalar o Tomcat em vários webhosts, mas você precisa de versões diferentes do tomcat em alguns hosts, para executar como usuários diferentes em outros casos, etc. O defaults/main.ymlarquivo pode parecer algo assim:

tomcat_version: 7.0.56
tomcat_user: tomcat

Como esses são apenas valores padrão, significa que serão usados ​​se essas variáveis ​​não forem definidas em nenhum outro lugar para o host em questão. Você pode substituí-los por extra-vars, por fatos em seu arquivo de inventário, etc. para especificar valores diferentes para essas variáveis.

Editar: Observe que a lista acima é para Ansible 1.x. No Ansible 2.x, a lista foi expandida. Como sempre, a Documentação Ansible fornece uma descrição detalhada da precedência de variável para 2.x.

Bruce P
fonte
4
Obrigado, é uma excelente página - era o que eu estava procurando. Entro em muito mais detalhes sobre o que colocar defaultse o que varsmais adiante.
Nwinkler
42
vale a pena enfatizar: os colares de papéis têm uma precedência muito alta . na minha experiência, eles são mais altos do que play vars, o que é realmente irritante.
tedder42
Cinco anos depois, mas ... Eu costumo olhar dessa maneira: padrões de função são coisas que eu espero que um usuário da função substitua em seus vars em algum lugar. Vars de função, OTOH, permitem evitar informações codificadas em uma tarefa, mas provavelmente serão substituídas apenas para teste e alteradas por um mantenedor de função. Como exemplo, um nome de usuário de administrador inicial estaria em padrões, mas as versões de dependência em vars.
ntwrkguru 8/06
41

As variáveis ​​de função definidas em vartêm uma precedência muito alta - elas só podem ser substituídas passando-as na linha de comando, na tarefa específica ou em um bloco. Portanto, quase todas as suas variáveis ​​devem ser definidas em defaults.

No artigo " Precedência variável - onde colocar suas funções ", o autor fornece um exemplo do que colocar vars: constantes constantes do sistema que não mudam muito. Portanto, você pode ter vars/debian.ymle vars/centos.ymlcom os mesmos nomes de variáveis, mas com valores diferentes e incluí-los condicionalmente.

Chiborg
fonte
3

IMHO é impraticável e não sensato que lugares ansible como alta prioridade à configuração no vars de papéis . A configuração vars/main.ymle defaults/main.ymldeve ser baixa e provavelmente a mesma prioridade.

Existem exemplos reais de casos em que queremos esse tipo de comportamento?

Existem exemplos de que não queremos isso.

O ponto a ser destacado aqui é que a configuração defaults/main.ymlnão pode ser dinâmica. Configuração no vars/main.ymlcan. Portanto, por exemplo, você pode incluir a configuração para SO e versão específicos dinamicamente, conforme mostrado em geerlingguy.postgresql

Mas como a precedência é tão estranha e impraticável no Ansible, o geerlingguy precisa introduzir pseudo variáveis, como pode ser visto nas variáveis.yml

- name: Define postgresql_packages.
  set_fact:
    postgresql_packages: "{{ __postgresql_packages | list }}"
  when: postgresql_packages is not defined

Este é um exemplo concreto da vida real que demonstra que a precedência é impraticável.

Outro ponto a ser destacado aqui é que queremos que as funções sejam configuráveis. As funções podem ser externas, gerenciadas por outra pessoa. Como regra geral, você não deseja que a configuração em funções tenha alta prioridade.

onknows
fonte
Isso deve ser um comentário, não uma resposta.
ntwrkguru 8/06
3

Basicamente, tudo o que entra em "padrões da função" (a pasta de padrões dentro da função) é o mais maleável e facilmente substituído. Qualquer coisa no diretório vars da função substitui as versões anteriores dessa variável no espaço para nome. A idéia a seguir é que, quanto mais explícito você entrar no escopo, maior será a precedência da linha de comando - e vars extras sempre ganhando. Variáveis ​​de host e / ou inventário podem conquistar padrões de função, mas não inclusões explícitas, como o diretório vars ou uma tarefa include_vars. doc

pauljolsen
fonte
-4

Variáveis ​​e padrões andam de mãos dadas. aqui está um exemplo

-name: install package
 yum: name=xyz{{package_version}} state=present

no seu arquivo de padrões, você teria algo como:

package_version: 123

O que o ansible fará é, ele pegará o valor package_versione o colocará ao lado do nome do pacote para que ele seja lido em algum lugar como:

-name: install package
 yum: name=xyz123 state=present

Dessa forma, ele será instalado xyz123e não xyz123.4ou o que estiver no grande repositório do xyz's.

No final, ele fará yum install -y xyz123

Então, basicamente, os padrões são os valores presentes; se você não definir um valor específico para as variáveis, esse espaço não poderá ficar vazio.

qubsup
fonte
Votado porque não aborda a questão. Obviamente, defaultssão usados ​​quando não há varsdefinições, mas a resposta não explica por que você definiria um valor como um ou outro, que é o que o OP pediu. Compare com a explicação abaixo.
Thomas Hirsch