Seite wählen

NETWAYS Blog

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: 
    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
Manager Consulting

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.

Never ending Spam

nospamHeute halten wir uns schlicht und einfach und möchten die Allgemeinheit und die IT-Welt mal wieder vor den ganzen Spam-Wellen warnen. Derzeit kommen diese mit ZIP Files in unterschiedlichsten Zusammenhängen.
Beispiele sind Nachrichten von Ihrer freundlichen Apotheke, der Post/DHL wegen einer Sendung, dem Telefonbetreiber zwecks Rechnung oder Kündigung oder dem Klassiker der Bank. Wer bei seinem Filter Zip als Anhang durchlässt wird es aber auch schwer haben diese Spams derzeit zu filtern. Wieder ein Grund mehr ZIPs nicht als Anhang zuzulassen, E-Mails sind nicht zum File-Transfer entworfen worden 🙂
Es gibt sicher eine Person im Kreis der Verwandten von jedem, wo man sicher ist, das dieser derartige Nachrichten samt Anhang öffnet. Hier kann man nur noch einmal warnen, das z.B. die o.g. Absender einem nicht ohne weiteres eine Mail mit dubiosem Anhang schicken.
Daher bitte weitersagen, das man vor dem öffnen der Anhänge erst einmal die Nachrichten genau prüfen soll. Bin ich überhaupt Kunde, hat der Absender eigentlich die Adresse, wird man direkt angesprochen (Name, Vorname).
Und wer Hilfe bei Setup seines Mailservers braucht kann gern auf unsere Unterstützung zurückgreifen oder den Service direkt bei uns nutzen.

Listen filtern in Python

Zum Abschluss dieser Woche kommt von meiner Seite noch ein wenig Code. Angenommen wir haben eine Liste von Benutzern (users) und möchten nur auf den gesperrten weiterarbeiten, so können wir diese, auf verschiedene Art und Weise filtern:


disabled_users = []
for user in users:
    if user.disabled:
        disabled_users.append(user)

Das ganze geht natürlich auch noch etwas eleganter mit list comprehension oder der Built-in-Funktion filter:


disabled_users = [user for user in users if user.disabled]
def is_disabled(user):
    """Returns True if user is disabled else False.
    """
    ...
disabled_users = filter(is_disabled, users)
# oder:
disabled_users = [user for user in users if is_disabled(user)]

Die oberen Beispiele erzeugen jeweils eine neue Liste. Um dies zu verhindern, arbeiten wir mit folgender Modifikation auf Referenzen des Listeninhalts:


users[:] = [user for user in users if user.disabled]

Der „[:]“-Operator erzeugt uns hier eine shallow copy der Liste.
Wer jetzt noch den Unterschied zwischen Generatoren und Iteratoren kennt, bekommt mit folgender Zeile die ultimative 🙂 Art, Listen zu filtern:


users[:] = (user for user in users if user.disabled)

Schönes Wochenende.

Eric Lippmann
Eric Lippmann
CTO

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Nginx als lastverteilter Bild Konverter

Der bekannte Webserver nginx, auf dem ca. 6% aller Webseiten des Internets laufen und der auch noch Reverse Proxy- und pop3/imap Proxyserver sein kann,  hat noch eine andere, oft wenig beachtete Möglichkeit. Mit Hilfe seines Image Filters ist es möglich, ihn als lastverteilten Lieferanten für Bilder zu benutzen, die er on-the-fly in andere Größen skalieren kann.

1. Lastverteilung

Nginx kann von Haus aus Anfragen an andere Webserver verteilen. Hierzu definiert man zuerst einen Upstream Server.

upstream cache_group {
server :8888 weight=100;
server 127.0.0.1:8888 weight=1;
}

Im vhost der die ersten Anfragen annimmt, definiert man dass der Webserver zuerst schaut, ob er das optimierte Bild schon hat, bzw. wenn das Original gefordert wird dieses sofort ausliefert.

server {
       listen   80;
       server_name mein_Server;
       location = /favicon.ico {
               #empty_gif;
               return 204;
       }
       location / {
               root                    /var/www/images;
               rewrite "^\/(50|100|150|200|250|300|350)\/(.*)\.(jpg|png)$" /$1/$2.$3 break;
               rewrite "^\/(.*)\.(jpg|png)" /$1.$2 break;
               error_page              404 = @cache;
       }
       location @cache {
               internal;
               proxy_pass              http://cache_group;
               proxy_store             on;
               proxy_store_access      user:rw  group:rw  all:r;
               proxy_temp_path         /var/www/temp;
               root                    /var/www/images;
       }
}

Falls der Server das Bild nicht findet schaut er, statt die error_page 404 auszugeben, in der cache_group nach. Hier greift die bei Upstream eingerichtete Gewichtung der Server. Nginx wird 100mal so oft auf dem zweiten Image Server suchen wie auf sich selbst. Wenn das Bild auch auf dem anderen Server nicht gefunden wird, wird es dort generiert. Das sorgt natürlich dafür, dass der erste Server entlastet wird. Das Verzeichnis /var/www sollte ein gemeinsames Share sein, damit das generierte Bild auch beiden Servern zur Verfügung steht.
Die im vhost eingestellten rewrite Regeln sind nötig, um unterscheiden zu können, welche Größe des Bildes angefordert wird, bzw. ob einfach das Original benutzt wird. Ruft der Client http://mein_Server/300/testbild.jpg ab bekommt er das Bild aus /var/www/images/300/testbild.jpg. Bei http://mein_Server/testbild.jpg greift die untere rewrite Regel und er kommt auf /var/www/images/testbild.jpg

2. Bildoptimierung

Der vhost für den Cache sieht folgendermaßen aus:

server {
        listen 8888;
        server_name mein_Server;
        location / {
                root                    /var/www/images/;
                error_page              404 = @local_image;
        }
        location @local_image {
                internal;
                proxy_pass              http://local_group_image;
                proxy_store             on;
                proxy_store_access      user:rw  group:rw  all:r;
                proxy_temp_path         /var/www/temp;
                root                    /var/www/images;
        }

Von hier aus springt er, falls das Bild dort nicht finden kann in den Image teil.
Hierfür muss man zunächst noch einen Upstream angeben:

upstream local_group_image {
        server 127.0.0.1:7777;
}

Und anschließend den vhost inklusive Imagefilter und Sicherheitscheck (es sollen nur die Größen erstellt werden, die wir vorher angeben) erstellen. Der Sicherheitscheck funktioniert durch den Regex in der Location Direktive.

server {
        listen 7777;
        server_name mein_Server;
        location ~ "\/(50|100|150|200|250|300|350)\/.*\.(png|jpg)$" {
                root    /var/www/images/;
                rewrite "^\/(50|100|150|200|250|300|350)\/(.*)\.(jpg|png)$" /$2.$3 break;
                image_filter resize $1 $1;
                image_filter_buffer 6M;
                image_filter_jpeg_quality 95;
        }
}

Jetzt sollte alles so funktionieren, wie wir uns das vorstellen. Das Konstrukt ist natürlich noch um weitere Server erweiterbar. Auch zusätzliche Aufgaben, wie z.B. SSL oder andere Bild Formate sind schnell integriert. Wen man so weit ist, wie hier beschrieben, hat man eine skalierbare, stabile und leicht gewichtige Lösung die mit ein wenig Mehrarbeit auch Ausfallsicher ist.

Christoph Niemann
Christoph Niemann
Senior Consultant

Christoph hat bei uns im Bereich Managed Service begonnen und sich dort intensiv mit dem internen Monitoring auseinandergesetzt. Seit 2011 ist er nun im Consulting aktiv und unterstützt unsere Kunden vor Ort bei größeren Monitoring-Projekten und PERL-Developer-Hells.