Odpowiedź: Wykonaj zadanie tylko wtedy, gdy podany jest znacznik

76

Znaczników Ansible można używać do uruchamiania tylko podzbioru zadań / ról. Oznacza to, że domyślnie wszystkie zadania są wykonywane i możemy tylko uniemożliwić wykonanie niektórych zadań.

Czy możemy ograniczyć wykonanie zadania tylko wtedy, gdy podany jest tag „foo”? Czy możemy użyć bieżących tagów w whensekcji zadania?

Taha Jahangir
źródło
2
wygląda na to, że potrzebujesz jakiegoś ustawienia zadania, takiego jak limit_to_tags: foo, które nie istnieje i nie sądzę, aby było to w tej chwili możliwe. Przyszła implementacja musi również mieć plan określający, czy AND lub OR te znaczniki razem.
dgh
Spójrz na moją odpowiedź w „Ansible - Default / Explicit Tags” stackoverflow.com/questions/28789912/…
sirkubax

Odpowiedzi:

38

Ansible 2.5 jest wyposażony w specjalne tagi neveri always. Tag nevermoże być używany dokładnie w tym celu. Na przykład:

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

W tym przykładzie zadanie zostanie uruchomione tylko wtedy, gdy znacznik debug(lub never) zostanie wyraźnie zażądany. [Odniesienie do ansible docs]

Taha Jahangir
źródło
20

Chociaż jest to rozwiązanie okrężne, działa.

Wewnątrz listy zadań zarejestruj zmienną, gdy uruchomione zostanie normalne wykonanie. Następnie dodaj warunek when, który sprawdza tę zmienną do oznaczonego zadania.

- 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
źródło
Możesz także użyć untaggeddo tego:- set_fact: untagged_run=true tags: untagged
Pyzo
Czy możesz wyjaśnić coś więcej na ten temat? Przykład z prawdziwego świata?
Quintin Par
17

Nie mam wystarczającej reputacji, aby głosować lub komentować odpowiedź sugerującą użycie zmiennych wiersza poleceń ( --extra-vars), ale muszę to dodać:

Zastrzeżeniem tej metody jest to, że gra będzie zawierać błędy i nie powiedzie się, jeśli nie zdefiniujesz tej dodatkowej zmiennej.

Można zapobiec niepowodzeniu odtwarzania w przypadku braku --extra-varsdefinicji, definiując wartość domyślną w samym podręczniku:

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

Przesłanianie przez --extra-varsnadal będzie działać, ponieważ zmienne zdefiniowane w wierszu poleceń mają pierwszeństwo przed wszystkimi innymi definicjami.

W rezultacie gra działa bezbłędnie, gdy thoroughnie jest zmieniana truena w wierszu poleceń.

Alex Peters
źródło
5
To samo można osiągnąć za pomocą thorough | default('no') | bool.
Costi Ciudatu,
2
Lub when: thorough is defined and thoroughjeśli wolisz tę składnię
KCD
Dzięki, bardziej podoba mi się is defined andskładnia. więcej niż wiele rur, które nie uważam za intuicyjne.
Elijah Lynn
10

Możesz użyć warunkowego, aby zabezpieczyć się przed przypadkowo uruchomionymi zadaniami, które w innym przypadku zostałyby wykonane, jeśli nie podasz tagu. Zastrzeżeniem tej metody jest to, że gra będzie zawierać błędy i nie powiedzie się, jeśli nie zdefiniujesz tej dodatkowej zmiennej.

Za pomocą argumentu extra-vars możesz uruchomić warunek do wykonania.

Z ansible-playbook --help:

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

Przykład:

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
źródło
2
Aby uniknąć błędu, jeśli nie zdefiniujesz „dokładnego”, po prostu użyj thorough | default("false") | match("true"). Domyślnie nie musi tak być false, po prostu wszystko co nie pasuje true, ale poprawia czytelność.
Tom Wilson,
4

Sprawdzanie zmiennej „tags” nie działa w Ansible 2.1.1.0. Test poniżej. Mam inny pomysł na wykonanie zadania tylko wtedy, gdy znacznik jest zdefiniowany, działając zarówno dla Ansible 1.9.X, jak i 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

Dzięki temu podczas uruchamiania playbooka bez tagu zmienna „foo” zostanie ustawiona na true, a następnie na false, więc nic nie zostanie wykonane. Jeśli dodasz znacznik „bar”, zastosowane zostanie tylko pierwsze ustawienie, więc zmienna „foo” będzie prawdziwa, a następnie twoje zadanie zostanie wykonane. Cieszyć się!


A oto test dotyczący zmiennej „tags” w Ansible 2.1.1.0:

Oto podręcznik:

- 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

A oto wynik:

$ 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
źródło
2

Tak. Uruchomienie ansible-playbook z --tags fooflagą zapewni, że tylko zadania oznaczone tagiem foozostaną wykonane. Załóżmy na przykład, że mamy podręcznik o nazwie example.yml:

tasks:

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

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

bieganie:

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

Upewni się, że wykonano tylko mniam zadanie.

Tak naprawdę tak naprawdę nie musisz używać tagów w sekcji, gdy warunkowo wykonujesz zadanie. Zauważ, że w zależności od złożoności twoich podręczników / ról może być konieczne użycie kombinacji --tags i --skip-tags, aby kontrolować, które zadania są wykonywane. Na przykład, jeśli zadania dołączania są oznaczone jako „foo”, a niektóre zadania w dołączonym podręczniku są oznaczone jako „pasek” i uruchomisz

ansible-playbook --tags "foo"

Zadanie wewnętrzne (oznaczone tylko jako „pasek”) zostanie wykonane. Aby uniknąć wykonywania wszystkich zadań wewnętrznych oznaczonych jako „bar”, musisz wykonać następujące polecenie

ansible-playbook --tags foo --skip-tags bar
Shahar
źródło
7
To nie jest prawda: „Określenie znacznika w zadaniu oznacza, że ​​zadanie zostanie wykonane tylko wtedy, gdy ten znacznik zostanie przekazany jawnie do komendy ansible-playbook.”
gimboland
1
Po drugie, stwierdzenie nie jest prawdziwe.
Chris,
10
tak, możesz osiągnąć takie zachowanie, upewniając się, że zawsze używasz właściwych ansible-playbookopcji, ale myślę, że OP prosi o sposób na adnotację zadania, aby nie zostało ono wykonane, chyba że w ansible-playbookpoleceniu zostanie wyraźnie dodany określony znacznik .
dgh
4
Tak, to nie odpowiada na pytanie PO.
Allen Luce
wszystkie akcje oznaczone / nieoznaczone są uruchamiane, gdy nie podasz tagu. Tagi nie mogą wykluczyć działania do uruchomienia, obejmują tylko. Nie ma logiki predykatów oprócz filtra addytywnego.
bbaassssiiee
1

Istnieje specjalny znacznik - „nigdy” , który uniemożliwi uruchomienie zadania, chyba że znacznik jest wyraźnie wymagany.

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]
xtoznaxto
źródło
Wspomniano już w powyższej odpowiedzi: serverfault.com/a/907329/105928
Taha Jahangir
0

kiedy klauzula nie może ocenić obecności tagów. Aby obejść ten problem, używam zmiennych i tagów razem do uruchamiania zadań specyficznych dla tej zmiennej / tagu.

Przykład: Wyobraź sobie podręcznik i ekwipunek

# Inwentarz
[dev]
192.168.1.1

# site.yml
- gospodarze: dev
  role:
    - {rola: wspólna}

i we wspólnym / task / main.yml

# role / common / tasks / main.yaml
- nazwa: zainstaluj linki
  apt: name = links state = present

- obejmują: uninstall.yml
  kiedy zdefiniowano: uninstall_links
  tagi:
    - odinstaluj

# role / common / tasks / uninstall.yml
- nazwa: odinstaluj łącza
  apt: name = links state = nieobecny

Przy takim podejściu używasz znacznika, aby wybrać tylko zadania w uninstall.yml, ale musisz również ustawić zmienną „uninstall_links” na coś, aby ją włączyć. Jeśli więc uruchomisz playbook bez żadnych parametrów, domyślnie uruchomi się zadanie instalacji. Aby odinstalować, możesz ustawić znacznik „odinstaluj” w swoim playbooku (lub cmdline) i MUSISZ ustawić zmienną. Jeśli nie ustawisz tagu, uruchomi on wszystko (zainstaluje i odinstaluje) w tej kolejności, co jest dobre do przetestowania całego procesu.

Jak uruchomić wszystko (zainstaluje się i odinstaluje):

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

Jak uruchomić tylko tag „odinstaluj” w grupie programistów

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

Dlatego zmienne i tagi mogą również znajdować się w plikach site.yml / inventory, umożliwiając zatwierdzenie w SCM i zarejestrowanie zamiaru.

Anderson Goulart
źródło
0

nootal ma rację, moje podejście nie działa - zignoruj ​​:( Teraz używam „kiedy: myvar jest zdefiniowany” i przełącznika wiersza poleceń „-e” myvar = X ”, aby wykonywać zadania tylko na wyraźne żądanie.

Jeszcze łatwiejsze (przynajmniej z ansible 2.1.1.0):

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

-> uruchomi się tylko wtedy, gdy tagi zostały dostarczone ORAZ tagi zawierają „foo”

DrPsychick
źródło
0

On Ansible 2.3.2.0tu jest moje rozwiązanie problemu:

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

Zaczyna się od ustawienia, in_tagaby Truebyło to ustawienie, set_factktóre włącza go ponownie, Falsegdy nie określisz żadnego tagsz ansible-playbook.

Gdy określisz tagi, in_tagpozostanie Truei failzadanie zostanie uruchomione.

PS: możesz dodać logikę do dowolnych zadań

PS2: możesz również rozszerzyć logikę i kodować na stałe wszystkie tagi, które masz, i oczywiście set_fact: in_tag_blah=Truew połączeniu z nimi tags: ["blah"].

tehmoon
źródło