{"id":80305,"date":"2020-05-05T01:42:50","date_gmt":"2020-05-04T23:42:50","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/kak-nachat-testirovat-ansible-otrefaktorit-proekt-za-god-i-ne-sletet-s-katushek"},"modified":"2020-05-05T01:42:50","modified_gmt":"2020-05-04T23:42:50","slug":"kak-nachat-testirovat-ansible-otrefaktorit-proekt-za-god-i-ne-sletet-s-katushek","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-nachat-testirovat-ansible-otrefaktorit-proekt-za-god-i-ne-sletet-s-katushek","title":{"rendered":"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/b8981189e3a2d7f8429757cd521b7583.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dies ist die Transkription <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=GdrJv5oypfg\">eines Vortrags<\/a><\/noindex> findet man <noindex><a rel=\"nofollow\" href=\"https:\/\/www.meetup.com\/DevOps-40\/events\/269140089\/\">DevOps-40 2020-03-18<\/a><\/noindex>:<\/p>\n<p><\/p>\n<p>Ab dem zweiten Commit wird jeder Code zu Legacy-Code, da die urspr\u00fcnglichen Ideen nicht mehr mit der rauen Realit\u00e4t \u00fcbereinstimmen. Das ist weder gut noch schlecht, sondern eine Gegebenheit, mit der man leben muss. Teil dieses Prozesses ist das Refactoring. Refactoring von Infrastructure as Code. Lassen Sie uns die Geschichte erz\u00e4hlen, wie man Ansible in einem Jahr refakturiert und dabei den Verstand beh\u00e4lt.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"zarozhdenie-legacy\">Die Entstehung von Legacy<\/h2>\n<p><\/p>\n<h3 id=\"den--1-nulevoy-pacient\">Tag Nr. 1: Der Nullpatient<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/086414710864293a91a37785854bc096.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es gab ein hypothetisches Projekt. Darauf befand sich ein Dev-Team und Ops-Ingenieure. Sie standen vor derselben Herausforderung: Wie man Server bereitstellt und eine Anwendung startet. Das Problem war, dass jede Gruppe ihr eigenes Vorgehen hatte. Im Projekt wurde beschlossen, Ansible zu verwenden, um das Wissen zwischen den Dev- und Ops-Teams zu synchronisieren.<\/p>\n<p><\/p>\n<h3 id=\"den--89-zarozhdenie-legacy\">Tag Nr. 89: Die Entstehung von Legacy<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/329bc3f190ca4d6519be6ac94026bc6d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Unbemerkt von uns selbst wollten wir es so gut wie m\u00f6glich machen, und am Ende resultierte es in Legacy. Wie kann das passieren?<\/p>\n<p><\/p>\n<ul>\n<li>Wir haben hier eine dringende Aufgabe, wir machen einen schnellen Hack \u2013 das reparieren wir sp\u00e4ter.<\/li>\n<li>Die Dokumentation kann weggelassen werden; es ist ja so klar, was hier passiert.<\/li>\n<li>Ich kenne Ansible \/ Python \/ Bash \/ Terraform! Sehen Sie, wie ich mich winden kann!<\/li>\n<li>Ich bin ein Full Stack Overflow Developer und habe das von Stack Overflow kopiert. Ich wei\u00df nicht, wie es funktioniert, aber es sieht gut aus und l\u00f6st das Problem.<\/li>\n<\/ul>\n<p><\/p>\n<p>Am Ende kann man einen v\u00f6llig unverst\u00e4ndlichen Code erhalten, f\u00fcr den es keine Dokumentation gibt, unklar ist, was er macht, und ob er n\u00f6tig ist. Das Problem ist, dass Sie ihn weiterentwickeln, anpassen und improvisieren m\u00fcssen, was die Situation nur noch schlimmer macht.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: localhost\n  tasks:\n    - shell: echo -n Z &gt;&gt; a.txt &amp;&amp; cat a.txt\n      register: output\n      delay: 1\n      retries: 5\n      until: not output.stdout.find(&quot;ZZZ&quot;)<\/code><\/pre>\n<p><\/p>\n<h3 id=\"den--109-osoznanie-problemy\">Tag Nr. 109: Problembewusstsein<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/b7da9f6aecc5bebab6072ba6e5dfa824.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Das urspr\u00fcnglich gedachte und umgesetzte IaC-Modell entspricht nicht mehr den Anforderungen der Benutzer \/ des Gesch\u00e4fts \/ anderer Teams. Die Zeit f\u00fcr \u00c4nderungen in der Infrastruktur wird untragbar. An diesem Punkt wird klar, dass es Zeit ist, Ma\u00dfnahmen zu ergreifen.<\/p>\n<p><\/p>\n<h2 id=\"refaktoring-iac\">Refactoring von IaC<\/h2>\n<p><\/p>\n<h3 id=\"den--139-a-vam-tochno-nuzhen-refaktoring\">Tag Nr. 139: Brauchen Sie wirklich ein Refactoring?<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/881455f096870d51bc2b9b8f87f171b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Bevor Sie mit dem Refactoring beginnen, sollten Sie eine Reihe wichtiger Fragen beantworten:<\/p>\n<p><\/p>\n<ol>\n<li>Warum brauchen Sie das alles?<\/li>\n<li>Haben Sie genug Zeit?<\/li>\n<li>Haben Sie gen\u00fcgend Wissen?<\/li>\n<\/ol>\n<p><\/p>\n<p>Wenn Sie nicht wissen, wie Sie auf die Fragen antworten sollen, wird das Refactoring weder beginnen noch m\u00f6glicherweise sogar nur schlechter werden. Da es Erfahrung gab, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/467171\/\">Was ich gelernt habe, als ich 200.000 Zeilen Infrastrukturcode getestet habe<\/a><\/noindex>kam eine Anfrage vom Projekt, um zu helfen, Rollen zu korrigieren und sie mit Tests zu \u00fcberdecken.<\/p>\n<p><\/p>\n<h3 id=\"den--149-podgotovka-refaktoringa\">Tag Nr. 149: Vorbereitung des Refactorings<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/3e2d66a81cd162dcb4181f3914fc132d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u041f\u0435\u0440\u0432\u043e\u043e\u0447\u0435\u0440e\u0434\u043d\u043e\u0435 \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c\u0441\u044f. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u0449\u0430\u0435\u043c\u0441\u044f, \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438 \u0438 \u043f\u0440\u0438\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u0438 \u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u044b \u043a\u0430\u043a-\u0442\u043e \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0430\u0442\u044c\u044f \u0432 confluence, \u0447\u0442\u043e \u0431\u044b \u043f\u0440\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u0430 &quot;\u043a\u0430\u043a \u043b\u0443\u0447\u0448\u0435?&quot; \u0438\u043b\u0438 &quot;\u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435\u0435?&quot; \u043c\u044b \u043d\u0435 \u0441\u0431\u0438\u043b\u0438\u0441\u044c \u0441 \u043a\u0443\u0440\u0441\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u0434\u0435\u0438 <em>teile und herrsche<\/em>: wir zerlegen die Infrastruktur in kleine St\u00fccke \/ Bausteine. Dieser Ansatz erm\u00f6glicht es, einen isolierten Teil der Infrastruktur zu nehmen, zu verstehen, was er tut, ihn mit Tests zu \u00fcberziehen und \u00c4nderungen vorzunehmen, ohne Angst zu haben, etwas kaputt zu machen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/a0ea12ae6568d5c7e97469eaf404d608.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Das Testen der Infrastruktur wird zum Grundpfeiler, und hier ist es wichtig, die Testpyramide der Infrastruktur zu erw\u00e4hnen. Genau die gleiche Idee wie in der Entwicklung, jedoch f\u00fcr die Infrastruktur: Wir beginnen mit kosteng\u00fcnstigen, schnellen Tests, die einfache Dinge wie Abst\u00e4nde \u00fcberpr\u00fcfen, und steigen dann zu teureren, umfassenden Tests auf, die eine gesamte Infrastruktur bereitstellen.<\/p>\n<p><\/p>\n<h4 id=\"popytki-testirovaniya-ansible\">Versuche zur Ansible-Testung<\/h4>\n<p><\/p>\n<p>Bevor wir beschreiben, wie wir Ansible in unserem Projekt getestet haben, m\u00f6chte ich die fr\u00fcheren Versuche und Ans\u00e4tze skizzieren, die wir verwendet haben, um den Kontext der getroffenen Entscheidungen zu verstehen.<\/p>\n<p><\/p>\n<h5 id=\"den---997-sds-provision\">Tag Nr. -997: SDS-Bereitstellung<\/h5>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/3d93865fb03c7d7baa055b99e21d9ae9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Das erste Mal, dass ich Ansible testen durfte, geschah im Rahmen eines Projekts zur Entwicklung von SDS (Software Defined Storage). Es gibt einen separaten Artikel zu diesem Thema.<br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/342216\/\">Wie man auf Kr\u00fccken mit dem Testen seiner Distribution Fahrr\u00e4der zerbricht.<\/a><\/noindex>, aber kurz gesagt, wir haben eine umgekehrte Test-Pyramide erstellt, und wir haben 60-90 Minuten f\u00fcr eine Rolle ben\u00f6tigt, was zu lange ist. Die Grundlage waren e2e-Tests, d.h. wir haben eine vollst\u00e4ndige Installation bereitgestellt und diese dann getestet. Hinzu kam das Rad selber zu erfinden. Aber man muss zugeben, dass diese L\u00f6sung funktionierte und es uns erm\u00f6glichte, stabil zu releasen.<\/p>\n<p><\/p>\n<h5 id=\"den---701-ansible-i-test-kitchen\">Tag \u2116 -701: Ansible und Test Kitchen<\/h5>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/1b87eca5b01cace01b48edaf28a4ab7d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die Weiterentwicklung der Idee des Testens in Ansible war die Nutzung von bestehenden Tools, n\u00e4mlich Test Kitchen \/ Kitchen-CI und Inspec. Die Wahl fiel aufgrund der Ruby-Kenntnisse (mehr dazu in dem Artikel auf Habr\u00e9: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/437004\/\">Tr\u00e4umen YML-Programmierer von Ansible-Tests?<\/a><\/noindex>) arbeitete schneller, etwa 40 Minuten f\u00fcr 10 Rollen. Wir haben eine Gruppe von virtuellen Maschinen erstellt und dort die Tests durchgef\u00fchrt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/345fe1c82dde1e6a94978781c90f8a85.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Insgesamt funktionierte die L\u00f6sung, aber es gab einen Nachgeschmack wegen der Uneinheitlichkeit. Als wir jedoch die Anzahl der zu testenden Rollen auf 13 Grundrollen und 2 Meta-Rollen, die kleinere Rollen kombinieren, erh\u00f6hten, begannen die Tests pl\u00f6tzlich 70 Minuten zu dauern, was fast doppelt so lange ist. \u00dcber XP (Extreme Programming) Praktiken zu sprechen, war schwierig, denn niemand m\u00f6chte 70 Minuten warten. Das war der Anlass, unseren Ansatz zu \u00e4ndern.<\/p>\n<p><\/p>\n<h5 id=\"den---601-ansible-i-molecule\">Tag \u2116 -601: Ansible und Molecule<\/h5>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/37e144725fff4adda585781d057782ec.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Konzeptionell \u00e4hnelt es testkitchen, allerdings haben wir das Rollentesting in Docker \u00fcbertragen und den Stack gewechselt. Das Ergebnis ist, dass die Zeit auf stabile 20-25 Minuten f\u00fcr 7 Rollen verk\u00fcrzt wurde.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/640075d7087c1bc2337cb82ad412c6b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Indem wir die Anzahl der getesteten Rollen auf 17 erh\u00f6hten und 45 Rollen linpten, haben wir dies in 28 Minuten auf 2 Jenkins-Slaves durchlaufen.<\/p>\n<p><\/p>\n<h3 id=\"den--167-dobavlyaem-na-proekt-testy-ansible\">Tag Nr. 167: Wir f\u00fcgen dem Projekt Ansible-Tests hinzu.<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/e62261eb4000f2bc4df4cea398d38276.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die Aufgabe des Refactorings kann voraussichtlich nicht im Handumdrehen erledigt werden. Die Aufgabe sollte messbar sein, damit Sie sie in kleine St\u00fccke aufteilen und den Elefanten mit einem Teel\u00f6ffel nach und nach essen k\u00f6nnen. Es sollte ein Verst\u00e4ndnis dar\u00fcber bestehen, ob Sie sich in die richtige Richtung bewegen und wie lange der Weg noch dauern wird.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/daf1f9ba63e7122d5d39311b35de19a2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Im Grunde ist es nicht entscheidend, wie es gemacht wird: Man kann es auf ein Blatt Papier schreiben, Post-its am Schrank anbringen, Aufgaben in Jira erstellen oder ein Google-Dokument erstellen, um den aktuellen Status festzuhalten. Der Ursprung liegt darin, dass der Prozess nicht sofort abgeschlossen ist; er wird langwierig und m\u00fchsam sein. Es ist unwahrscheinlich, dass jemand m\u00f6chte, dass Sie w\u00e4hrend des Refactorings die Ideen verlieren, erm\u00fcden und aufgeben.<\/p>\n<p><\/p>\n<p>Refactoring ist einfach:<\/p>\n<p><\/p>\n<ul>\n<li>Essen.<\/li>\n<li>Schlafen.<\/li>\n<li>Programmieren.<\/li>\n<li>IaC-Test.<\/li>\n<li>Wiederholen.<\/li>\n<\/ul>\n<p><\/p>\n<p>Und so wiederholen wir, bis wir das angestrebte Ziel erreichen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/222fe586d3e4e0bc23051fff1eb7bff4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es kann nicht alles auf einmal getestet werden, daher war unsere erste Aufgabe die \u00dcberpr\u00fcfung und das Linting des Codes. <\/p>\n<p><\/p>\n<h3 id=\"den--181-green-build-master\">Tag Nr. 181: Green Build Master<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/86cf52ede5fd61411e2b87a132c7f386.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Linting ist ein kleiner erster Schritt zum Green Build Master. Es bricht fast nichts, erm\u00f6glicht aber die Feinabstimmung der Prozesse und erzeugt gr\u00fcne Builds in Jenkins. Die Idee ist, Gewohnheiten im Team zu entwickeln:<\/p>\n<p><\/p>\n<ul>\n<li>Rote Tests sind schlecht.<\/li>\n<li>Wenn du kommst, um etwas zu korrigieren, verbessere auch den Code ein wenig im Vergleich zu dem, was du vorgefunden hast.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"den--193-ot-lintovki-k-unit-testam\">Tag Nr. 193: Vom Linting zu Unit-Tests<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/2f79eb411cf64976459c7fc53f22b2fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nachdem der Prozess, wie der Code in den Master gelangt, etabliert ist, kann der schrittweise Verbesserungsprozess beginnen \u2013 indem man das Linting durch Rollen\u00fcbergaben ersetzt, sogar ohne Idempotenz. Es ist wichtig zu verstehen, wie man Rollen anwendet und wie sie funktionieren.<\/p>\n<p><\/p>\n<h3 id=\"den--211-ot-unit-k-integration-testam\">Tag Nr. 211: Von Unit- zu Integrationstests<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/9cfeb70b7b637eed4d0c93eb87d9d254.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wenn die meisten Rollen durch Unit-Tests abgedeckt und alles gelintet ist, kann man mit der Hinzuf\u00fcgung von Integrationstests beginnen. Das hei\u00dft, man testet nicht nur einen einzelnen Baustein in der Infrastruktur, sondern deren Kombination, zum Beispiel die vollst\u00e4ndige Konfiguration eines Instanz.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/c9cdcde1260df9837b2053b2cc811c84.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In Jenkins haben wir zahlreiche Stufen generiert, die parallel Rollen\/Playbooks linten, dann Unit-Tests in Containern durchf\u00fchren und schlie\u00dflich Integrationstests.<\/p>\n<p><\/p>\n<h4 id=\"jenkins--docker--ansible--tests\">Jenkins + Docker + Ansible = Tests<\/h4>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/218b1d768d2b284d18cfcba2370e080a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ol>\n<li>Repo auschecken und Build-Phasen generieren.<\/li>\n<li>Lint-Playbook-Phasen parallel ausf\u00fchren.<\/li>\n<li>Lint-Rollen-Phasen parallel ausf\u00fchren.<\/li>\n<li>Syntaxpr\u00fcfung der Rollen-Phasen parallel ausf\u00fchren.<\/li>\n<li>Test-Rollen-Phasen parallel ausf\u00fchren.\n<ol>\n<li>Lint-Rolle.<\/li>\n<li>Abh\u00e4ngigkeit von anderen Rollen \u00fcberpr\u00fcfen.<\/li>\n<li>Syntax \u00fcberpr\u00fcfen.<\/li>\n<li>Docker-Instanz erstellen.<\/li>\n<li>Molecule\/default\/playbook.yml ausf\u00fchren.<\/li>\n<li>Idempotenz \u00fcberpr\u00fcfen.<\/li>\n<\/ol>\n<\/li>\n<li>Integrationstests durchf\u00fchren.<\/li>\n<li>Fertigstellen<\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"den--271-bus-factor\">Tag Nr. 271: Bus-Faktor<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/eb1da11eb32f3f64d573e0414f0e05ba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In der Anfangszeit war eine kleine Gruppe von zwei bis drei Personen mit dem Refactoring besch\u00e4ftigt. Sie f\u00fchrten Code-Reviews im Master durch. Im Laufe der Zeit entwickelte das Team ein Wissen dar\u00fcber, wie man Code schreibt, und die Code-\u00dcberpr\u00fcfungen f\u00f6rderten die Verbreitung des Wissens \u00fcber die Infrastruktur und deren Funktionsweise. Das Besondere war, dass die Reviewer nach einem festgelegten Plan ausgew\u00e4hlt wurden, was bedeutete, dass du mit einer gewissen Wahrscheinlichkeit einen neuen Bereich der Infrastruktur erkunden konntest.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/5ca2cf914f32f69f8a84d6c5bd4e5114.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und es sollte hier bequem sein. Es sollte einfach sein, Reviews durchzuf\u00fchren, zu sehen, in welchem Rahmen sie gemacht werden und die Diskussionen nachzuverfolgen. Wir integrierten Jenkins + Bitbucket + Jira.<\/p>\n<p><\/p>\n<p>Aber so ist das Review an sich keine Allheilmittel. Irgendwie hat bei uns ein Code in den Master gelangt, der uns flappende Tests beschert hat.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- get_url:\n    url: &quot;{{ actk_certs }}\/{{ item.1 }}&quot;\n    dest: &quot;{{ actk_src_tmp }}\/&quot;\n    username: &quot;{{ actk_mvn_user }}&quot;\n    password: &quot;{{ actk_mvn_pass }}&quot;\n  with_subelements:\n    - &quot;{{ actk_cert_list }}&quot;\n    - &quot;{{ actk_certs }}&quot;\n  delegate_to: localhost\n\n- copy:\n    src: &quot;{{ actk_src_tmp }}\/{{ item.1 }}&quot;\n    dest: &quot;{{ actk_dst_tmp }}&quot;\n  with_subelements:\n    - &quot;{{ actk_cert_list }}&quot;\n    - &quot;{{ actk_certs }}&quot;<\/code><\/pre>\n<p><\/p>\n<p>Das wurde sp\u00e4ter behoben, aber der Eindruck blieb.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">get_url:\n    url: &quot;{{ actk_certs }}\/{{ actk_item }}&quot;\n    dest: &quot;{{ actk_src_tmp }}\/{{ actk_item }}&quot;\n    username: &quot;{{ actk_mvn_user }}&quot;\n    password: &quot;{{ actk_mvn_pass }}&quot;\n  loop_control:\n    loop_var: actk_item\n  with_items: &quot;{{ actk_cert_list }}&quot;\n  delegate_to: localhost\n\n- copy:\n    src: &quot;{{ actk_src_tmp }}\/{{ actk_item }}&quot;\n    dest: &quot;{{ actk_dst_tmp }}&quot;\n  loop_control:\n    loop_var: actk_item\n  with_items: &quot;{{ actk_cert_list }}&quot;<\/code><\/pre>\n<p><\/p>\n<h3 id=\"den--311-uskoryaem-testy\">Tag Nr. 311: Wir beschleunigen die Tests<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/ac7c16be6ea3e140916adc5b060286b7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0421\u043e \u0432\u0440\u0435\u043d\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u043e\u0441\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u0431\u0438\u043b\u0434\u044b \u0431\u0435\u0436\u0430\u043b\u0438 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u0434\u043e \u0447\u0430\u0441\u0430 \u0432 \u043f\u043b\u043e\u0445\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435. \u041d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0440\u0435\u0442\u0440\u043e \u0431\u044b\u043b\u0430 \u0444\u0440\u0430\u0437\u0430 \u043f\u043e \u0442\u0438\u043f\u0443 &quot;\u0445\u043e\u0440\u043e\u0448\u043e \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u043d\u043e \u043e\u043d\u0438 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0435&quot;. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u043e\u0442 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445 \u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u0434 docker, \u0434\u0430\u0431\u044b \u0431\u044b\u043b\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435. \u0422\u0430\u043a \u0436\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u043b\u0438 testinfra \u043d\u0430 ansible verifier \u0447\u0442\u043e \u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043a\u043e\u043b-\u0432\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/58576edb7ce00491cd92d7bc6810fc93.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Genauer gesagt, es gab ein Ma\u00dfnahmenpaket:<\/p>\n<p><\/p>\n<ol>\n<li>Umstieg auf Docker.<\/li>\n<li>Die Testung von Rollen entfernen, die durch Abh\u00e4ngigkeiten dupliziert wird.<\/li>\n<li>Die Anzahl der Slaves erh\u00f6hen.<\/li>\n<li>Reihenfolge der Testausf\u00fchrung.<\/li>\n<li>M\u00f6glichkeit zur Linting. <strong>ALLES<\/strong> lokal von einem Team.<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/3bcdaf0afc24c74739c852e220aa3b2d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>So wurde auch die Pipeline in Jenkins vereinheitlicht.<\/p>\n<p><\/p>\n<ol>\n<li>Bauen Sie die Phasen.<\/li>\n<li>Linten Sie alles parallel.<\/li>\n<li>Test-Rollen-Phasen parallel ausf\u00fchren.<\/li>\n<li>Fertigstellen.<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"lessons-learned\">Erfahrungen gesammelt<\/h2>\n<p><\/p>\n<h3 id=\"avoid-global-variables\">Globale Variablen vermeiden<\/h3>\n<p><\/p>\n<p>Ansible verwendet globale Variablen; es gibt teilweise einen Workaround in Form von <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/reference_appendices\/config.html#default-private-role-vars\">private_role_vars<\/a><\/noindex>, aber das ist kein Allheilmittel. <\/p>\n<p><\/p>\n<p>Hier ein Beispiel. Angenommen, wir haben <code>role_a<\/code> und <code>role_b<\/code><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\"># cat role_a\/defaults\/main.yml\n---\nmsg: a\n\n# cat role_a\/tasks\/main.yml\n---\n- debug:\n    msg: role_a={{ msg }}<\/code><\/pre>\n<p><\/p>\n<pre><code class=\"plaintext\"># cat role_b\/defaults\/main.yml\n---\nmsg: b\n\n# cat role_b\/tasks\/main.yml\n---\n- set_fact:\n    msg: b\n- debug:\n    msg: role_b={{ msg }}<\/code><\/pre>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: localhost\n  vars:\n    msg: hello\n  roles:\n    - role: role_a\n    - role: role_b\n  tasks:\n    - debug:\n        msg: play={{msg}}<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/7712ba529596ee00eaac22c9e59f7abe.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Eine interessante Sache ist, dass das Ergebnis der Playbooks von nicht immer offensichtlichen Dingen abh\u00e4ngt, wie beispielsweise der Reihenfolge der Rollen. Leider ist das in der Natur von Ansible, und das Beste, was man tun kann, ist, irgendwelche Absprachen zu verwenden, wie zum Beispiel, innerhalb der Rolle nur die Variablen zu verwenden, die in dieser Rolle beschrieben sind.<\/p>\n<p><\/p>\n<p><strong>SCHLECHT<\/strong>: eine globale Variable verwenden.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\"># cat roles\/some_role\/tasks\/main.yml\n---\ndebug:\n  var: java_home<\/code><\/pre>\n<p><\/p>\n<p><strong>GUT<\/strong>: In <code>defaults<\/code> die notwendigen Variablen definieren und sp\u00e4ter nur diese verwenden.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\"># cat roles\/some_role\/defaults\/main.yml\n---\nr__java_home:\n &quot;{{ java_home | default('\/path') }}&quot;\n\n# cat roles\/some_role\/tasks\/main.yml\n---\ndebug:\n  var: r__java_home\n<\/code><\/pre>\n<p><\/p>\n<h3 id=\"prefix-role-variables\">Pr\u00e4fix-Rollenvariablen<\/h3>\n<p><\/p>\n<p><strong>SCHLECHT<\/strong>: eine globale Variable verwenden.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\"># cat roles\/some_role\/defaults\/main.yml\n---\ndb_port: 5432<\/code><\/pre>\n<p><\/p>\n<p><strong>GUT<\/strong>: F\u00fcr Variablen in der Rolle Variablen mit dem Pr\u00e4fix des Rollennamens verwenden; das vereinfacht das Verst\u00e4ndnis, wenn man das Inventory betrachtet.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\"># cat roles\/some_role\/defaults\/main.yml\n---\nsome_role__db_port: 5432<\/code><\/pre>\n<p><\/p>\n<h3 id=\"use-loop-control-variable\">Verwenden Sie die Schleifensteuerungsvariable<\/h3>\n<p><\/p>\n<p><strong>SCHLECHT<\/strong>: Verwenden Sie in Schleifen die Standardvariable <code>item<\/code>, da dies zu unvorhergesehenem Verhalten f\u00fchren kann, wenn dieser Task\/Playbook irgendwo inkludiert wird.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n- hosts: localhost\n  tasks:\n    - debug:\n        msg: &quot;{{ item }}&quot;\n      loop:\n        - item1\n        - item2\n<\/code><\/pre>\n<p><\/p>\n<p><strong>GUT<\/strong>: Variablen im Loop \u00fcberschreiben durch <code>loop_var<\/code>.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n- hosts: localhost\n  tasks:\n    - debug:\n        msg: &quot;{{ item_name }}&quot;\n      loop:\n        - item1\n        - item2\n      loop_control:\n        loop_var: item_name\n<\/code><\/pre>\n<p><\/p>\n<h3 id=\"check-input-variables\">Eingangsvariablen \u00fcberpr\u00fcfen<\/h3>\n<p><\/p>\n<p>Wir haben uns darauf geeinigt, Variablenpr\u00e4fixe zu verwenden. Es ist sinnvoll zu \u00fcberpr\u00fcfen, ob sie so definiert sind, wie wir es erwarten, und dass sie beispielsweise nicht mit einem leeren Wert \u00fcberschrieben wurden.<\/p>\n<p><\/p>\n<p><strong>GUT<\/strong>: Variablen \u00fcberpr\u00fcfen.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- name: &quot;Verify that required string variables are defined&quot;\n  assert:\n    that: ahs_var is defined and ahs_var | length &gt; 0 and ahs_var != None\n    fail_msg: &quot;{{ ahs_var }} needs to be set for the role to work &quot;\n    success_msg: &quot;Required variables {{ ahs_var }} is defined&quot;\n  loop_control:\n    loop_var: ahs_var\n  with_items:\n    - ahs_item1\n    - ahs_item2\n    - ahs_item3<\/code><\/pre>\n<p><\/p>\n<h3 id=\"avoid-hashes-dictionaries-use-flat-structure\">Vermeiden Sie Hash-Dictionaries, verwenden Sie eine flache Struktur<\/h3>\n<p><\/p>\n<p>Wenn die Rolle ein Hash\/Dictionary in einem der Parameter erwartet, dann m\u00fcssen wir, wenn wir einen der darunterliegenden Parameter \u00e4ndern wollen, das gesamte Hash\/Dictionary neu definieren, was die Konfiguration komplizierter macht.<\/p>\n<p><\/p>\n<p><strong>SCHLECHT<\/strong>: Hash\/Dictionary verwenden.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\nuser:\n  name: admin\n  group: admin<\/code><\/pre>\n<p><\/p>\n<p><strong>GUT<\/strong>: Flache Variablenstruktur verwenden.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\nuser_name: admin\nuser_group: &quot;{{ user_name }}&quot;<\/code><\/pre>\n<p><\/p>\n<h3 id=\"create-idempotent-playbooks--roles\">Idempotente Playbooks &amp; Rollen erstellen<\/h3>\n<p><\/p>\n<p>Rollen und Playbooks sollten idempotent sein, da dies die Konfigurationsdrift reduziert und die Angst verringert, etwas zu besch\u00e4digen. Wenn Sie jedoch Molecule verwenden, ist dieses Verhalten standardm\u00e4\u00dfig gegeben.<\/p>\n<p><\/p>\n<h3 id=\"avoid-using-command-shell-modules\">Vermeiden Sie die Verwendung von Shell-Modulen.<\/h3>\n<p><\/p>\n<p>Die Verwendung des Shell-Moduls f\u00fchrt zu einer imperativen Beschreibung, anstelle der deklarativen, die das Kernelement von Ansible ist.<\/p>\n<p><\/p>\n<h3 id=\"test-your-roles-via-molecule\">Testen Sie Ihre Rollen mit Molecule.<\/h3>\n<p><\/p>\n<p>Molecule ist ein ziemlich flexibles Tool, schauen wir uns einige Szenarien an.<\/p>\n<p><\/p>\n<h4 id=\"molecule-multiple-instances\">Molecule Mehrere Instanzen.<\/h4>\n<p><\/p>\n<p>In <code>molecule.yml<\/code> im Abschnitt <code>platforms<\/code> Man kann mehrere Hosts beschreiben, die bereitgestellt werden sollen.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n    driver:\n      name: docker\n    platforms:\n      - name: postgresql-instance\n        hostname: postgresql-instance\n        image: registry.example.com\/postgres10:latest\n        pre_build_image: true\n        override_command: false\n        network_mode: host\n      - name: app-instance\n        hostname: app-instance\n        pre_build_image: true\n        image: registry.example.com\/docker_centos_ansible_tests\n        network_mode: host<\/code><\/pre>\n<p><\/p>\n<p>Diese Hosts k\u00f6nnen dann in <code>converge.yml<\/code> verwendet werden:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n- name: Alle zusammenf\u00fchren\n  hosts: all\n  vars:\n    ansible_user: root\n  roles:\n    - role: some_role\n\n- name: DB zusammenf\u00fchren\n  hosts: db-instance\n  roles:\n    - role: some_db_role\n\n- name: App zusammenf\u00fchren\n  hosts: app-instance\n  roles:\n    - role: some_app_role<\/code><\/pre>\n<p><\/p>\n<h4 id=\"ansible-verifier\">Ansible Verifier<\/h4>\n<p><\/p>\n<p>In molecule besteht die M\u00f6glichkeit, Ansible zu verwenden, um zu \u00fcberpr\u00fcfen, ob die Instanz korrekt konfiguriert wurde. Zudem ist dies seit der dritten Version standardm\u00e4\u00dfig der Fall. Diese Methode ist nicht so flexibel wie testinfra\/inspec, aber man kann pr\u00fcfen, ob der Inhalt einer Datei unseren Erwartungen entspricht.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n- name: Verify\n  hosts: all\n  tasks:\n    - name: copy config\n      copy:\n        src: expected_standalone.conf\n        dest: \/root\/wildfly\/bin\/standalone.conf\n        mode: &quot;0644&quot;\n        owner: root\n        group: root\n      register: config_copy_result\n\n    - name: Certify that standalone.conf changed\n      assert:\n        that: not config_copy_result.changed<\/code><\/pre>\n<p><\/p>\n<p>Oder einen Dienst bereitstellen, auf dessen Verf\u00fcgbarkeit warten und einen Smoke-Test durchf\u00fchren:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n  - name: \u00dcberpr\u00fcfen\n    hosts: solr\n    tasks:\n      - command: \/blah\/solr\/bin\/solr start -s \/solr_home -p 8983 -force\n      - uri:\n          url: http:\/\/127.0.0.1:8983\/solr\n          method: GET\n          status_code: 200\n        register: uri_result\n        until: uri_result is not failed\n        retries: 12\n        delay: 10\n      - name: Dokumente an Solr \u00fcbermitteln\n        command: \/blah\/solr\/bin\/post -c master \/exampledocs\/books.csv<\/code><\/pre>\n<p><\/p>\n<h3 id=\"put-complex-logic-into-modules--plugins\">Komplexe Logik in Module &amp; Plugins einf\u00fcgen<\/h3>\n<p><\/p>\n<p>Ansible propagiert einen deklarativen Ansatz, weshalb der Code bei Verzweigungen, Datenumwandlungen und Shell-Modulen schwer lesbar werden kann. Um dem entgegenzuwirken und die Verst\u00e4ndlichkeit zu erhalten, ist es sinnvoll, diese Komplexit\u00e4t durch die Erstellung eigener Module zu bek\u00e4mpfen.<\/p>\n<p><\/p>\n<h3 id=\"summarize-tips--tricks\">Zusammenfassung von Tipps &amp; Tricks<\/h3>\n<p><\/p>\n<ol>\n<li>Vermeiden Sie globale Variablen.<\/li>\n<li>Pr\u00e4fixrollenvariablen.<\/li>\n<li>Verwenden Sie Schleifensteuerungsvariablen.<\/li>\n<li>\u00dcberpr\u00fcfen Sie Eingangsvariablen.<\/li>\n<li>Vermeiden Sie Hash-Dictionaries, verwenden Sie flache Strukturen.<\/li>\n<li>Erstellen Sie idempotente Playbooks &amp; Rollen.<\/li>\n<li>Vermeiden Sie die Verwendung von Befehlszeilenmodulen.<\/li>\n<li>Testen Sie Ihre Rollen mit Molecule.<\/li>\n<li>Setzen Sie komplexe Logik in Module &amp; Plugins ein.<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"zaklyuchenie\">Fazit<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Wie man Ansible testet, ein Projekt in einem Jahr refakturiert und nicht den Verstand verliert\" src=\"\/wp-content\/uploads\/2020\/05\/c52a13f6ba5500fce506fb0d448b496e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Man kann die Infrastruktur in einem Projekt nicht einfach mal so refaktorisieren, selbst wenn Sie IaC haben. Es ist ein langwieriger Prozess, der Geduld, Zeit und Wissen erfordert.<\/p>\n<p><\/p>\n<h2 id=\"links\">Links<\/h2>\n<p><\/p>\n<ul>\n<li>Folien <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.mail.ru\/public\/266x\/3hJ2mQBzf\">How to test Ansible and don&#8217;t go nuts<\/a><\/noindex><\/li>\n<li>Video <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=GdrJv5oypfg\">How to test Ansible and don&#8217;t go nuts<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/467171\">Was ich gelernt habe, als ich 200.000 Zeilen Infrastrukturcode getestet habe<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/500040\/\">Ansible: Migration von 120 VM-Konfigurationen von CoreOS auf CentOS in 18 Monaten<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/342216\/\">Wie man auf Kr\u00fccken mit dem Testen seiner Distribution Fahrr\u00e4der zerbricht.<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/437004\/\">Teste mich, wenn du kannst, oder tr\u00e4umen YML-Programmierer von Ansible-Tests?<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/ultral\/awesome-iac-testing\">Eine Liste gro\u00dfartiger IaC-Testartikel, Vortr\u00e4ge &amp; Links<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/www.goncharov.xyz\/it\/ansible-testing-ru.html\">Cross-Post<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/500226\/\">Englische Version<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<p><strong>UPD1 2020.05.01 20:30<\/strong> \u2014 F\u00fcr die erste Profilierung von Playbooks kann verwendet werden <code>callback_whitelist = profile_tasks<\/code> um herauszufinden, was genau lange dauert. Danach gehen wir zu <noindex><a rel=\"nofollow\" href=\"https:\/\/shadow-soft.com\/turbo-charge-your-ansible\/\">den Klassikern zur Beschleunigung von Ansible<\/a><\/noindex>. Man kann es mit <noindex><a rel=\"nofollow\" href=\"https:\/\/mitogen.networkgenomics.com\/ansible_detailed.html\">mitogen<\/a><\/noindex><br \/>\n<strong>UPD2 2020.05.03 16:34<\/strong> \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/post\/500226\/\">Englische Version<\/a><\/noindex><\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/500058\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042d\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 DevOps-40 2020-03-18: \u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441\u043e \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f legacy, \u0442.\u043a. \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0434\u0443\u043c\u043a\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u0440\u0430\u0441\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441 \u0441\u0443\u0440\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u042d\u0442\u043e \u043d\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u043d\u0435 \u043f\u043b\u043e\u0445\u043e, \u044d\u0442\u043e \u0434\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e \u0441\u043f\u043e\u0440\u0438\u0442\u044c \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u0427\u0430\u0441\u0442\u044c\u044e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433. \u0420\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 Infrastructure as Code. \u0414\u0430 \u043d\u0430\u0447\u043d\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043a\u0430\u043a \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c Ansible \u0437\u0430 \u0433\u043e\u0434 \u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":80306,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-80305","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u042d\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 DevOps-40 2020-03-18: \u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441\u043e \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f legacy, \u0442.\u043a. \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0434\u0443\u043c\u043a\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u0440\u0430\u0441\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441 \u0441\u0443\u0440\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u042d\u0442\u043e \u043d\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u043d\u0435 \u043f\u043b\u043e\u0445\u043e, \u044d\u0442\u043e \u0434\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e \u0441\u043f\u043e\u0440\u0438\u0442\u044c \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u0427\u0430\u0441\u0442\u044c\u044e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433. \u0420\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 Infrastructure as Code. \u0414\u0430 \u043d\u0430\u0447\u043d\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043a\u0430\u043a \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c Ansible \u0437\u0430 \u0433\u043e\u0434 \u0438\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-nachat-testirovat-ansible-otrefaktorit-proekt-za-god-i-ne-sletet-s-katushek\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c Ansible, \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430 \u0433\u043e\u0434 \u0438 \u043d\u0435 \u0441\u043b\u0435\u0442\u0435\u0442\u044c \u0441 \u043a\u0430\u0442\u0443\u0448\u0435\u043a | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042d\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 DevOps-40 2020-03-18: \u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441\u043e \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f legacy, \u0442.\u043a. \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0434\u0443\u043c\u043a\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u0440\u0430\u0441\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441 \u0441\u0443\u0440\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u042d\u0442\u043e \u043d\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u043d\u0435 \u043f\u043b\u043e\u0445\u043e, \u044d\u0442\u043e \u0434\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e \u0441\u043f\u043e\u0440\u0438\u0442\u044c \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u0427\u0430\u0441\u0442\u044c\u044e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433. \u0420\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 Infrastructure as Code. \u0414\u0430 \u043d\u0430\u0447\u043d\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043a\u0430\u043a \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c Ansible \u0437\u0430 \u0433\u043e\u0434 \u0438\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-nachat-testirovat-ansible-otrefaktorit-proekt-za-god-i-ne-sletet-s-katushek\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-04T23:42:50+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-04T23:42:50+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47So starten Sie mit dem Testen von Ansible, refactorieren Sie Ihr Projekt in einem Jahr und bleiben Sie dabei auf der Spur | ProHoster","description":"Dies ist die Aufzeichnung des Vortrags auf DevOps-40 am 18.03.2020: Ab dem zweiten Commit wird jeder Code zu Legacy, da die urspr\u00fcnglichen Ideen von der harten Realit\u00e4t abweichen. Das ist weder gut noch schlecht, sondern eine Gegebenheit, mit der man sich arrangieren muss. Ein Teil dieses Prozesses ist das Refactoring. Refactoring von Infrastructure as Code. M\u00f6ge die Geschichte beginnen, wie man Ansible in einem Jahr refactored und","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-nachat-testirovat-ansible-otrefaktorit-proekt-za-god-i-ne-sletet-s-katushek","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c Ansible, \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430 \u0433\u043e\u0434 \u0438 \u043d\u0435 \u0441\u043b\u0435\u0442\u0435\u0442\u044c \u0441 \u043a\u0430\u0442\u0443\u0448\u0435\u043a | ProHoster","og:description":"\u042d\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 DevOps-40 2020-03-18: \u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441\u043e \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f legacy, \u0442.\u043a. \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0434\u0443\u043c\u043a\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u0440\u0430\u0441\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441 \u0441\u0443\u0440\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u042d\u0442\u043e \u043d\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0438 \u043d\u0435 \u043f\u043b\u043e\u0445\u043e, \u044d\u0442\u043e \u0434\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e \u0441\u043f\u043e\u0440\u0438\u0442\u044c \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u0427\u0430\u0441\u0442\u044c\u044e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433. \u0420\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 Infrastructure as Code. \u0414\u0430 \u043d\u0430\u0447\u043d\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043a\u0430\u043a \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c Ansible \u0437\u0430 \u0433\u043e\u0434 \u0438","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-nachat-testirovat-ansible-otrefaktorit-proekt-za-god-i-ne-sletet-s-katushek","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-04T23:42:50+00:00","article:modified_time":"2020-05-04T23:42:50+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"80305","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:20:41","updated":"2022-09-29 15:21:39"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/80305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=80305"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/80305\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/80306"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=80305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=80305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=80305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}