Seite wählen

NETWAYS Blog

Ansible – Loop over multiple tasks

ansible logo

The last time I wrote about Ansible and the possibility to use blocks to group multiple tasks. Which you can read here. Sadly this feature does not work with loop, so there is no clean way to loop over multiple tasks in a play without writing the same loop statement at tasks over and over.

But when we come across the need of tasks which depend on each other, for example, we execute a script with a certain parameter and its result is necessary for the upcoming tasks.

Let’s go through a common example, creating a site consists of a few steps. Creating the directory, creating the vhost and then enabling the site.


- name: "create {{ site }} directory"
  file:
    ensure: directory
    dest: "/var/www/{{ site }}"
    
- name: "create {{ site }}"
  template:
    src: vhost.j2
    dest: "/etc/apache2/sites-available/{{ site }}"
  register: vhost

- name: "enable {{ site }}"
  command: /usr/sbin/a2ensite "{{ site }}"
  register: result
  when: vhost.changed
  changed_when: "'Enabling site' in result.stdout"
  notify: apache_reload

We could use a loop for each tasks and afterwards find the right result for the next task to depend on. But the styleguide will warn you if you try to use Jinja2 syntax in when statements.

So the best solution to this is to use include_tasks, which can include a file with tasks. This task is allowed to have a loop directive and so we can include it multiple times.
Lets see how this would apply to our scenario:


- set_fact:
    sites:
      - default
      - icingaweb2

- name: create vhosts
  include_tasks: create-vhosts.yml
  loop: "{{ sites }}"
  loop_control:
    loop_var: site


In the Result we can see clearly that all tasks are applied for each element in the sites variable.


TASK [set_fact] *********************************************
ok: [localhost]

TASK [create vhosts] ****************************************
included: /Users/twening/Documents/netways/ansible_test20/create-vhosts.yml for localhost => (item=default)
included: /Users/twening/Documents/netways/ansible_test20/create-vhosts.yml for localhost => (item=icingaweb2)

TASK [create default directory] *****************************
ok: [localhost]

TASK [create default] ***************************************
ok: [localhost]

TASK [enable default] ***************************************
ok: [localhost]

TASK [create icingaweb2 directory] **************************
ok: [localhost]

TASK [create icingaweb2] ************************************
ok: [localhost]

TASK [enable icingaweb2] ************************************
ok: [localhost]

PLAY RECAP **************************************************
localhost                  : ok=10   changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


Check out our Blog for more awesome posts and if you need help with Ansible send us a message or sign up for one of our trainings!

Thilo Wening
Thilo Wening
Consultant

Thilo hat bei NETWAYS mit der Ausbildung zum Fachinformatiker, Schwerpunkt Systemadministration begonnen und unterstützt nun nach erfolgreich bestandener Prüfung tatkräftig die Kollegen im Consulting. In seiner Freizeit ist er athletisch in der Senkrechten unterwegs und stählt seine Muskeln beim Bouldern. Als richtiger Profi macht er das natürlich am liebsten in der Natur und geht nur noch in Ausnahmefällen in die Kletterhalle.

Daily business: der Editor vim

Es ist unerfreulich lange her, dass ich das erste Mal mit vim in Berührung kam — anno 1997, um genau zu sein, während meiner ersten verzweifelten Gehversuche in Sachen S.u.S.E. Linux. Oder war das noch vi? So irgendwie habe ich das Tool über die Jahre dann hinter mir her geschleift wie eine altmodische Handtasche, mich aber viel zu spät erst ernsthafter damit befasst — ein blöder Fehler, vor dem ich einige von euch ja vielleicht bewahren kann. Denn was viele (und gerade auch Neueinsteiger) gar nicht zu ahnen scheinen: vim ist üblicherweise auf Systemen vorhanden, kann viel, ist ziemlich cool und in der Handhabung auch gar nicht so widerlich, wenn man sich erst leidlich eingearbeitet hat.

Die Konfiguration des Editors erfolgt in einer Textdatei namens .vimrc, welche im $HOME-Verzeichnis des jeweiligen Nutzers liegen muss. Beginnen wir diese Datei mit nocompatible: denn ein compatible vim ist lediglich noch ein vi, sprich alle nützlichen Erweiterungen und Errungenschaften der letzten 20 Jahre würden abgeschaltet — und wer will das schon?

set nocompatible " Using vim settings and not vi

Widmen wir uns also einigen kleinen Kniffen, die mir für die tägliche Arbeit inzwischen unverzichtbar geworden sind: naturgemäß (und da ich gerade einen Haufen müffelnden Puppet-Codes in Richtung Ansible transportieren darf) editiere ich aktuell häufig an YAML-Dateien herum, und da ist das Thema „Einrückungen“ beispielsweise sehr relevant: YAML kennt, plump gesagt, keine Tabs, und so bewährt es sich sehr in der persönlichen .vimrc bereits festzuhalten, dass ein Tab beispielsweise durch zwei Leerzeichen ersetzt wird und Einrückungen ebenfalls zwei Leerzeichen betragen sollen. Protipp: Lasst außerdem über existierende Dateien ein :retab laufen, so dass alle eventuell vorhandenen Tabs gemäß eurer Konfiguration in Leerzeichen umgesetzt werden — die Einstellungen greifen nicht automatisch bei bereits bestehendem Text. Und: möchtet ihr YAML anders einrücken als beispielsweise C oder PHP, so beschäftigt euch mit den Möglichkeiten, die autocmd bietet!

set autoindent " Guess what?
filetype plugin indent on " Enable indenting for files
set backspace=indent,eol,start " Allow backspacing over indention/ line breaks/ insertion start
set softtabstop=2 " Indent 2 spaces when hitting TAB
set shiftwidth=2 " Indend 2 spaces when autoindent
set tabstop=2 " Show existing tab with 2 spaces width
set expandtab " Convert tabs into spaces

Gerade bei YAML hilft es mir häufig sehr wenn ich sehe, an welcher Stelle im Dokument ich mich gerade befinde; deshalb lasse ich mir die Zeilen durchnummerieren und mittels Unterstreichung die aktuelle Position anzeigen. Syntax Highlighting ist natürlich großartig, das will ich unbedingt, und durch eine einfache Anweisung sorgt zukünftig für die visuelle Hervorhebung zusammengehörender Klammern. Protipp: während number die Zeilen aufsteigend durchnummeriert, stellt relativenumber die Zeilennummern relativ zur aktuellen Position dar.

set number " Enable line numbers
syntax on " Set syntax highlighting
set showmatch " Show matching brackets
set cursorline " Highlight line under cursor
set cursorcolumn " Highlight column

Was bei der täglichen Arbeit hilft: eine Statuszeile, die mit genau jenen Informationen aufwartet, die persönlich hilfreich sind. In meinem Fall sind das Angaben wie Dateiname, beispielsweise, Dateityp oder an welcher Stelle — prozentual gesehen — ich mich innerhalb meiner Datei gerade befinde. Für euch sind hier vielleicht ganz andere Informationen wichtig, weshalb ich euch die Lektüre der entsprechenden Dokumentation ans Herz legen möchte.

set laststatus=2 " Show status line
set statusline=%t " tail of filename
set statusline+=\ %{&ff} " File format
set statusline+=\ %y " Filetype
set statusline+=\ %c, " Cursor column
set statusline+=%l/%L " Cursor line/ total lines
set statusline+=\ %P " Percent through file

Was ich wirklich zu lieben lernte: undo und redo. Die Basics kennen noch die meisten: u macht die letzte Änderung rückgängig, uuu die letzten drei und 5u die letzten fünf. Wirklich interessant wird das allerdings, wenn man es mit Zeiträumen verbindet: so macht earlier 2m (alternativ: ea 2m) die Änderungen der letzten zwei Minuten rückgängig, wohingegen later 5m (alternativ: lat 5m) alle Änderungen der letzten fünf Minuten wiederherstellt. Die Sache hat nur einen Haken: wie fast überall sind diese Statements nur innerhalb der laufenden Sitzung möglich; wird der Editor beendet und die gleiche Datei später erneut editiert, ist keine History der bisherigen Änderungen verfügbar.
Wenig überraschend lässt sich auch das anpassen: über set undofile weisen wir vim an, die Änderungen jeder Datei zu persistieren; vim tut das dann jeweils in Form eines hidden file an gleicher Stelle, was auf Dauer etwas unübersichtlich werden könnte. Erstellen wir mittels mkdir ~/.vim/undo ein eigenes Verzeichnis für Dateien dieser Art, können wir vim aber auch instruieren all diese Änderunsdateien dort vorzuhalten. Das erlaubt dann auch umfangreiche Zeitsprünge: ea 3d wird die Änderungen der letzten drei Tage rückgängig machen.

set undofile " Undo history even between sessions
set undodir=~/.vim/undo " All undo files in one directory

Zuguterletzt verpassen wir unserem vim ein hübsches colorscheme — eine Auswahl solch vordefinierter Farbschemata findet sich, in Abhängigkeit verwendeter Version und Distribution, üblicherweise in /usr/share/vim/vim$VERSION/colors/ in Form von .txt-Dateien. Ich entscheide mich für desert, ihr könnt euch aussuchen was euch am besten gefällt und versiertere Nutzer erstellen sich ihre colorschemes später dann ohnehin selber… Und wenn wir ohnehin gerade mit Farbgebungen spielen lassen wir uns die Zeilennummer spaßeshalber rot hinterlegen, während die Hervorhebung der Spalte in einem aufdringlichen hellen Magenta erfolgen soll. Einschub: eine Liste verfügbarer Farben lässt sich aus vim heraus unkompliziert mit dem Kommando :h cterm-color abrufen.

colorscheme desert " Setting nice colors
highlight CursorLineNR ctermbg=red
highlight CursorColumn ctermbg=LightMagenta

Es gäbe noch So! Viel! Mehr! Belassen wir es für heute mal dabei. Eine einsatzbereite exemplarische vimrc-demo findet ihr auf GitHub; sie ist nicht als „finale Fassung“ zu verstehen sondern vielmehr als Ausgangspunkt für die Erarbeitung einer persönlichen und über die Zeit immer perfekteren Version. Und vielleicht wollt ihr über die Kommentare verraten, ob Artikel dieser Art hilfreich für euch sind — und welche Einstellung, welches Plugin, welcher Kniff für euch unverzichtbar ist?

Marianne Spiller
Marianne Spiller
Senior Consultant

Nachdem sie über Jahre immer wieder für eine NETWAYS Mitarbeiterin gehalten wurde, hat sie im März 2020 ernst gemacht und wurde eine. Als Senior Consultant unterstützt sie fortan Professional Services. Ihre Freizeit widmet sie in weiten Teilen dem Schreiben, man findet sie aber auch häufig mit Kamera und Stativ auf unwegsamem Gelände.

DevOpsDays Berlin cancelled

The DevOpsDays Berlin have been cancelled for this year due to Corona. “Though there were good arguments for running the conference, most of us felt uncomfortable to expose people to a potential danger that isn’t fully understood yet”, the organizers said. They decided to suspend the event in 2020 and to hold it again in 2021. Holding the conference online was not really an option for the Berlin crew. Other DevOpsDays who did an online version of their event had great success with the attendee numbers, but they felt that this would miss out with the most important part of the conference: Bringing people together in person and the community aspect of the event. The Berlin organizers are planning an event for 2021, which can be expected to fall into the same time as this or the last years: Beginning to middle of fall 2021.

Entries from this Call for Papers won’t be kept for next year (“because the only thing older than a ‘Tech Talk’ from a year ago is yesterday’s newspaper”). Who already proposed would need to create a new entry next year. The DevOpsDays Berlin organizers thank all speakers for their awesome talk and session proposals this year, and encourage and invite people to propose again in 2021.

Keep an eye on https://devopsdays.berlin/ or on the Twitter feed @blndevops to stay informed and get the new dates.

Julia Hornung
Julia Hornung
Senior Marketing Manager

Julia ist seit Juni 2018 bei NETWAYS. Mit ihren Spezialgebieten Texte/Konzepte, Branding und PR ist sie für Tone of Voice und Wording von NETWAYS und Icinga verantwortlich. Davor war sie als Journalistin und in der freien Theaterszene spannenden Geschichten auf der Spur. Ihre Leidenschaft gilt gutem Storytelling, klarer Sprache und ausgefeilten Texten. Ihre innere Mitte findet sie beim Klettern und Yoga.

Gitlab Johnyj12345 Hack

Yesterday we received the information that there is a new Gitlab “hack” which could affect older versions of Gitlab. If affected it will behave like this:

The publicly visible procedure is always the same: Johny creates one or more issues that are linked with each other and at the end of the link cascade there’s either an attached file or a link to a file which holds Gitlab’s secrets.yml.

Source: https://blog.philipp-trommler.me/posts/2020/07/13/security-possible-gitlab-hack-johnyj12345/

It seems like the vulnerability was fixed with these security release:
https://about.gitlab.com/releases/2020/03/26/security-release-12-dot-9-dot-1-released/

The NWS team wrote some scripts to see if any of the Gitlab CE / Gitlab EE apps are affected, which was not the case, also because NWS apps are running on the latest version of Gitlab.

This issue is very critical since the secrets.yml can be found with a simple web search and contains informations like:

  • secret_key_base
  • db_key_base
  • otp_key_base

 

If you are affected, you should

  • take down your Gitlab instance
  • remove the user
  • remove the issues
  • update your instance.

Best would be to also reset the “secrets.yml”, but as far as i know, there is currently no way to do so.

 

Here is a short script to check quick if the user exists (if you don’t want to check via web interface):

#!/bin/bash

echo "User.all" | gitlab-rails console | grep "Johny12345" 2>&1
response=`echo $?`

if [ $response == "0" ]; then
echo "[ALERT] Johny was here ... "
else
echo "[OK] No Johny found ..."
fi

Marius Gebert
Marius Gebert
Systems Engineer

Marius ist seit 2013 bei NETWAYS. Er hat 2016 seine Ausbildung zum Fachinformatiker für Systemintegration absolviert und ist nun im Web Services Team tätig. Hier kümmert er sich mit seinen Kollegen um die NWS Plattform und alles was hiermit zusammen hängt. 2017 hat Marius die Prüfung zum Ausbilder abgelegt und kümmert sich in seiner Abteilung um die Ausbildung unserer jungen Kollegen. Seine Freizeit verbringt Marius gerne an der frischen Luft und ist für jeden Spaß zu...

Ansible – Use Blocks and Rescue Errors

Ansible is a widely used and powerful open-source configuration and deployment management tool. It can be used for simple repetitive daily tasks or complex application deployments, therefore Ansible is able to cover mostly any situation.

Since version 2.0.0 Ansible introduced the usage of blocks, they provide the possibility to group or rescue failed tasks.
On blocks we can assign most directives which are available for any other task at block level, only loops aren’t available.

- name: Update Systems
  hosts: all
  tasks:
    - name: execute this block only for rhel family hosts
      block:
        - name: install epel repository
          yum:
            name: epel-release
            state: present

        - name: install updates
          yum:
            name: '*'
            state: latest
            exclude: kernel*

      when: ansible_os_family == 'RedHat'
      become: true

When we try to deploy applications, sometimes we need to test connections or if requirements are met. When those tasks fail caused by the negative test result, the playbook by default fails and therefore stops.
To force Ansible to execute all other tasks, we could use the directive ignore_failed: true and checking the return value for any other depending task.

With blocks this is easily solved, by using rescue to catch the error and force a particular tasks to run.
The always will make sure that the listed tasks get executed.


- name: rescue my errors
  hosts: localhost
  tasks:
    - name: Try to reach host
      block:
        - name: "[Try reach DNS] Check Connection over DNS"
          command: ping client01.demo.local -c 2
          register: output
      rescue:
        - name: "[Rescue failed DNS] Check Connection over IP"
          command: ping 192.168.33.1 -c 2
          register: output
      always:
        - debug:
            var: output

To handle more than one rescue statement, the block can be simply used in the rescue section, like in the following example.


  - name: Try to execute skript
    block:
      - name: Check Connection over DNS
        command: ping nclient01.demo.local -c 2
        register: output
    rescue:
      - name: "this will fail"
        block:
          - name: it will be false
            command: /bin/false
            register: output
        rescue:
          - name: "this works"
            command: ping 192.168.33.1 -c 2
            register: output

Try to reduce ignored tasks in failed state with rescue blocks, this reduces the confusion of users when inspecting the output.
As second advice try to reduce code duplication by grouping tasks with similar directives.

Check out our Blog for more awesome posts and if you need help with Ansible send us a message or sign up for one of our trainings!

Thilo Wening
Thilo Wening
Consultant

Thilo hat bei NETWAYS mit der Ausbildung zum Fachinformatiker, Schwerpunkt Systemadministration begonnen und unterstützt nun nach erfolgreich bestandener Prüfung tatkräftig die Kollegen im Consulting. In seiner Freizeit ist er athletisch in der Senkrechten unterwegs und stählt seine Muskeln beim Bouldern. Als richtiger Profi macht er das natürlich am liebsten in der Natur und geht nur noch in Ausnahmefällen in die Kletterhalle.

Veranstaltungen

Dez 01

Icinga 2 Fundamentals Training | Online

Dezember 1 @ 09:00 - Dezember 4 @ 17:00
Dez 03

DevOps Meetup

Dezember 3 @ 17:30 - 20:30
Dez 08

Terraform mit OpenStack Training | Online

Dezember 8 @ 09:00 - Dezember 9 @ 17:00
Dez 08

Icinga 2 Advanced Training | Online

Dezember 8 @ 09:00 - Dezember 10 @ 17:00
Dez 15

GitLab Training | Online

Dezember 15 @ 09:00 - Dezember 16 @ 17:00