{"id":14902,"date":"2020-10-19T20:25:11","date_gmt":"2020-10-19T18:25:11","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/"},"modified":"2020-10-19T20:25:11","modified_gmt":"2020-10-19T18:25:11","slug":"ansible-loop-over-registered-results","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/","title":{"rendered":"Ansible loop over registered results"},"content":{"rendered":"<p>We were recently confronted with one of our playbook constraint while trying to identify which database software could be uninstalled from our servers.<br \/>\nUntil now, we ran the playbook to de-install a specific version which were \u201cdiscovered manually\u201d. However, we even got lazy to run this \u201cdiscovery phase\u201d manually.<\/p>\n<p>This short post explains how to design a play around the results of a specific task like generating a list of obsolete Oracle RDBMS software.<\/p>\n<p><!--more--><\/p>\n<p>Indeed, we tried to loop over registered results from a simple SHELL command like fuser; The goal was to build a list with the result of fuser and iterate over the whole list.<\/p>\n<p>Here the task snippet of what we tried achieve:<\/p>\n<pre class=\"brush: yaml; gutter: true; first-line: 1; highlight: [10,21]\">    - name: Find all installed Oracle RDBMS binaries\n      find:\n        paths: \/u01\/app\/oracle\/product\/\n        recurse: no\n        file_type: directory\n      register: reg_oracle_home_installed\n\n    - name: Check if ORACLE_HOME is used\n      shell: \"\/sbin\/fuser {{ ora_home.path }}\/bin\/oracle\"\n      register: reg_oracle_home_status\n      loop: \"{{ reg_oracle_home_installed.files }}\"\n      loop_control:\n        loop_var: ora_home\n        label: \"{{ ora_home.path }}\"\n      changed_when: false\n      failed_when: reg_oracle_home_status.rc is not regex('^(1|0)$')\n\n    - name: Dynamic list of candidate ORACLE_HOME to deinstall\n      debug:\n        msg: \" {{ entry.ora_home.path }}\"\n      loop: \"{{ reg_oracle_home_status.results }}\"\n      loop_control:\n        loop_var: entry\n        label: \"{{ entry.ora_home.path }}\"\n<\/pre>\n<p>According to the Ansible documentation, the <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/reference_appendices\/common_return_values.html\">return values<\/a> for registered data structure in loops should return a list per item.However, processing the \u201cresults\u201d list is not working as expected which explains why you are still reading my post &#x1f609;.<\/p>\n<p>Below, the returned data structure debug output:<\/p>\n<pre class=\"brush: yaml; gutter: false; first-line: 1\">ok: [vmoel7] =&gt; (item={'stderr_lines': [], u'cmd': u'fuser \/u01\/app\/oracle\/product\/18_7_0_0_RU190716_v0\/bin\/oracle', u'stdout': u'', u'msg': u'non-zero return code', u'delta': u'0:00:00.027083', 'stdout_lines': [], 'failed_when_result': False, 'ansible_loop_var': u'item', u'end': u'2020-10-15 22:13:42.461691', 'item': {u'islnk': False, u'uid': 54321, u'rgrp': True, u'xoth': True, u'rusr': True, u'woth': False, u'nlink': 72, u'issock': False, u'mtime': 1563907992.349, u'gr_name': u'oinstall', u'path': u'\/u01\/app\/oracle\/product\/18_7_0_0_RU190716_v0', u'xusr': True, u'atime': 1593096574.662, u'inode': 132, u'isgid': False, u'size': 4096, u'isdir': True, u'wgrp': False, u'ctime': 1563907992.349, u'isblk': False, u'xgrp': True, u'isuid': False, u'dev': 2065, u'roth': True, u'isreg': False, u'isfifo': False, u'mode': u'0755', u'pw_name': u'oracle', u'gid': 54321, u'ischr': False, u'wusr': True}, u'changed': True, u'failed': False, u'stderr': u'', u'rc': 1, u'invocation': {u'module_args': {u'warn': True, u'executable': None, u'_uses_shell': True, u'strip_empty_ends': True, u'_raw_params': u'fuser \/u01\/app\/oracle\/product\/18_7_0_0_RU190716_v0\/bin\/oracle', u'removes': None, u'argv': None, u'creates': None, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, u'start': u'2020-10-15 22:13:42.434608'}) =&gt; {\n    \"msg\": \"unsed OracleHome={'stderr_lines': [], 'ansible_loop_var': u'item', u'end': u'2020-10-15 22:13:42.461691', u'stdout': u'', 'item': {u'uid': 54321, u'woth': False, u'mtime': 1563907992.349, u'inode': 132, u'isgid': False, u'size': 4096, u'roth': True, u'isuid': False, u'isreg': False, u'pw_name': u'oracle', u'gid': 54321, u'ischr': False, u'wusr': True, u'xoth': True, u'rusr': True, u'nlink': 72, u'issock': False, u'rgrp': True, u'gr_name': u'oinstall', u'path': u'\/u01\/app\/oracle\/product\/18_7_0_0_RU190716_v0', u'xusr': True, u'atime': 1593096574.662, u'isdir': True, u'ctime': 1563907992.349, u'wgrp': False, u'xgrp': True, u'dev': 2065, u'isblk': False, u'isfifo': False, u'mode': u'0755', u'islnk': False}, u'changed': True, u'rc': 1, u'failed': False, u'cmd': u'fuser \/u01\/app\/oracle\/product\/18_7_0_0_RU190716_v0\/bin\/oracle', u'stderr': u'', u'delta': u'0:00:00.027083', u'invocation': {u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': True, u'strip_empty_ends': True, u'_raw_params': u'fuser \/u01\/app\/oracle\/product\/18_7_0_0_RU190716_v0\/bin\/oracle', u'removes': None, u'argv': None, u'warn': True, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, 'stdout_lines': [], 'failed_when_result': False, u'start': u'2020-10-15 22:13:42.434608', u'msg': u'non-zero return code'}\"\n}\n<\/pre>\n<p>Indeed, it looks like a YAML list but it isn&#8217;t \u2026 Lets quickly verify the variable type using \u201ctype_debug\u201d<br \/>\nCode Snippet:<\/p>\n<pre class=\"brush: xml; gutter: true; first-line: 1; highlight: [2]\">    - debug:\n        msg: \"reg_oracle_home_status.results: {{ reg_oracle_home_status.results | type_debug }}\"\n<\/pre>\n<p>Output:<\/p>\n<pre class=\"brush: yaml; gutter: gutter; first-line: 1\">ok: [vmoel7] =&gt; {\n    \"msg\": \"reg_oracle_home_status.results: list\"\n}\n<\/pre>\n<p>Hum, it\u2019s a list! Hence, It\u2019s must be a bug.<\/p>\n<p>So, let\u2019s try to reformat it using the from_yaml Python method. Follows, the output after python from_yaml conversion:<\/p>\n<pre class=\"brush: yaml; gutter: false; first-line: 1; highlight: [4,6,15,16]\">ok: [vmoel7] =&gt; {\n    \"msg\": [\n        {\n            \"cmd\": \"fuser \/u01\/app\/oracle\/product\/18_7_0_0_RU190716_v0\/bin\/oracle\",\n            \u2026\n            \"msg\": \"non-zero return code\",\n            \"rc\": 1,\n            \"start\": \"2020-10-15 22:22:40.857383\",\n            \"stderr\": \"\",\n            \"stderr_lines\": [],\n            \"stdout\": \"\",\n            \"stdout_lines\": []\n       },\n        {\n            \"cmd\": \"fuser \/u01\/app\/oracle\/product\/19_8_0_0_RU200714_v0\/bin\/oracle\",\n            \"rc\": 0,\n            \u2026\n        }\n      \u2026\n<\/pre>\n<p>Better isn\u2019t it?<\/p>\n<p><!--more--><\/p>\n<p>Now, we are able to process the list in a loop as expected:<\/p>\n<pre class=\"brush: xml; gutter: true; first-line: 1;highlight: [4]\">    - name: Dynamic list of candidate ORACLE_HOME to deinstall\n      debug:\n        msg: \"deinstall ORACLE_HOME={{ entry.ora_home.path}}\"\n      loop: \"{{ reg_oracle_home_status.results | from_yaml | list }}\"\n      loop_control:\n        loop_var: entry\n        label: \"{{ entry.ora_home.path }}\"\n      # ReturnCode=0 - if used\n      when: entry.rc != 0\n\n<\/pre>\n<p>Sounds obvious? But took a couple of hours to debug.<\/p>\n<p>it\u2019s probably the case for plenty of Ansible nerds all over the world if you look at the number of forum threads.<\/p>\n<p>The proof? You are still reading this post &#x1f60a;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We were recently confronted with one of our playbook constraint while trying to identify which database software could be uninstalled from our servers. Until now, we ran the playbook to de-install a specific version which were \u201cdiscovered manually\u201d. However, we even got lazy to run this \u201cdiscovery phase\u201d manually. This short post explains how to [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1320],"tags":[150,151],"type_dbi":[],"class_list":["post-14902","post","type-post","status-publish","format-standard","hentry","category-devops","tag-ansible","tag-devops"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Ansible loop over registered results - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ansible loop over registered results\" \/>\n<meta property=\"og:description\" content=\"We were recently confronted with one of our playbook constraint while trying to identify which database software could be uninstalled from our servers. Until now, we ran the playbook to de-install a specific version which were \u201cdiscovered manually\u201d. However, we even got lazy to run this \u201cdiscovery phase\u201d manually. This short post explains how to [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-10-19T18:25:11+00:00\" \/>\n<meta name=\"author\" content=\"J\u00e9r\u00f4me Witt\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"J\u00e9r\u00f4me Witt\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/\"},\"author\":{\"name\":\"J\u00e9r\u00f4me Witt\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/a2d3ecddaf732850101a39b9d62c31b7\"},\"headline\":\"Ansible loop over registered results\",\"datePublished\":\"2020-10-19T18:25:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/\"},\"wordCount\":286,\"commentCount\":0,\"keywords\":[\"Ansible\",\"DevOps\"],\"articleSection\":[\"DevOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/\",\"name\":\"Ansible loop over registered results - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2020-10-19T18:25:11+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/a2d3ecddaf732850101a39b9d62c31b7\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ansible loop over registered results\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/a2d3ecddaf732850101a39b9d62c31b7\",\"name\":\"J\u00e9r\u00f4me Witt\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/17095c081578ca53f52ec4030ba2bde72cc18badb325cd2ba1ee2831106507ad?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/17095c081578ca53f52ec4030ba2bde72cc18badb325cd2ba1ee2831106507ad?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/17095c081578ca53f52ec4030ba2bde72cc18badb325cd2ba1ee2831106507ad?s=96&d=mm&r=g\",\"caption\":\"J\u00e9r\u00f4me Witt\"},\"description\":\"J\u00e9rome Witt started his Consultant career a few years ago. He is specialized in database and infrastructure management, engineering, and optimization. He is very skilled in Oracle high availability, backup &amp; recovery, and tuning technologies. His expertise also includes the open source field (Linux\/Unix), advanced Perl, Shell, Windows PowerShell programming, and Automation tools (UC4). J\u00e9r\u00f4me Witt is Oracle Certified Professional 11g (OCP 11g), Oracle Certified Expert Tuning (OCE), and ITIL V3 Foundation certified. Prior to joining dbi services, J\u00e9r\u00f4me Witt was Consultant at Trivadis in Basel. He also worked as a Junior Automation specialist at Selmoni AG in Basel. J\u00e9r\u00f4me Witt holds a BTS degree in Information Systems and Industrial Networks from France. His branch-related experience covers Pharma, Health Care, Banking &amp; Financial Services, Energy, Automotive etc.\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/jerome-witt\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Ansible loop over registered results - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/","og_locale":"en_US","og_type":"article","og_title":"Ansible loop over registered results","og_description":"We were recently confronted with one of our playbook constraint while trying to identify which database software could be uninstalled from our servers. Until now, we ran the playbook to de-install a specific version which were \u201cdiscovered manually\u201d. However, we even got lazy to run this \u201cdiscovery phase\u201d manually. This short post explains how to [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/","og_site_name":"dbi Blog","article_published_time":"2020-10-19T18:25:11+00:00","author":"J\u00e9r\u00f4me Witt","twitter_card":"summary_large_image","twitter_misc":{"Written by":"J\u00e9r\u00f4me Witt","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/"},"author":{"name":"J\u00e9r\u00f4me Witt","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/a2d3ecddaf732850101a39b9d62c31b7"},"headline":"Ansible loop over registered results","datePublished":"2020-10-19T18:25:11+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/"},"wordCount":286,"commentCount":0,"keywords":["Ansible","DevOps"],"articleSection":["DevOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/","url":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/","name":"Ansible loop over registered results - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2020-10-19T18:25:11+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/a2d3ecddaf732850101a39b9d62c31b7"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/ansible-loop-over-registered-results\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Ansible loop over registered results"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/a2d3ecddaf732850101a39b9d62c31b7","name":"J\u00e9r\u00f4me Witt","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/17095c081578ca53f52ec4030ba2bde72cc18badb325cd2ba1ee2831106507ad?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/17095c081578ca53f52ec4030ba2bde72cc18badb325cd2ba1ee2831106507ad?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/17095c081578ca53f52ec4030ba2bde72cc18badb325cd2ba1ee2831106507ad?s=96&d=mm&r=g","caption":"J\u00e9r\u00f4me Witt"},"description":"J\u00e9rome Witt started his Consultant career a few years ago. He is specialized in database and infrastructure management, engineering, and optimization. He is very skilled in Oracle high availability, backup &amp; recovery, and tuning technologies. His expertise also includes the open source field (Linux\/Unix), advanced Perl, Shell, Windows PowerShell programming, and Automation tools (UC4). J\u00e9r\u00f4me Witt is Oracle Certified Professional 11g (OCP 11g), Oracle Certified Expert Tuning (OCE), and ITIL V3 Foundation certified. Prior to joining dbi services, J\u00e9r\u00f4me Witt was Consultant at Trivadis in Basel. He also worked as a Junior Automation specialist at Selmoni AG in Basel. J\u00e9r\u00f4me Witt holds a BTS degree in Information Systems and Industrial Networks from France. His branch-related experience covers Pharma, Health Care, Banking &amp; Financial Services, Energy, Automotive etc.","url":"https:\/\/www.dbi-services.com\/blog\/author\/jerome-witt\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/14902","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=14902"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/14902\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=14902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=14902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=14902"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=14902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}