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.

Ansible Host-Gruppen: Wer gehört zu wem?

Immer wieder kommt es vor, dass ich in größeren Ansible-Umgebungen arbeite. Diese enthalten eine Vielzahl von verschiedenen Gruppen im Inventory, die sich auch mal aus anderen Host-Gruppen zusammen setzen. Da ist es nicht immer leicht den Überblick zu behalten.
Da kommt es schon mal vor, prüfen zu wollen oder zu müssen ob alle Gruppen richtig aufgebaut sind oder korrekt interpretiert werden.
Nach ein wenig Recherche war auch schnell mit einem einfachen Ein-Zeiler eine Lösung gefunden, um sich anzeigen zu lassen in welcher Gruppe die einzelnen Server einsortiert sind oder wie sich die Gruppe im Ansible-Inventory zusammen setzt

ansible -i <inventory> localhost -m debug -a 'var=groups'

Dabei lässt sich entweder das Inventory-Verzeichnis oder eine konkrete Inventory-Hostdatei angeben.
Und weil es mit einem Beispiel immer besser ist:

ansible -i hosts localhost -m debug -a 'var=groups'
localhost | SUCCESS => {
    "groups": {
        "all": [
            "maja42310",
            "maja42444",
            "willy1334",
            "willy24242",
            "koenigin_blau"
        ],
        "drohnen": [
            "willy1334",
            "willy24242"
        ],
        "honigbienen": [
            "maja42310",
            "maja42444"
        ],
        "honigbienenvolk": [
            "maja42310",
            "maja42444",           
            "willy1334",
            "willy24242",
            "koenigin_blau"
        ],
        "koenigin": [
            "koenigin_blau"
        ],
        "ungrouped": []
    }
}

Da ich mir das nun mehr als ein mal nicht merken konnte, dachte ich mir ich schreib das mal hier auf. Vielleicht hilft es ja dem ein oder anderen und ich kann es mir jetzt besser merken:)

Wenn Ihr noch mehr über Ansible erfahren wollt, dann besucht doch einfach eines unserer Trainings bei Netways Events. Sollte es schon etwas konkreter sein und Ihr benötigt gezielt Hilfe, fragt doch gerne unsere Kollegen vom Sales Team ob Ihr nicht Unterstützung von Netways Professional Service bekommt.

Daniel Neuberger
Daniel Neuberger
Senior Consultant

Nach seiner Ausbildung zum Fachinformatiker für Systemintegration und Tätigkeit als Systemadministrator kam er 2012 zum Consulting. Nach nun mehr als 4 Jahren Linux und Open Source Backup Consulting zieht es ihn in die Welt des Monitorings und System Management. Seit April 2017 verstärkt er das NETWAYS Professional Services Team im Consulting rund um die Themen Elastic, Icinga und Bareos. Wenn er gerade mal nicht um anderen zu Helfen durch die Welt tingelt geht er seiner...

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.

Ansible – should I use omit filter?

When we talk about Ansible, we more and more talk about AWX or Tower. This Tool comes in handy when you work with Ansible in a environment shared with colleagues or multiple teams.
In AWX we can reuse the playbooks we developed and share them with our colleagues on a GUI Platform.

Often we need a bit of understanding how a playbook is designed or if a variable need to be defined for the particular play. This can be much more tricky when sharing templates to people unaware of your work.

This is where the omit filter can be used. The easiest way to explain this, if the variable has no content or isn’t defined, omit the parameter.

The following example is an extract from the documentation:


- name: touch files with an optional mode
  file:
    dest: "{{ item.path }}"
    state: touch
    mode: "{{ item.mode | default(omit) }}"
  loop:
    - path: /tmp/foo
    - path: /tmp/bar
    - path: /tmp/baz
      mode: "0444"

In AWX we can create surveys, those are great to ask a few questions and provide a guide on how to use the underlying play. But often we need to choose between two variables whether one or another action should happen. Defined by the variable in use. If we leave one of both empty, Ansible will see those empty as defined but “None” (Python null) as content.

With the omit filter we can remove the parameter from the play, so if the parameter is empty it won’t be used.

The following code is the usage of icinga2_downtimes module which can create downtimes for hosts or hostgroups but the parameters cannot be used at the same time. In this case I can show the variable for hostnames and hostgroups in the webinterface. The user will use one variable and the other variable will be removed and therefore no errors occur.


- name: schedule downtimes
  icinga2_downtimes:
    host: https://icingaweb2.localdomain
    username: icinga_downtime
    password: "{{ icinga_downtime_password }}"
    hostnames: "{{ icinga2_downtimes_hostnames | default(omit) }}"
    hostgroups: "{{ icinga2_downtimes_hostgroups | default(omit) }}"
    all_services: "{{ icinga2_downtimes_allservices | default(False) }}"

The variables shown in the AWX GUI on the template.

This filter can be used in various other locations to provide optional parameters to your users.

If you want to learn more about Ansible, checkout our Ansible Trainings or read more on our blogpost.

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.

Config Management Camp Ghent 2020 – Recap

Cfgmgmtcamp Logo

It seams like Config Management Camp at beginning of February in Ghent gets a fixed date for me. I attended the fifth year in series, gave a talk in the last three and joined the Foreman Construction day on the day after as many times. So why am I still attending while some people are perhaps already telling you that the time of configuration management is over in favor of containers and Kubernetes. While I can not totally agree or disagree with this thesis, my schedule is still full of Foreman, Puppet and Ansible, so it makes sense to keep me updated. Furthermore the event allows to network like not many others with speaker diner, community event (also known as beer event) and Foreman community dinner. And last but not least it is always interesting to hear what the big names think about configuration management in the future and how to adopt to a world of containers and Kubernetes which was a big part of the talks in the main track.

But to get everything in correct order let me start at Sunday morning where Blerim, Aleksander and I started so we can meet Bernd and Markus who attended FOSDEM in advance in our AirBnb before going to speaker diner. I have to admit I really like Ghent’s old City so I was happy the same restaurant right in the middle of Ghent was chosen for diner like last year. And also like last year I joined the Foreman table to meet old and new friends for some hours mixed of small talk and technical discussions.

The first conference day started as always with main tracks only and I can really recommend Ryn Daniels’ talk Untitled Config Game. After lunch I joined the Foreman community room to get latest news from the community and the 2.0 release by Tomer Brisker and Ewoud Kohl van Wijngaarden respectively. The talks about Katello and how to create API and CLI for a Compute Resource where also quite interesting, but my favorite was Marek Hulan who had initially chosen a very similar title for his talk about Foreman’s new Reporting Engine and showed some interesting examples and the future templates documentation which will be automatically rendered in a similar fashion like the API documentation which is always available at /apidoc on a Foreman installation. Last but hopefully not least was my talk about existing solutions which get data from Foreman into central systems like Elasticsearch for logs and Supervisor Authority Plugin which enables Elastic APM to show performance bottlenecks, stacktraces and some metrics and is perhaps the most promising solution for me. As I was the one between the audience and the beer I was quite happy finishing my talk in time and get some more Kriek afterwards.

Day two had also some create talks to start with John Willis telling us he got 99 (or perhaps even far more) problems and a bash DSL ain’t one of them and Bernd how convenience is killing Open Standards. The first was really great in showing how configuration management has evolved compared to the container world which follows the same evolutionary process. The second was not only related to configuration management but IT at all including clouds and many more (and Bernd was fully aware of the discrepancy giving such a talk on a macbook). This day I visited more different tracks to hear about the migration of Pulp 2 to 3 behind Katello, testing of Ansible roles with Molecule (including some chemistry lessons), Ansible modules for pulp, how Foreman handles Secure boot and last but not least to get an update on Mgmt Config. After the talks we joined the Foreman Community diner which was located in a separate room of the same location we visited last year, allowing even more discussions without fearing to disturb others.

The Foreman Construction day like many other community events is a fringe event at the same location allow to hack together on some features and I was happy to make the beginner session I had given already the last years an official workshop. It was based on our official training focusing on installation and provisioning including hints and answering questions. After lunch I joined the hacking session for some time before shopping some Kriek and waffles and then traveling home.

Dirk Götz
Dirk Götz
Principal Consultant

Dirk ist Red Hat Spezialist und arbeitet bei NETWAYS im Bereich Consulting für Icinga, Puppet, Ansible, Foreman und andere Systems-Management-Lösungen. Früher war er bei einem Träger der gesetzlichen Rentenversicherung als Senior Administrator beschäftigt und auch für die Ausbildung der Azubis verantwortlich wie nun bei NETWAYS.

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