Resolvido: Execute a tarefa somente quando uma tag for especificada

75

Tags possíveis podem ser usadas para executar apenas um subconjunto de tarefas / funções. Isso significa que, por padrão, todas as tarefas são executadas e só podemos impedir a execução de algumas tarefas.

Podemos limitar uma tarefa a ser executada apenas quando a tag "foo" for especificada? Podemos usar tags atuais na whenseção de uma tarefa?

Taha Jahangir
fonte
2
parece que você precisa de alguma configuração de tarefa como limit_to_tags: foo que não existe e eu não acho que isso seja possível no momento. Uma implementação futura também precisa ter um plano para AND ou OR essas tags juntas.
dgh
Dê uma olhada na minha resposta em "Ansible - Tags padrão / explícitas" stackoverflow.com/questions/28789912/…
sirkubax 9/15/15

Respostas:

38

O Ansible 2.5 vem com tags especiais nevere always. A tag neverpode ser usada exatamente para esse fim. Por exemplo:

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]

Neste exemplo, a tarefa será executada apenas quando a tag debug(ou never) for solicitada explicitamente. [Referência em documentos ansible]

Taha Jahangir
fonte
20

Embora seja uma solução indireta, ela funciona.

Dentro da lista de tarefas, registre uma variável quando a execução normal for executada. Em seguida, adicione uma condição when que verifique essa variável na tarefa marcada.

- shell: /bin/true
  register: normal_task_list

- name: Only run when tag is specified
  shell: /bin/echo "Only running because of specified tag"
  when: normal_task_list is not defined
  tags: specified
Chris Chipman
fonte
Você também pode usar untaggedpara fazer isso:- set_fact: untagged_run=true tags: untagged
Pyzo 28/11
Você pode explicar um pouco mais sobre isso? Um exemplo do mundo real?
Quintin Par
17

Não tenho reputação suficiente para votar ou comentar a resposta que sugere o uso de variáveis ​​de linha de comando ( --extra-vars), mas tenho isso a acrescentar:

A ressalva deste método é que a jogada irá errar e falhar se você não definir essa variável extra.

Você pode impedir a falha na reprodução na ausência de uma --extra-varsdefinição, definindo um valor padrão no próprio manual:

---
- hosts: ...
# ↓↓↓
  vars:
    thorough: false
# ↑↑↑
  tasks:
  - name: apt - install nfs-common only when thorough is true
    when: thorough | bool
    apt:
      cache_valid_time: 86400
      force: yes
      pkg:
        - nfs-common

A substituição via --extra-varsainda funcionará porque as variáveis ​​definidas na linha de comando têm precedência sobre todas as outras definições.

O resultado é que a reprodução é executada sem erro quando thoroughnão é alterada para truena linha de comando.

Alex Peters
fonte
5
O mesmo pode ser alcançado usando thorough | default('no') | bool.
Costi Ciudatu 10/10
2
Ou when: thorough is defined and thoroughse você preferir que a sintaxe
KCD
Obrigado, ame mais a is defined andsintaxe. mais do que os múltiplos canos que não considero intuitivos.
Elias Lynn
10

Você pode usar Condicionais para se proteger contra tarefas em execução acidental que, caso contrário, seriam executadas se você não especificar uma tag. A ressalva deste método é que a jogada irá falhar e falhar se você não definir essa variável extra.

Usando o argumento extra-vars, você pode ativar sua condicional para ser executada.

Do ansible-playbook --help:

 -e EXTRA_VARS, --extra-vars=EXTRA_VARS
    set additional variables as key=value or YAML/JSON

Exemplo:

ansible-playbook test.yaml -e "thorough=true"

test.yaml:

...
- name: apt - install nfs-common only when thorough is true
  apt:
    cache_valid_time: 86400
    force: yes
    pkg:
    - nfs-common
  when: thorough | default(False)
...
Ava
fonte
2
Para evitar um erro, se você não definir "completo", basta usar thorough | default("false") | match("true"). O padrão não precisa ser false, apenas algo que não corresponda true, mas melhora a legibilidade.
Tom Wilson
4

Verificar a variável 'tags' não está funcionando no Ansible 2.1.1.0. Veja abaixo o teste. Eu tenho uma outra idéia para executar tarefas apenas quando uma tag é definida, trabalhando para o Ansible 1.9.X e 2.XY:

- set_fact: foo=true
  tags: bar
- set_fact: foo=false
- name: do something when 'bar' tag is defined
  debug: var=foo
  when: foo
  tags: bar

Com isso, ao executar o playbook sem nenhuma tag, a variável 'foo' será configurada como true e depois false, para que nada seja executado. Se você adicionar a tag 'bar', somente a primeira configuração será aplicada; portanto, a variável 'foo' será verdadeira; sua tarefa será executada. Desfrutar!


E aqui está o teste sobre a variável 'tags' no Ansible 2.1.1.0:

Aqui está o manual:

- hosts: localhost
  connection: local
  tasks:
    - name: display tags variable
      debug: var=tags
      tags: foo

    - name: do something only when tag 'foo' is provided
      debug: var=tag
      when: tags is defined
      tags: foo

E aqui está a saída:

$ ansible-playbook --version ; ansible-playbook ./test.yml -t foo
ansible-playbook 2.1.1.0
  config file = /home/nootal/projects/ivy/src/ansible/ansible.cfg
  configured module search path = Default w/o overrides

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

TASK [display tags variable] ***************************************************
ok: [localhost] => {
    "tags": "VARIABLE IS NOT DEFINED!"
}

TASK [do something only when tag 'foo' is provided] ****************************

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0   
nootal
fonte
2

Sim. A execução do ansible-playbook com o --tags foosinalizador garantirá que apenas as tarefas marcadas foosejam executadas. Por exemplo, suponha que tenhamos um manual chamado example.yml:

tasks:

  - yum: name={{ item }} state=installed
    with_items:
       - httpd
       - memcached
    tags:
       - packages

  - name: some other task
    ..
    tags:
      - some other tag

corrida:

ansible-playbook example.yml --tags "packages"

Garantirá que apenas a tarefa yum seja executada.

Então, na verdade, você não precisa usar tags na seção when para executar condicionalmente uma tarefa. Observe que, dependendo da complexidade de seus playbooks / funções, pode ser necessário usar uma combinação de --tags e --skip-tags para controlar quais tarefas são executadas. Por exemplo, se uma tarefa de inclusão estiver marcada como 'foo' e alguma tarefa dentro do manual incluído estiver marcada como 'barra' e você executar

ansible-playbook --tags "foo"

A tarefa interna (marcada apenas como 'barra') será executada. Para evitar a execução de todas as tarefas internas marcadas como 'bar', você deverá executar o seguinte comando

ansible-playbook --tags foo --skip-tags bar
Shahar
fonte
7
Isso não é verdade: "A especificação de uma marca em uma tarefa significa que somente quando ela for passada explicitamente para o comando ansible-playbook, essa tarefa será executada."
gimboland
1
Destacada, a afirmação não é verdadeira.
Chris
10
Sim, você pode obter o comportamento garantindo sempre o uso das ansible-playbookopções corretas , mas acho que o OP está pedindo uma maneira de anotar uma tarefa para que não seja executada, a menos que uma tag específica seja explicitamente adicionada ao ansible-playbookcomando.
dgh
4
Sim, isso não está respondendo à pergunta do OP.
Allen Luce
todas as ações marcadas / não marcadas são executadas quando você não especifica uma tag. Tags não podem excluir uma ação a ser executada, apenas incluir. Não há lógica de predicado, exceto para um filtro aditivo.
bbaassssiiee 22/09
1

Há uma tag especial - "never" , que impedirá a execução de uma tarefa, a menos que uma tag seja solicitada especificamente.

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]
xtoznaxto
fonte
Já mencionado na resposta acima: serverfault.com/a/907329/105928
Taha Jahangir
0

A cláusula when não pode avaliar a presença de tags. Como solução alternativa, uso variáveis ​​e tags juntas para executar tarefas específicas a essa tag / variável.

Ex: imagine um manual e um inventário

# inventário
[dev]
192.168.1.1

# site.yml
- hosts: dev
  funções:
    - {role: common}

e em comum / tasks / main.yml

# papéis / comum / tarefas / main.yaml
- nome: instalar links
  apt: nome = estado dos links = presente

- inclua: uninstall.yml
  quando: uninstall_links estiver definido
  Tag:
    - Desinstalar

# role / common / tasks / uninstall.yml
- nome: Desinstalar links
  apt: nome = estado dos links = ausente

Com essa abordagem, você usa a tag para selecionar apenas as tarefas em uninstall.yml, mas também precisa definir a variável 'uninstall_links' para algo que a habilite. Portanto, se você executar o manual sem nenhum parâmetro, ele executará, por padrão, a tarefa de instalação. Para desinstalar, você pode definir a tag 'uninstall' como seu playbook (ou cmdline) e DEVE definir a variável. Se você não definir a tag, ela executará tudo (instalar e desinstalar) nessa ordem, o que é bom para testar todo o processo.

Como executar tudo (ele será instalado e desinstalado):

$ ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true"

Como executar apenas a tag 'uninstall' no grupo dev

$ ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true" -t uninstall

Portanto, variáveis ​​e tags também podem estar nos arquivos site.yml / inventário, permitindo que você se comprometa com seu SCM e registre sua intenção.

Anderson Goulart
fonte
0

nootal está certo, minha abordagem não funciona - ignore-a :( Agora eu uso "when: myvar is defined" e a linha de comando "-e" myvar = X "para executar tarefas apenas quando solicitadas explicitamente.

Ainda mais fácil (pelo menos com o ansible 2.1.1.0):

- name: do something only when tag 'foo' is provided
  when: tags is defined
  tags: foo

-> só será executado quando as tags forem fornecidas E as tags incluem "foo"

DrPsychick
fonte
0

Em Ansible 2.3.2.0, aqui está minha solução para o problema:

---
- hosts: localhost
  gather_facts: no
  vars:
    in_tag: yes
  tasks:
    - set_fact: in_tag=no
    - fail:
        msg: "recently_added is set and you're using blah tag"
      when: ( in_tag | bool )
      tags:
        - blah
    - debug:
        msg: "always remember"

Ele começa definindo in_tagpara True, em seguida, há uma set_factque define-lo de volta para Falsequando você não especificar qualquer tagsde ansible-playbook.

Quando você especifica tags, in_tagpermanece em Truee a failtarefa é executada.

PS: você pode adicionar a lógica a qualquer tarefa que desejar

PS2: você também pode estender a lógica e codificar todas as tags que você possui e set_fact: in_tag_blah=Trueem combinação com, é tags: ["blah"]claro.

tehmoon
fonte