{"id":3929,"date":"2024-09-02T07:00:00","date_gmt":"2024-09-02T05:00:00","guid":{"rendered":"https:\/\/www.my-it-brain.de\/wordpress\/?p=3929"},"modified":"2024-08-21T16:47:50","modified_gmt":"2024-08-21T14:47:50","slug":"demonstration-von-ansible-lint-am-beispiel-einer-ansible-collection","status":"publish","type":"post","link":"https:\/\/www.my-it-brain.de\/wordpress\/demonstration-von-ansible-lint-am-beispiel-einer-ansible-collection\/","title":{"rendered":"Demonstration von Ansible Lint am Beispiel einer Ansible Collection"},"content":{"rendered":"\n<p>In diesem Beitrag erkl\u00e4re ich kurz, was <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/\">Ansible Lint<\/a> ist und demonstriere dessen Anwendung am Beispiel meiner Ansible Collection <a href=\"https:\/\/codeberg.org\/tronde\/nextcloud\">tronde\/nextcloud<\/a>.<\/p>\n\n\n\n<p>Er richtet sich prim\u00e4r an Personen, die mit Ansible Lint noch nicht vertraut sind. Linting-Profis werden vermutlich keine neuen Erkenntnisse gewinnen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Was ist Ansible Lint und wof\u00fcr ist es gut?<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Lint<\/strong> (<a href=\"https:\/\/de.wikipedia.org\/wiki\/Englische_Sprache\">englisch<\/a> f\u00fcr \u201e<a href=\"https:\/\/de.wikipedia.org\/wiki\/Fussel\">Fussel<\/a>\u201c) ist eine <a href=\"https:\/\/de.wikipedia.org\/wiki\/Software\">Software<\/a> zur <a href=\"https:\/\/de.wikipedia.org\/wiki\/Statische_Code-Analyse\">statischen Code-Analyse<\/a>. Davon abgeleitet hat sich das Verb <strong>linten<\/strong> (englisch <em>to lint<\/em>) f\u00fcr das Durchf\u00fchren der statischen Code-Analyse etabliert.<\/p>\n<cite><a href=\"https:\/\/de.wikipedia.org\/wiki\/Lint_(Programmierwerkzeug)\">https:\/\/de.wikipedia.org\/wiki\/Lint_(Programmierwerkzeug)<\/a><\/cite><\/blockquote>\n\n\n\n<p>Dem obigen Zitat und der <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/\">Projektdokumentation<\/a> folgend, ist Ansible Lint dementsprechend ein Werkzeug zur statischen Code-Analyse von Ansible Playbooks, Roles und Collections. Mit der Anwendung dieses Werkzeugs auf die eigenen Ansible-Inhalte kann sichergestellt werden, dass diese g\u00e4ngigen Konventionen und Standards entsprechen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wie wird Ansible Lint installiert?<\/h2>\n\n\n\n<p>Die Dokumentation beschreibt verschiedene <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/installing\/\">Installationsverfahren<\/a>. Ich habe <code>ansible-lint<\/code> als Bestandteil der <a href=\"https:\/\/ansible.readthedocs.io\/projects\/dev-tools\/\">Ansible Development Tools (ADT)<\/a> <a href=\"https:\/\/ansible.readthedocs.io\/projects\/dev-tools\/installation\/\">installiert<\/a>. Dies ist ein Werkzeugkasten mit weiteren Programmen wie z.B. `ansible-core` und <a href=\"https:\/\/ansible.readthedocs.io\/projects\/molecule\/\">Ansible Molecule<\/a>, welche ich f\u00fcr die Entwicklung meiner Ansible Collection nutze.<\/p>\n\n\n\n<p>Auf meiner Fedora Workstation habe ich die ADT wie folgt installiert:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~]$ mkdir venv\n~]$ cd venv\nvenv]$ ]$ python -m venv adt\nvenv]$ source adt\/bin\/activate\n(adt) venv]$ pip install pip --upgrade\nRequirement already satisfied: pip in .\/adt\/lib64\/python3.12\/site-packages (23.3.2)\nCollecting pip\n  Using cached pip-24.2-py3-none-any.whl.metadata (3.6 kB)\nUsing cached pip-24.2-py3-none-any.whl (1.8 MB)\nInstalling collected packages: pip\n  Attempting uninstall: pip\n    Found existing installation: pip 23.3.2\n    Uninstalling pip-23.3.2:\n      Successfully uninstalled pip-23.3.2\nSuccessfully installed pip-24.2\n(adt) venv]$  pip install ansible-dev-tools\nCollecting ansible-dev-tools\n  Using cached ansible_dev_tools-24.7.2-py3-none-any.whl.metadata (11 kB)\n\u2026 Ausgabe gek\u00fcrzt\n(adt) venv]$ adt --version\nansible-builder                          3.1.0\nansible-core                             2.17.3\nansible-creator                          24.7.1\nansible-dev-environment                  24.7.0\nansible-dev-tools                        24.7.2\nansible-lint                             24.7.0\nansible-navigator                        24.8.0\nansible-sign                             0.1.1\nmolecule                                 24.8.0\npytest-ansible                           24.8.0\ntox-ansible                              24.8.0<\/code><\/pre>\n\n\n\n<p>Ansible Lint liefert eine ganze Reihe von <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/profiles\/\">Profilen<\/a> mit, welche Autoren unterst\u00fctzen, die Code-Qualit\u00e4t schrittweise zu verbessern. Der Befehl <code>ansible-lint --list-profiles<\/code> gibt die verf\u00fcgbaren Profile mit einer Beschreibung aus.<\/p>\n\n\n\n<p>Ich werde im Folgenden mit dem Profil <em><a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/profiles\/#shared\">shared<\/a><\/em> arbeiten, welches f\u00fcr Autoren gedacht ist, die ihre Collection auf <a href=\"https:\/\/galaxy.ansible.com\">https:\/\/galaxy.ansible.com<\/a> ver\u00f6ffentlichen m\u00f6chten.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Eine Collection linten<\/h2>\n\n\n\n<p>Bevor es zur Sache geht, wechsel ich in das Projektverzeichnis meiner Ansible Collection und erstelle einen neuen Branch, mit dem Befehl <code>git checkout -b lint<\/code>. Die in meinem Repo vorhandene Datei <code>.ansible-lint-ignore<\/code> l\u00f6sche ich, da ich im folgenden alle Fehler und Regelverst\u00f6\u00dfe sehen m\u00f6chte. Zu Beginn stellt sich mein Arbeitsverzeichnis wie folgt dar:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(adt) nextcloud]$ git status\nOn branch lint\nChanges not staged for commit:\n  (use \"git add\/rm &lt;file&gt;...\" to update what will be committed)\n  (use \"git restore &lt;file&gt;...\" to discard changes in working directory)\n\tdeleted:    .ansible-lint-ignore\n\nno changes added to commit (use \"git add\" and\/or \"git commit -a\")<\/code><\/pre>\n\n\n\n<p>Das Programm <code>ansible-lint<\/code> besitzt mit der Option <code>--fix<\/code> die F\u00e4higkeit, Fehler automatisch zu korrigieren und auch YAML-Dateien neu zu formatieren. Der folgende Code-Block umfasst die gek\u00fcrzte Ausgabe, wenn das Kommando <code>ansible-lint --profile=shared --fix<\/code> im Arbeitsverzeichnis ausgef\u00fchrt wird.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(adt) nextcloud]$ ansible-lint --profile=shared --fix\nWARNING  Listing 37 violation(s) that are fatal\ngalaxy&#91;no-changelog]: No changelog found. Please add a changelog file. Refer to the galaxy.md file for more info.\ngalaxy.yml:1\n\nvar-naming&#91;pattern]: Variables names should match ^&#91;a-z_]&#91;a-z0-9_]*$ regex. (NC_HTML) (vars: NC_HTML)\nroles\/backup_restore_nextcloud\/defaults\/main.yml:4\n\n\u2026\n\nrisky-file-permissions: File permissions unset or incorrect.\nroles\/backup_restore_nextcloud\/tasks\/main.yml:18 Task\/Handler: Copy backup files to container host\n\nno-changed-when: Commands should not change things if nothing needs doing.\nroles\/backup_restore_nextcloud\/tasks\/main.yml:40 Task\/Handler: Import tarball contents into an existing podman volume\n\nno-changed-when: Commands should not change things if nothing needs doing.\nroles\/backup_restore_nextcloud\/tasks\/main.yml:54 Task\/Handler: Export podman volumes to tarballs\n\nvar-naming&#91;pattern]: Variables names should match ^&#91;a-z_]&#91;a-z0-9_]*$ regex. (MYSQL_DATABASE) (vars: MYSQL_DATABASE)\nroles\/deploy_nextcloud_with_mariadb_pod\/defaults\/main.yml:13\n\n\u2026\n\nRead documentation for instructions on how to ignore specific rule violations.\n\nModified 6 files.\n                     Rule Violation Summary                      \n count tag                    profile rule associated tags       \n    33 var-naming&#91;pattern]    basic   idiom                      \n     1 risky-file-permissions safety  unpredictability           \n     1 galaxy&#91;no-changelog]   shared  metadata                   \n     2 no-changed-when        shared  command-shell, idempotency \n\nFailed: 37 failure(s), 0 warning(s) on 25 files. Profile 'shared' was required, but 'min' profile passed.<\/code><\/pre>\n\n\n\n<p>Obige Ausgabe:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Benennt Funde mit Pfadangabe und Zeilennummer<\/li>\n\n\n\n<li>F\u00fchrt 37 Fehler auf, inkl. der Regeln, die nicht eingehalten werden; Beispiele\n<ul class=\"wp-block-list\">\n<li><code>galaxy[no-changelog]: No changelog found. Please add a changelog file. Refer to the galaxy.md file for more info.<\/code><\/li>\n\n\n\n<li><code>risky-file-permissions: File permissions unset or incorrect.<\/code><\/li>\n\n\n\n<li><code>no-changed-when: Commands should not change things if nothing needs doing.<\/code><\/li>\n\n\n\n<li><code>var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex.<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Informiert, dass <code>ansible-lint<\/code> \u00c4nderungen an 6 Dateien vorgenommen hat<\/li>\n<\/ul>\n\n\n\n<p>Mit <code>git diff <\/code>verschaffe ich mir einen \u00dcberblick, welche \u00c4nderungen <code>ansible-lint<\/code> vorgenommen hat. Dies sind in meinem Fall:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Quoting von Strings<\/li>\n\n\n\n<li>Einr\u00fcckung von Kommentaren<\/li>\n<\/ul>\n\n\n\n<p>Als N\u00e4chstes sehe ich mir die \u00fcbrigen Fehler der Reihe nach an. <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/rules\/\">Die Dokumentation beinhaltet eine \u00dcbersicht mit Beschreibungen der einzelnen Regeln<\/a>. Dies ist n\u00fctzlich, wenn der kurze Text in der Ausgabe von <code>ansible-lint<\/code> nicht ausreichend ist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>galaxy[no-changelog]: No changelog found. Please add a changelog file.<\/code><\/h3>\n\n\n\n<p>Unter <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/rules\/galaxy\/#changelog-details\">Galaxy: Changelog Details<\/a> finden sich Hinweise, wie dieser Fehler zu beheben ist. Ich erstelle die leere Datei <code>CHANGELOG.md<\/code> im Wurzelverzeichnis meiner Collection und der Fehler ist abgestellt.<\/p>\n\n\n\n<p>Nat\u00fcrlich werde ich diese Datei zuk\u00fcnftig nutzen, um die wichtigsten \u00c4nderungen zu dokumentieren. ;-)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>risky-file-permissions: File permissions unset or incorrect.<\/code><\/h3>\n\n\n\n<p>Auch hier habe ich kurz in der Dokumentation unter <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/rules\/risky-file-permissions\/\">risky-file-permissions<\/a> nachgesehen. Den Fehler habe ich abgestellt, indem ich den Parameter <code>mode: 0600<\/code> zum Task hinzugef\u00fcgt habe.<\/p>\n\n\n\n<p>Dies war ein Fl\u00fcchtigkeitsfehler, wie er h\u00e4ufig passieren kann, wenn man seinen Code nicht konsequent \u00fcberpr\u00fcft. Ohne den Dateimode explizit zu setzen, kann dies zu unvorhersehbaren bzw. \u00fcberraschenden Verhalten f\u00fchren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>no-changed-when: Commands should not change things if nothing needs doing.<\/code><\/h3>\n\n\n\n<p>An zwei Stellen bin ich leider nicht herumgekommen, das <code>ansible.builtin.command<\/code> Modul zu verwenden, da kein natives Modul f\u00fcr diese Aufgabe existiert. Betrachtet man sich die beiden Tasks f\u00e4llt auf, dass diese jedes Mal Daten verarbeiten werden. Sie sind nicht idempotent. Im Ergebnis k\u00f6nnen sie erfolgreich sein oder fehlschlagen, aber sie werden immer Daten verarbeiten und dadurch \u00e4ndern.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> 41     - name: Import tarball contents into an existing podman volume\n 42       ansible.builtin.command:\n 43         cmd: |\n 44           podman volume import\n 45           {{ item }} {{ backup_restore_nextcloud_import_path }}\/{{ item }}.tar\n 46       loop:\n 47         - \"{{ NC_HTML }}\"\n 48         - \"{{ NC_APPS }}\"\n 49         - \"{{ NC_CONFIG }}\"\n 50         - \"{{ NC_DATA }}\"\n 51         - \"{{ MYSQL_DATA }}\"\n 52            \n 53 # I need to use the command module as the volume module lacks the functionality\n 54 # to export podman volumes.\n 55 - name: Export podman volumes to tarballs\n 56   ansible.builtin.command:\n 57     cmd: podman volume export {{ item }} --output {{ backup_restore_nextcloud_export_path }}\/{{ item }}.tar\n 58   loop:    \n 59     - \"{{ NC_HTML }}\"\n 60     - \"{{ NC_APPS }}\"\n 61     - \"{{ NC_CONFIG }}\"\n 62     - \"{{ NC_DATA }}\"\n 63     - \"{{ MYSQL_DATA }}\"\n 64   tags:    \n 65     - never\n 66     - backup<\/code><\/pre>\n\n\n\n<p>Um herauszufinden, wie ich <code>ansible-lint<\/code> zufriedenstellen kann, schaue ich wieder in der Doku unter <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/rules\/no-changed-when\/\">no-changed-when<\/a> nach. Nach der dortigen Beschreibung ist mein Fehler, dass ich den R\u00fcckgabewert des Kommandos nicht behandel. Daher registriere ich nun eine Variable je Task, die die Task-Ausgabe aufnimmt und pr\u00fcfe den R\u00fcckgabewert. Ist der R\u00fcckgabewert gleich 0 wird der Task-Status auf <code>changed<\/code> gesetzt, ist der R\u00fcckgabewert ungleich 0 wird der Status entsprechend auf <code>failed<\/code> gesetzt. Das ganze sieht nun wie folgt aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> 41     - name: Import tarball contents into an existing podman volume\n 42       ansible.builtin.command:\n 43         cmd: |\n 44           podman volume import\n 45           {{ item }} {{ backup_restore_nextcloud_import_path }}\/{{ item }}.tar\n 46       register: __import_tar_output\n 47       changed_when: __import_tar_output.rc == 0\n 48       failed_when: __import_tar_output.rc != 0\n 49       loop:\n 50         - \"{{ NC_HTML }}\"\n 51         - \"{{ NC_APPS }}\"\n 52         - \"{{ NC_CONFIG }}\"\n 53         - \"{{ NC_DATA }}\"\n 54         - \"{{ MYSQL_DATA }}\"\n 55  \n 56 # I need to use the command module as the volume module lacks the functionality\n 57 # to export podman volumes.\n 58 - name: Export podman volumes to tarballs\n 59   ansible.builtin.command:\n 60     cmd: podman volume export {{ item }} --output {{ backup_restore_nextcloud_export_path }}\/{{ item }}.tar\n 61   register: __import_tar_output\n 62   changed_when: __import_tar_output.rc == 0\n 63   failed_when: __import_tar_output.rc != 0\n 64   loop:\n 65     - \"{{ NC_HTML }}\"\n 66     - \"{{ NC_APPS }}\"\n 67     - \"{{ NC_CONFIG }}\"\n 68     - \"{{ NC_DATA }}\"\n 69     - \"{{ MYSQL_DATA }}\"\n 70   tags:\n 71     - never\n 72     - backup<\/code><\/pre>\n\n\n\n<p>Collection-intern verwendete Variablen leite ich mit zwei Unterstrichen (&#8218;_&#8216;) ein, um mir zu verdeutlichen, dass diese nicht durch den Nutzer gesetzt werden und daher auch nicht im <code>README.md<\/code> oder <code>defaults\/main.yml<\/code> dokumentiert sind.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex.<\/code><\/h3>\n\n\n\n<p>Hier brauche ich nicht weiter nachzuschlagen. Ich versto\u00dfe gegen diese Regel, da ich meine Variablen-Namen gro\u00dfgeschrieben habe. Die Ausgabe von <code>ansible-lint<\/code> zeigt dies deutlich:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var-naming&#91;pattern]: Variables names should match ^&#91;a-z_]&#91;a-z0-9_]*$ regex. (NC_HTML) (vars: NC_HTML)\nroles\/backup_restore_nextcloud\/defaults\/main.yml:4<\/code><\/pre>\n\n\n\n<p>Diese Meldungen lassen sich mit folgendem Bash-Einzeiler abstellen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ for text in $(cut -d':' -f 1 roles\/deploy_nextcloud_with_mariadb_pod\/defaults\/main.yml | grep -v '^$\\|^#\\|---'); do find roles -type f -iname \"*.yml\" | xargs sed -i -e \"s\/$text\/\\L&amp;\/g\"; done<\/code><\/pre>\n\n\n\n<p>Aus verschiedenen Gr\u00fcnden hebe ich mir die \u00dcberarbeitung f\u00fcr sp\u00e4ter auf und nutze die Meldung, um zu demonstrieren, wie man <code>ansible-lint<\/code> dazu bringt, bestimmte Fehler zu ignorieren.<\/p>\n\n\n\n<p>Um Regeln f\u00fcr ausgew\u00e4hlte Dateien zu ignorieren, spezifiziert man den jeweiligen Dateinamen und den Namen der Regel in der Datei <code>.ansible-lint-ignore<\/code>, welche im Wurzelverzeichnis der Collection erstellt wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nextcloud]$ cat .ansible-lint-ignore \nroles\/deploy_nextcloud_with_mariadb_pod\/defaults\/main.yml var-naming&#91;pattern]\nroles\/backup_restore_nextcloud\/defaults\/main.yml var-naming&#91;pattern]<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Zweiter Durchgang mit ansible-lint<\/h2>\n\n\n\n<p>Damit habe ich alle Probleme, die im ersten Durchlauf von <code>ansible-lint<\/code> gefunden wurden, adressiert. Ein zweiter Durchlauf zeigt das Ergebnis meiner Arbeit:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(adt) nextcloud]$ ansible-lint --profile=shared\nWARNING  Listing 33 violation(s) marked as ignored, likely already known\nvar-naming&#91;pattern]: Variables names should match ^&#91;a-z_]&#91;a-z0-9_]*$ regex. (NC_HTML) (vars: NC_HTML) (warning) # ignored\nroles\/backup_restore_nextcloud\/defaults\/main.yml:4\n\n\u2026Ausgabe gek\u00fcrzt\n\nWARNING  Listing 1 violation(s) that are fatal\nyaml&#91;octal-values]: Forbidden implicit octal value \"0600\"\nroles\/backup_restore_nextcloud\/tasks\/main.yml:22\n\nRead documentation for instructions on how to ignore specific rule violations.\n\n                Rule Violation Summary                 \n count tag                profile rule associated tags \n     1 yaml&#91;octal-values] basic   formatting, yaml     \n\nFailed: 1 failure(s), 33 warning(s) on 27 files. Profile 'shared' was required, but 'min' profile passed.<\/code><\/pre>\n\n\n\n<p>Die ignorierten Regelverst\u00f6\u00dfe werden als Warnung weiterhin ausgegeben, nehmen jedoch keinen Einfluss auf die abschlie\u00dfende Bewertung.  Daf\u00fcr habe ich einen neuen Fehler (<a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/rules\/yaml\/#octals\" data-type=\"link\" data-id=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/rules\/yaml\/#octals\">yaml[octal-values]<\/a>) eingebaut. Nach dem aktuellen Regelwerk erfordern oktale Werte ein explizites Quoting, um als Strings verarbeitet zu werden.<\/p>\n\n\n\n<p>Nachdem ich das Problem mit <code>mode: '0600'<\/code> behoben habe, endet ein weiterer Lauf von <code>ansible-lint<\/code> schlussendlich mit:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Passed: 0 failure(s), 33 warning(s) on 27 files. Profile 'shared' was required, but 'production' profile passed.<\/code><\/pre>\n\n\n\n<p>Damit erf\u00fcllt meine Collection aktuell sogar die Anforderungen des n\u00e4chst h\u00f6heren Profils <a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/profiles\/#production\">production<\/a>; allerdings nur, weil ich einige Regeln bewusst ignoriere. Daher ist aktuell noch nicht sichergestellt, dass meine Collection tats\u00e4chlich bei einem Import auf Ansible Galaxy akzeptiert wird.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Zusammenfassung<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ansible Lint ist ein Werkzeug zur statischen Analyse von Ansible Playbooks, Roles und Collections<\/li>\n\n\n\n<li>Das Werkzeug unterst\u00fctzt Autoren dabei, g\u00e4ngige Konventionen und Standards einzuhalten und die Qualit\u00e4t des eigenen Codes auf einem Mindest-Niveau zu halten<\/li>\n\n\n\n<li>Ansible Lint bietet mehrere Profile f\u00fcr verschiedene Anwendungsf\u00e4lle<\/li>\n\n\n\n<li>Regeln k\u00f6nnen bei Bedarf ignoriert werden, was zwar das Ergebnis des Linting beeinflusst, die Qualit\u00e4t jedoch nicht steigert<\/li>\n\n\n\n<li>Linting sollte fester Bestandteil des eigenen Entwicklungsworkflows sein und stets nach \u00c4nderungen durchgef\u00fchrt werden<\/li>\n<\/ul>\n\n\n\n<p>Ich pers\u00f6nlich f\u00fchre <code>ansible-lint<\/code> gern in einem eigenst\u00e4ndigen Schritt aus. Es besteht jedoch auch die M\u00f6glichkeit, dies in den verwendeten Editor, die genutzte IDE oder Molecule zu integrieren und bei \u00c4nderungen automatisch laufen zu lassen.<\/p>\n\n\n\n<p>Ich freue mich, wenn euch dieser Artikel gefallen hat.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quellen und weiterf\u00fchrende Links<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/\">Ansible Lint Documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/rules\/\">Ansible Lint Rules<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/ansible.readthedocs.io\/projects\/lint\/profiles\/\">Ansible Lint Profiles<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/ansible.readthedocs.io\/projects\/dev-tools\/\">Ansible Development Tools (ADT)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/ansible.readthedocs.io\/projects\/molecule\/\">Ansible Molecule<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In diesem Beitrag erkl\u00e4re ich kurz, was Ansible Lint ist und demonstriere dessen Anwendung am Beispiel meiner Ansible Collection tronde\/nextcloud. Er richtet sich prim\u00e4r an Personen, die mit Ansible Lint noch nicht vertraut sind. Linting-Profis werden vermutlich keine neuen Erkenntnisse gewinnen. Was ist Ansible Lint und wof\u00fcr ist es gut? Lint (englisch f\u00fcr \u201eFussel\u201c) ist<span class=\"continue-reading\"> <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/demonstration-von-ansible-lint-am-beispiel-einer-ansible-collection\/\">[Weiterlesen&#8230;]<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_metis_text_type":"","_metis_text_length":0,"_post_count":0,"footnotes":""},"categories":[532],"tags":[848,430,305],"class_list":["post-3929","post","type-post","status-publish","format-standard","hentry","category-ansible","tag-ansible-lint","tag-osbn","tag-planet"],"_links":{"self":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/3929","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/comments?post=3929"}],"version-history":[{"count":8,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/3929\/revisions"}],"predecessor-version":[{"id":3937,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/3929\/revisions\/3937"}],"wp:attachment":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/media?parent=3929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/categories?post=3929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/tags?post=3929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}