{"id":17622,"date":"2022-06-22T14:36:11","date_gmt":"2022-06-22T12:36:11","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/?p=17622"},"modified":"2024-09-11T15:02:37","modified_gmt":"2024-09-11T13:02:37","slug":"ansible-imagination-is-the-limit","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/","title":{"rendered":"Ansible: Imagination is the Limit"},"content":{"rendered":"\n<p>As you might know, I have discovered Ansible <a href=\"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/\" target=\"_blank\" rel=\"noreferrer noopener\">1 year ago<\/a>. Since then, I am not using for its main purpose as wikipedia says:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Ansible is an open-source software provisioning, configuration management, and application-deployment tool enabling infrastructure as code.<\/p>\n<\/blockquote>\n\n\n\n<p>Instead, I develop few playbooks for others objectives.<\/p>\n\n\n\n<p>I will present you two of them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Search in logs<\/li>\n\n\n\n<li>Count clients connections<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Search in Logs<\/h2>\n\n\n\n<p>In one customer, they have an application deployed over 12 nodes cluster. For day to day operation, I receive user tickets with an error message, but without knowing on which server they were connected while facing the problem (There is a load balancer in front of clients). Unfortunately, Centralized Log Management is not ready, thus I had to think to another solution. Here is where Ansible could help.<\/p>\n\n\n\n<p>The advantage of Ansible over bash scripting, in this situation, is that all users credentials are already managed by the Ansible environment that was developed:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: Include common tasks\n    tags: &#x5B; always ]\n    include_role:\n      name: common\n      apply:\n        tags: always\n<\/pre><\/div>\n\n\n<p>These transparently manages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Service user name and associated credentials.<\/li>\n\n\n\n<li>Access to server with admin account (login and password).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">What are we Looking for?<\/h3>\n\n\n\n<p>Let&#8217;s focus on main feature: The search. To do that, first thing is to know what we are looking for:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: Prompt pattern\n    block:\n    - name: Prompt pattern\n      register: pattern_input\n      ansible.builtin.pause:\n        prompt: |\n          Enter searched pattern\n    - name: Set pattern fact\n      set_fact:\n        pattern: &quot;{{ pattern_input.user_input }}&quot;\n\n    when: pattern is not defined\n    delegate_to: localhost\n    run_once: True\n<\/pre><\/div>\n\n\n<p>What I did is to interactively request the pattern we are looking for if it was not already provided as playbook parameter (ie. not defined). If the pattern is already set, the block of code will not be executed.<\/p>\n\n\n\n<p>To avoid requesting same pattern as many times as there are servers in the cluster, this will be run only once (line 14) and it will not be related to a specific host of the inventory, so I kept it local (line 13).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Searching<\/h3>\n\n\n\n<p>Now, I am ready to do the actual search:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: Search {{ pattern }} in log\n    find:\n      paths: \/opt\/,\/u02\/app\/weblogic\/config\/domains\/{{ weblogic_domain }}\/servers\/\n      file_type: file\n      exclude: &#039;*.gz&#039;\n      contains: &#039;.*{{ pattern }}.*&#039;\n      recurse: true\n      age: -5d\n    register: findings\n    become: true\n    become_user: weblogic\n<\/pre><\/div>\n\n\n<p>I am using the find module with a regex. This regex requires &#8220;.*&#8221;, meaning any characters any amount of time, to be added at beginning and end. If not, it will search only files contain exactly the pattern. Not more, not less. Result will be stored (ie. registered) in <em>findings<\/em> variable. Note that I searched for files not older than 5 days (line 8) and exclude archived logs (line 5) for faster results.<\/p>\n\n\n\n<p>Then, my idea was to provide a list of files containing the pattern:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: output the path of the files\n    set_fact:\n     path: &quot;{{ findings.files | map(attribute=&#039;path&#039;) | join(&#039;\\n - &#039;)  }}&quot;\n<\/pre><\/div>\n\n\n<p>The path variable will be temporary and written to a file that is local to the Ansible controller server.<\/p>\n\n\n\n<p>Finally, writing the file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: Remove {{ ansible_limit }} file\n    ansible.builtin.file:\n      path: &quot;{{ ansible_limit }}.out&quot;\n      state: absent\n    delegate_to: localhost\n    run_once: True\n\n  - name: Copy list of files in {{ ansible_limit }}\n    ansible.builtin.lineinfile:\n      path: &quot;{{ ansible_limit }}.out&quot;\n      line: &quot;{{inventory_hostname}}:\\n - {{ path }}&quot;\n      create: yes\n      mode: 0666\n    delegate_to: localhost\n    throttle: 1\n<\/pre><\/div>\n\n\n<p>In first task, I am removing the file and, secondly, I am writing result in file. At first, the results were unordered since they depended on the completion time of tasks on each individual node. To avoid that, I added a &#8220;<em>throttle: 1<\/em>&#8221; option which will ensure, it is run one task at a time. &#8220;<em>order: sorted<\/em>&#8221; is also added at the beginning of the playbook to ensure that.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Count Clients Connections<\/h2>\n\n\n\n<p>This second playbook is to get the amount of client connected to each servers to confirm they are correctly load balanced across all nodes.<\/p>\n\n\n\n<p>First task is to get the process ID with a &#8220;<em>shell<\/em>&#8221; task:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: Getting process ID\n    shell: ps aux | grep &#039;{{ pattern }}&#039; | grep -v grep | tr -s &#039; &#039;| cut -d&#039; &#039; -f2\n    register: ps_output\n<\/pre><\/div>\n\n\n<p>&#8220;pattern&#8221; is a string which will help to find the PID.<\/p>\n\n\n\n<p>Then, I used netstat to find all established connection to that process (pid_string= &#8220;{{ ps_output.stdout }}\/java&#8221;):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: netstat\n    shell: netstat -anpt 2&gt;\/dev\/null | grep &#039;{{ pid_string }}&#039; | grep ESTABLI | grep -v 1521\n    register: conn_list\n    become: true\n    become_user: weblogic\n<\/pre><\/div>\n\n\n<p>I filtered out connection to Oracle Database (port 1521) as this process has connections to it as well.<\/p>\n\n\n\n<p>The amount of lines of &#8220;conn_list&#8221; variable will be the amount of connections:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n  - name: Set conn_count\n    set_fact:\n      conn_count: &quot;{{ conn_list.stdout_lines | length }}&quot;\n<\/pre><\/div>\n\n\n<p>The same way a previous playbook, I am creating a file local to the Ansible controller where I write a line for each nodes with amount of connections:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n      - name: Copy result in {{ result_file }}\n        ansible.builtin.lineinfile:\n          path: &quot;{{ result_file }}&quot;\n          line: &quot;{{inventory_hostname}};{{ pattern }};{{ pid_string }};{{ conn_count }}\n          create: yes\n          mode: 0666\n        throttle: 1\n<\/pre><\/div>\n\n\n<p>I have included the pattern used and the process ID of the host on each host. Please note that all tasks associated with the local file are grouped together and delegated to localhost.<\/p>\n\n\n\n<p>Finally, I thought I could add a total of connections for all nodes. This was the difficult part. Initially, I used a sed of the file to do it, but then, I thought &#8220;There is nothing that Ansible can&#8217;t do!&#8221;. So I persevered and found that solution:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n      - name: Calculate totals in {{ result_file }}\n        set_fact:\n          TotalConnLines: &quot;{{ansible_play_hosts_all | map(&#039;extract&#039;, hostvars, &#039;conn_count&#039;) | map(&#039;int&#039;) | sum }}&quot;\n        run_once: True\n<\/pre><\/div>\n\n\n<p>Let&#8217;s detail that jinja template:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>ansible_play_hosts_all<\/li>\n\n\n\n<li>map(&#8216;extract&#8217;, hostvars, &#8216;conn_count&#8217;)<\/li>\n\n\n\n<li>map(&#8216;int&#8217;)<\/li>\n\n\n\n<li>sum<\/li>\n<\/ol>\n\n\n\n<p>Part 1 is to get a list of all hosts where Ansible is ran. Then, part 2, I extract from &#8220;<em>hostvars<\/em>&#8220;, the variable &#8220;<em>conn_count<\/em>&#8221; for each hosts. This is now a list of counts. I could simply pipe it to &#8220;sum&#8221;, but this failed because elements of the list are strings. So, I had to apply &#8220;int&#8221; on them with help of map (part 3). Finally, summing up counts at part 4.<\/p>\n\n\n\n<p>Then, I write the total line to the resulting file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n      - name: Add total line in {{ result_file }}\n        ansible.builtin.lineinfile:\n          path: &quot;{{ result_file }}&quot;\n          line: &quot;;{{ TotalConnLines }}&quot;\n          insertbefore: EOF\n        run_once: True\n<\/pre><\/div>\n\n\n<p>This is quite a complex jinja template to do it, but we see nothing is impossible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">And Yours?<\/h2>\n\n\n\n<p>And you, for what are you using <strong>Ansible<\/strong> which was not his main purpose?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As you might know, I have discovered Ansible 1 year ago. Since then, I am not using for its main purpose as wikipedia says: Ansible is an open-source software provisioning, configuration management, and application-deployment tool enabling infrastructure as code. Instead, I develop few playbooks for others objectives. I will present you two of them: Search [&hellip;]<\/p>\n","protected":false},"author":109,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1321],"tags":[150],"type_dbi":[],"class_list":["post-17622","post","type-post","status-publish","format-standard","hentry","category-ansible","tag-ansible"],"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: Imagination is the Limit - dbi Blog<\/title>\n<meta name=\"description\" content=\"Impossible is not Ansible. What Ansible can help you with, today? Is there anything that Ansible can&#039;t do?\" \/>\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-imagination-is-the-limit\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ansible: Imagination is the Limit\" \/>\n<meta property=\"og:description\" content=\"Impossible is not Ansible. What Ansible can help you with, today? Is there anything that Ansible can&#039;t do?\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-06-22T12:36:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-09-11T13:02:37+00:00\" \/>\n<meta name=\"author\" content=\"DevOps\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"DevOps\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 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-imagination-is-the-limit\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/\"},\"author\":{\"name\":\"DevOps\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/4cd1b5f8a3de93f05a16ab8d7d2b7735\"},\"headline\":\"Ansible: Imagination is the Limit\",\"datePublished\":\"2022-06-22T12:36:11+00:00\",\"dateModified\":\"2024-09-11T13:02:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/\"},\"wordCount\":803,\"commentCount\":0,\"keywords\":[\"Ansible\"],\"articleSection\":[\"Ansible\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/\",\"name\":\"Ansible: Imagination is the Limit - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2022-06-22T12:36:11+00:00\",\"dateModified\":\"2024-09-11T13:02:37+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/4cd1b5f8a3de93f05a16ab8d7d2b7735\"},\"description\":\"Impossible is not Ansible. What Ansible can help you with, today? Is there anything that Ansible can't do?\",\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ansible: Imagination is the Limit\"}]},{\"@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\/4cd1b5f8a3de93f05a16ab8d7d2b7735\",\"name\":\"DevOps\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/cdd2dd7441774355062c0f0f68612296b059cd1e2ff6c7af0b15dba0ed64a85f?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/cdd2dd7441774355062c0f0f68612296b059cd1e2ff6c7af0b15dba0ed64a85f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/cdd2dd7441774355062c0f0f68612296b059cd1e2ff6c7af0b15dba0ed64a85f?s=96&d=mm&r=g\",\"caption\":\"DevOps\"},\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/devops\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Ansible: Imagination is the Limit - dbi Blog","description":"Impossible is not Ansible. What Ansible can help you with, today? Is there anything that Ansible can't do?","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-imagination-is-the-limit\/","og_locale":"en_US","og_type":"article","og_title":"Ansible: Imagination is the Limit","og_description":"Impossible is not Ansible. What Ansible can help you with, today? Is there anything that Ansible can't do?","og_url":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/","og_site_name":"dbi Blog","article_published_time":"2022-06-22T12:36:11+00:00","article_modified_time":"2024-09-11T13:02:37+00:00","author":"DevOps","twitter_card":"summary_large_image","twitter_misc":{"Written by":"DevOps","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/"},"author":{"name":"DevOps","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/4cd1b5f8a3de93f05a16ab8d7d2b7735"},"headline":"Ansible: Imagination is the Limit","datePublished":"2022-06-22T12:36:11+00:00","dateModified":"2024-09-11T13:02:37+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/"},"wordCount":803,"commentCount":0,"keywords":["Ansible"],"articleSection":["Ansible"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/","url":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/","name":"Ansible: Imagination is the Limit - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2022-06-22T12:36:11+00:00","dateModified":"2024-09-11T13:02:37+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/4cd1b5f8a3de93f05a16ab8d7d2b7735"},"description":"Impossible is not Ansible. What Ansible can help you with, today? Is there anything that Ansible can't do?","breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/ansible-imagination-is-the-limit\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Ansible: Imagination is the Limit"}]},{"@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\/4cd1b5f8a3de93f05a16ab8d7d2b7735","name":"DevOps","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/cdd2dd7441774355062c0f0f68612296b059cd1e2ff6c7af0b15dba0ed64a85f?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/cdd2dd7441774355062c0f0f68612296b059cd1e2ff6c7af0b15dba0ed64a85f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/cdd2dd7441774355062c0f0f68612296b059cd1e2ff6c7af0b15dba0ed64a85f?s=96&d=mm&r=g","caption":"DevOps"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/devops\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/17622","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\/109"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=17622"}],"version-history":[{"count":15,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/17622\/revisions"}],"predecessor-version":[{"id":24011,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/17622\/revisions\/24011"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=17622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=17622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=17622"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=17622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}