<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Skipped on Zwindler's Reflection</title><link>https://blog.zwindler.fr/tags/skipped/</link><description>Recent content in Skipped on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Mon, 07 Feb 2022 07:00:00 +0000</lastBuildDate><atom:link href="https://blog.zwindler.fr/tags/skipped/index.xml" rel="self" type="application/rss+xml"/><item><title>Ansible : subtilités avec « defined » et « skipped »</title><link>https://blog.zwindler.fr/2022/02/07/ansible-subtilite-defined-skipped/</link><pubDate>Mon, 07 Feb 2022 07:00:00 +0000</pubDate><guid>https://blog.zwindler.fr/2022/02/07/ansible-subtilite-defined-skipped/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/10/ansible_logo.webp" alt="Featured image of post Ansible : subtilités avec « defined » et « skipped »" /&gt;&lt;h2 id="ansible-des-fois-cest-pénible"&gt;Ansible des fois c’est pénible
&lt;/h2&gt;&lt;p&gt;Je vous parle souvent d’Ansible car c’est vraiment un outil qui a changé ma vie d’Ops. Pour autant, des fois c’est up peu pénible à comprendre&amp;hellip;&lt;/p&gt;
&lt;p&gt;Dans cet article je vais vous parler d’un de ces moments où j’ai vraiment pesté contre les Devs (c’est pas la première fois&amp;hellip;). L’erreur initiale était mienne (&lt;em&gt;a priori&lt;/em&gt;) mais les workarounds que j’ai testés me paraissaient légitimes&amp;hellip;&lt;/p&gt;
&lt;p&gt;Et cet article va me permettre de vous illustrer 2 concepts utiles pour vos tâches et variables Ansible qui sont skipped et defined.&lt;/p&gt;
&lt;h2 id="cest-lhistoire-de-deux-tâches"&gt;C’est l’histoire de deux tâches
&lt;/h2&gt;&lt;p&gt;Pour remettre les choses dans le contexte : j’ai certaines actions que j’effectue ou non selon les cas sur un groupe d’hôtes donnés. Et c’était typiquement le cas ici…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: le code Ansible en lui-même n’est pas impeccable, on peut (et d’ailleurs, on va) faire beaucoup plus propre ; ce n’est pas ce que je veux montrer ici.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Voilà les tâches incriminés :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Get some content from a command&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;command outputting something&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;changed_when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;command_output&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;not_in_test_env&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Write command_output to file&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output_file_path }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output.stdout }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Le contenu des deux tâches importe peu, car c’est plus des limitations d’Ansible que je vais vous présenter ensuite qui importe. On pourra retrouver cette limitation dans d’autres cas plus pertinents.&lt;/p&gt;
&lt;p&gt;Ce qu’il faut retenir, c’est que :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la première tâche génère un output texte et enregistre le contenu dans une variable &lt;strong&gt;&lt;em&gt;command_output&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;la seconde tâche copie le contenu de cette variable dans un fichier texte&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cela pourrait donc être n’importe quelle variable qu’on collecte de n’importe quelle autre façon&amp;hellip; On peut donc légitimement appliquer ce genre d’opération dans d’autres contextes, avec certains nodes où on souhaite exécuter ces deux actions et certains autres, non.&lt;/p&gt;
&lt;h2 id="et-là-cest-le-drame"&gt;Et là, c’est le drame.
&lt;/h2&gt;&lt;p&gt;Lors du moment où j’ai eu mon erreur, &lt;strong&gt;j’étais persuadé d’avoir bien&lt;/strong&gt; &lt;strong&gt;mis un when: not_in_test_env&lt;/strong&gt; pour skip la 2ème tâche aussi si la première l’est. Visiblement ce n’est pas le cas puisque je n’ai pas pu reproduire&amp;hellip;&lt;/p&gt;
&lt;p&gt;Dans le premier cas qui nous intéresse donc, si &lt;em&gt;&lt;strong&gt;not_in_test_env&lt;/strong&gt;&lt;/em&gt; est positionné à &lt;strong&gt;true&lt;/strong&gt;, pas de problème.&lt;/p&gt;
&lt;p&gt;En revanche, si je saute la première partie grâce à la variable &lt;em&gt;&lt;strong&gt;not_in_test_env&lt;/strong&gt;&lt;/em&gt; positionnée à &lt;strong&gt;false&lt;/strong&gt; dans les fichiers de configuration de l’inventaire, vu qu’a priori j’ai fait une erreur et n’ai pas correctement écrit mon when dans la 2ème tâche, la première tâche est bien « Skipped » lors de l’exécution du playbook, mais la tâche suivante « Fail » misérablement.&lt;/p&gt;
&lt;p&gt;Et pour cause&amp;hellip; Ansible essaye à tout prix de résoudre la variable &lt;strong&gt;command_output.stdout&lt;/strong&gt; alors même que la tâche va être « Skipped ». Sur le moment, je n’arrivais pas à comprendre POURQUOI ça n’étais pas skip et j’ai donc essayer de trouver des parades.&lt;/p&gt;
&lt;h2 id="pile-tu-gagnes-"&gt;Pile, tu gagnes, &amp;hellip;
&lt;/h2&gt;&lt;p&gt;Ma première idée a été de tenter de feinter l’erreur en initialisant la variable dans le cas où elle n’est pas renseignée car la tâche est « Skipped ».&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Write command_output to file&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output_file_path }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output.stdout | default(&amp;#39;&amp;#39;) }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Manque de bol pour moi&amp;hellip; je suis encore sur une vieille version d’Ansible, le &lt;strong&gt;| default( »)&lt;/strong&gt; ne fonctionne pas sur les sous-variables (ici &lt;strong&gt;.stdout&lt;/strong&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Beginning in version 2.8, attempting to access an attribute of an Undefined value in Jinja will return another Undefined value, rather than throwing an error immediately. This means that you can now simply use a default with a value in a nested data structure (in other words, &lt;code&gt;{{ foo.bar.baz | default('DEFAULT') }}&lt;/code&gt;) when you do not know if the intermediate values are defined.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html" target="_blank" rel="noopener"
&gt;https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;| default&lt;/strong&gt; ou pas, Ansible essaye donc de résoudre &lt;strong&gt;command_output.stdout&lt;/strong&gt; ; la tâche continue donc de « Fail »&amp;hellip;&lt;/p&gt;
&lt;h2 id="-face-je-perd"&gt;&amp;hellip; Face, je perd
&lt;/h2&gt;&lt;p&gt;En passant en mode « debug », j’ai remarqué quelque chose que je ne savais pas. Quand on « Skip » une tâche avec un &lt;strong&gt;register:&lt;/strong&gt;, la variable pas enregistrée (car skip) n’est &lt;strong&gt;pas&lt;/strong&gt; vide. Mon problème est que &lt;strong&gt;command_output.stdout&lt;/strong&gt; n’existe effectivement pas, mais &lt;strong&gt;command_output&lt;/strong&gt; si.&lt;/p&gt;
&lt;p&gt;Plus précisément, Ansible injecte une sous entrée &lt;strong&gt;command_output.skipped&lt;/strong&gt; positionnée à « true ».&lt;/p&gt;
&lt;p&gt;Je me suis donc dit : banco ! Je vais modifier ma condition pour qu’elle empêche l’exécution de la tâche si &lt;strong&gt;command_output.skipped&lt;/strong&gt; existe (car ça veut dire que &lt;strong&gt;command_output.stdout&lt;/strong&gt; n’existe pas).&lt;/p&gt;
&lt;p&gt;Ça donne quelque chose comme ça :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Get some content from a command&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;command outputting something&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;changed_when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;command_output&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;not_in_test_env&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Write command_output to file&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output_file_path }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output.stdout }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;not command_output.skipped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et là, dans le cas où &lt;strong&gt;not_in_test_env&lt;/strong&gt; est false, ça ne fail plus.&lt;/p&gt;
&lt;p&gt;Victoire ? Non bien sûr&amp;hellip; car &lt;strong&gt;command_output.skipped&lt;/strong&gt; n’existe pas (pas de skipped = false) quand la tâche est exécutée (c’est à dire « pas skipped »). Retour à la case départ : maintenant ça « Fail » dans le cas où on ne « Skip » plus&amp;hellip;&lt;/p&gt;
&lt;h2 id="sur-la-tranche-je-perds-aussi"&gt;Sur la tranche, je perds aussi
&lt;/h2&gt;&lt;p&gt;Dernière idée, on peut se dire que le plus simple / propre, c’est tout simplement de tester le fait qu’une variable (que ce soit &lt;strong&gt;command_output.stdout&lt;/strong&gt; ou &lt;strong&gt;command_output.skipped&lt;/strong&gt;) soit « defined » pour décider si on exécute ou pas la tâche.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Write command_output to file&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output_file_path }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output.stdout }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;command_output.stdout is defined&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mais évidemment, pour que la blague soit complète, ce qu’il faut savoir c’est qu’une solution à base de &lt;strong&gt;command_output.skipped is defined&lt;/strong&gt;, ne peut pas marcher&amp;hellip;&lt;/p&gt;
&lt;p&gt;En fait, il n’est pas possible avec Ansible d’utiliser &lt;strong&gt;is defined&lt;/strong&gt; pour vérifier l’existence (ou non) d’un sous élément.&lt;/p&gt;
&lt;h2 id="solutions"&gt;Solutions
&lt;/h2&gt;&lt;p&gt;La solution la plus simple, que je croyais dur comme fer avoir implémenté (mais mes tests additionnels me prouvent que non) c’est simplement d’ajouter un &lt;strong&gt;when: not_in_test_env&lt;/strong&gt; à la 2ème tâche&amp;hellip;&lt;/p&gt;
&lt;p&gt;Dans la même veine, et qui permet en plus d’éviter d’initialiser pour rien &lt;strong&gt;&lt;em&gt;command_output.skipped&lt;/em&gt;&lt;/strong&gt;, il aurait pu être malin de simplement utiliser un &lt;strong&gt;block:&lt;/strong&gt; avec le when, englobant les deux tâches :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Get some content from a command&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;command outputting something&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;changed_when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;command_output&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Write command_output to file&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output_file_path }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output.stdout }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;not_in_test_env&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et la vraie solution si jamais vous voulez absolument vérifier si la tâche précédente a été skipped ou pas, est d’utiliser la syntaxe suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Write command_output to file&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output_file_path }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;{{ command_output.stdout }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;skipped&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;not in command_output&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cette syntaxe n’est pas hyper évidente de prime abord, mais c’est la seule qui fonctionne dans Ansible pour faire ça&amp;hellip;&lt;/p&gt;
&lt;h2 id="bonus"&gt;Bonus
&lt;/h2&gt;&lt;p&gt;Un lecteur (&amp;lsquo;Jof) m&amp;rsquo;a fait remarquer qu&amp;rsquo;il y a une autre solution qui marche dans tous les cas :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;when command_output|skipped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Merci à lui !&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Le vrai problème ici est quand même que j’avais vraiment besoin de vacances pour ne pas avoir été capable de trouver l’erreur aussi basique ;-).&lt;/p&gt;
&lt;p&gt;La seconde est que j’utilise une version antédiluvienne d’Ansible et que ça irait beaucoup mieux avec des versions plus récentes (pour le &lt;strong&gt;| default&lt;/strong&gt; notamment).&lt;/p&gt;
&lt;p&gt;La dernière chose à retenir est que quand on veut vérifier la présence ou non d’un sous élément dans une variable, le mieux reste d’utiliser &lt;strong&gt;in&lt;/strong&gt; ou &lt;strong&gt;not in&lt;/strong&gt; plutôt que &lt;strong&gt;is defined&lt;/strong&gt; qui ne fonctionne pas dans tous les cas.&lt;/p&gt;
&lt;h2 id="sources-additionnelles"&gt;Sources additionnelles
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/56066503/i-am-having-ansible-issues-with-register-command-when-using-when-in-tasks" target="_blank" rel="noopener"
&gt;stackoverflow.com/questions/56066503/i-am-having-ansible-issues-with-register-command-when-using-when-in-tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="github.com/ansible/ansible/issues/17500#issuecomment-246370020" &gt;github.com/ansible/ansible/issues/17500#issuecomment-246370020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="github.com/ansible/ansible/issues/4297#issuecomment-356427588" &gt;github.com/ansible/ansible/issues/4297#issuecomment-356427588&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>