{"id":16314,"date":"2021-05-07T11:24:40","date_gmt":"2021-05-07T09:24:40","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/"},"modified":"2024-09-11T15:06:50","modified_gmt":"2024-09-11T13:06:50","slug":"starting-with-simple-ansible-playbooks","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/","title":{"rendered":"Starting with Simple Ansible Playbooks"},"content":{"rendered":"<p>As you might have seen in my previous blog posts, I am a real fan of everything that can help automate because of two main reasons:<\/p>\n<ol>\n<li>It saves some time for others non-repetitive tasks<\/li>\n<li>It avoids any error that could occur by manual steps<\/li>\n<\/ol>\n<p>Ansible triggered my attention.<!--more--> Despite a few LinkedIn training I followed, I did not feel comfortable to develop my own playbooks.<br \/>\nThat changed few weeks back, when I attended the <a href=\"https:\/\/www.dbi-services.com\/trainings\/ansible-basics\/\">Ansible workshop<\/a> on one day with <a href=\"https:\/\/www.dbi-services.com\/blog\/author\/jerome-witt\/\">J\u00e9rome Witt<\/a>.<br \/>\nThis one gave me the last push to start writing useful playbooks for my day to day activities.<\/p>\n<h3>Context<\/h3>\n<p>As Service Delivery Manager (SDM), we are preparing VM to be installed as Kubernetes nodes or Documentum servers (WebServer, FullText and Content Server). Previously, we were running a prerequisite script manually which generated a report of what is conform or not on each server one by one which implies:<\/p>\n<ol>\n<li>Copy of script<\/li>\n<li>Execute it<\/li>\n<li>Collect result<\/li>\n<\/ol>\n<p>We are not allowed to fix most of the non-conformity ourselves, but we have to request the responsible team to have it done for us (Local users, Linux settings). Then, we can rerun the script to check if it was correctly implemented.<br \/>\nWe also have a script to test that servers are whitelisted to the SMTP host by sending a test email. We will start with this one in the next chapter.<br \/>\nAlso because of the growing Kubernetes environment (there is batch of 10 VMs to prepare), we must find a way to automated these two tasks (prerequisite and SMTP).<\/p>\n<h3>Directory structure<\/h3>\n<p>Here is the view of the ansible tree:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\u251c\u2500\u2500 ansible.cfg\n\u251c\u2500\u2500 appdir.yml\n\u251c\u2500\u2500 inventories\n\u2502 \u251c\u2500\u2500 DEV.yml\n\u2502 \u2514\u2500\u2500 TEST.yml\n\u251c\u2500\u2500 out\n\u2502 \u251c\u2500\u2500 DEV\n\u2502 \u2502 \u251c\u2500\u2500 Dserver1-K8s-issues.csv\n\u2502 \u2502 ...\n\u2502 \u2502 \u2514\u2500\u2500 Dserver10-K8s-issues.csv\n\u2502 \u2514\u2500\u2500 TEST\n\u2502 \u251c\u2500\u2500 Tserver1-K8s-issues.csv\n\u2502 ...\n\u2502 \u2514\u2500\u2500 Tserver10-K8s-issues.csv\n\u251c\u2500\u2500 prereqsK8s.yml\n\u251c\u2500\u2500 scripts\n\u2502 \u251c\u2500\u2500 check_prerequisites_rhel7.sh\n\u2502 \u2514\u2500\u2500 testmail.sh\n\u2514\u2500\u2500 testmail.yml\n<\/pre>\n<p>To avoid long page, I summarized repetitions by &#8220;&#8230;&#8221;.<\/p>\n<h3>Test Mail<\/h3>\n<p>To make it consistent with past implementations, I decided to keep the existing script for email testing. I will proceed as listed above: copy of script, execute it. If testmail.sh script does not return &#8216;Message accepted for delivery&#8217;, playbook will raise an error for the concerned host. If it is just &#8220;update&#8221;, it will be considered successful. And here is the playbook:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">---\n- name: SMTP Testing\n  hosts: all\n  gather_facts: no\n  tasks:\n    - name: Copy testmail.sh\n      ansible.builtin.copy:\n        src: scripts\/testmail.sh\n        dest: testmail.sh\n        mode: '0700'\n    - name: Run testmail.sh\n      shell: .\/testmail.sh | grep 'Message accepted for delivery'\n      register: output\n<\/pre>\n<p>Example of outputs for command &#8216;ansible-playbook -i inventories\/DEV.yml testmail.yml&#8217;:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">PLAY [SMTP Testing] **********************************************************************************************************************************************************************************\n\nTASK [Copy testmail.sh] ******************************************************************************************************************************************************************************\nchanged: [Dserver1]\n...\nchanged: [Dserver10]\n\nTASK [Run testmail.sh] *******************************************************************************************************************************************************************************\nchanged: [Dserver1]\n...\nchanged: [Dserver10]\n\nPLAY RECAP *******************************************************************************************************************************************************************************************\nDserver1  : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0\n...\nDserver10 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0<\/pre>\n<p>As per <a href=\"https:\/\/en.wikipedia.org\/wiki\/Idempotence\">idempotence<\/a>, if I run script second time, task [Copy testmail.sh] will be ok, but not changed.<br \/>\n[Run testmail.sh] will always run and will always have changed state in PLAY RECAP.<\/p>\n<h3>Prerequisites<\/h3>\n<p>For same reason as SMTP, we will keep the current prerequisite check bash script. Also because, it will be faster to have valid playbook running. The additional step, compared to email testing, will be to download script result from distant servers to local for easier analyzes. check_prerequisites_rhel7.sh need to be run as root, that why I enabled &#8220;become&#8221; option. Here is the playbook:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1; highlight: [14]\">---\n- name: K8s workers prereqs checks\n  hosts: all\n  gather_facts: no\n  tasks:\n    - name: Copy check_prerequisites_rhel7.sh\n      ansible.builtin.copy:\n        src: scripts\/check_prerequisites_rhel7.sh\n        dest: check_prerequisites_rhel7.sh\n        mode: '0707'\n    - name: Run check_prerequisites_rhel7.sh\n      shell: \".\/check_prerequisites_rhel7.sh K8s\"\n      register: output\n      become: yes\n      environment:\n        PATH: '\/usr\/local\/sbin:\/usr\/local\/bin:\/sbin:\/bin:\/usr\/sbin:\/usr\/bin:\/root\/bin'\n    - name: Get result files\n      fetch:\n        src: \"{{ inventory_hostname | lower }}-K8s-issues.csv\"\n        dest: \"out\/{{ inventory_file | basename | splitext | first }}\/\"\n        flat: yes<\/pre>\n<p>Similarly as testmail, I simply need to call the playbook with the command &#8220;ansible-playbook -i inventories\/DEV.yml prereqsK8s.yml&#8221;:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">PLAY [K8s workers prereqs checks] ********************************************************************************************************************************************************************\n\nTASK [Copy check_prerequisites_rhel7.sh] *************************************************************************************************************************************************************\nok: [Dserver1]\n...\nok: [Dserver10]\n\nTASK [Run check_prerequisites_rhel7.sh] **************************************************************************************************************************************************************\n...\nchanged: [Dserver10]\n...\nchanged: [Dserver1]\n...\n\nTASK [Get result files] ******************************************************************************************************************************************************************************\nok: [Dserver10]\n...\nok: [Dserver1]\n...\n\nPLAY RECAP *******************************************************************************************************************************************************************************************\nDserver1             : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0\nDserver10            : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0<\/pre>\n<p>Then, I have to look into the local copy of the results in out\/dev\/ directory.<br \/>\nFrom the Ansible log, I can already deduce interesting facts:<\/p>\n<ol>\n<li>First task (COPY) will be executed only at first run of the playbook, unless script is updated<\/li>\n<li>Second task (RUN) will be executed every time I run the playbook, thus changed will be 1 or more<\/li>\n<li>Third task (GET) will be executed only if result of bash script is different from previous playbook run<\/li>\n<\/ol>\n<h3>Simple Change<\/h3>\n<p>A simple prerequisite is to have \/app and \/appdocker owned by docker with proper permissions set. The playbook for this is:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1; highlight: [10,11,12,13,15,16]\">---\n- name: Create \/app and \/app\/docker directories\n  hosts: all\n  gather_facts: no\n  become: yes\n  tasks:\n    - name: Create directory {{ item }}\n      ansible.builtin.file:\n        path: \"{{ item }}\"\n        state: directory\n        owner: docker\n        group: docker\n        mode: '750'\n      loop:\n        - \"\/app\"\n        - \"\/app\/docker\"\n<\/pre>\n<p>As highlighted, I only have to say that directory must exist, the owner and group as well as permissions. To avoid duplication of the task for \/app\/docker folder, I am using the loop statement. To run the playbook, I execute ansible-playbook -i inventories\/TEST.yml appdir.yml:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">PLAY [Create \/app and \/app\/docker directories] ***************************************************************************************************************\n\nTASK [Create directory {{ item }}] ***************************************************************************************************************************\nchanged: [Dserver1]  =&gt; (item=\/app)\n...\nchanged: [Dserver1]  =&gt; (item=\/app\/docker)\n...\nchanged: [Dserver10] =&gt; (item=\/app)\n...\nchanged: [Dserver10] =&gt; (item=\/app\/docker)\n\nPLAY RECAP ***************************************************************************************************************************************************\nDserver1  : ok=0 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0\n...\nDserver10 : ok=0 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0<\/pre>\n<p>A second run will have this RECAP which means nothing was changed (changed=0) as it was conform:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">PLAY RECAP ***************************************************************************************************************************************************\nDserver1  : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0\n...\nDserver10 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0<\/pre>\n<h3>Next Steps<\/h3>\n<p>As possible improvements, I could think of converting each checks in preprerquisites script to an Ansible task but keeping in mind that most of the checks must not be implemented by the playbook.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating simple ansible playbooks<\/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,1320],"tags":[150,1075],"type_dbi":[],"class_list":["post-16314","post","type-post","status-publish","format-standard","hentry","category-ansible","category-devops","tag-ansible","tag-bash"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.5) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Starting with Simple Ansible Playbooks - dbi Blog<\/title>\n<meta name=\"description\" content=\"How to automate simple but repetitive tasks with ansible playbooks.\" \/>\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\/starting-with-simple-ansible-playbooks\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Starting with Simple Ansible Playbooks\" \/>\n<meta property=\"og:description\" content=\"How to automate simple but repetitive tasks with ansible playbooks.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-05-07T09:24:40+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-09-11T13:06:50+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\\\/starting-with-simple-ansible-playbooks\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/\"},\"author\":{\"name\":\"DevOps\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/4cd1b5f8a3de93f05a16ab8d7d2b7735\"},\"headline\":\"Starting with Simple Ansible Playbooks\",\"datePublished\":\"2021-05-07T09:24:40+00:00\",\"dateModified\":\"2024-09-11T13:06:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/\"},\"wordCount\":681,\"commentCount\":0,\"keywords\":[\"Ansible\",\"Bash\"],\"articleSection\":[\"Ansible\",\"DevOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/\",\"name\":\"Starting with Simple Ansible Playbooks - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\"},\"datePublished\":\"2021-05-07T09:24:40+00:00\",\"dateModified\":\"2024-09-11T13:06:50+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/4cd1b5f8a3de93f05a16ab8d7d2b7735\"},\"description\":\"How to automate simple but repetitive tasks with ansible playbooks.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/starting-with-simple-ansible-playbooks\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Starting with Simple Ansible Playbooks\"}]},{\"@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":"Starting with Simple Ansible Playbooks - dbi Blog","description":"How to automate simple but repetitive tasks with ansible playbooks.","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\/starting-with-simple-ansible-playbooks\/","og_locale":"en_US","og_type":"article","og_title":"Starting with Simple Ansible Playbooks","og_description":"How to automate simple but repetitive tasks with ansible playbooks.","og_url":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/","og_site_name":"dbi Blog","article_published_time":"2021-05-07T09:24:40+00:00","article_modified_time":"2024-09-11T13:06:50+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\/starting-with-simple-ansible-playbooks\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/"},"author":{"name":"DevOps","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/4cd1b5f8a3de93f05a16ab8d7d2b7735"},"headline":"Starting with Simple Ansible Playbooks","datePublished":"2021-05-07T09:24:40+00:00","dateModified":"2024-09-11T13:06:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/"},"wordCount":681,"commentCount":0,"keywords":["Ansible","Bash"],"articleSection":["Ansible","DevOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/","url":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/","name":"Starting with Simple Ansible Playbooks - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2021-05-07T09:24:40+00:00","dateModified":"2024-09-11T13:06:50+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/4cd1b5f8a3de93f05a16ab8d7d2b7735"},"description":"How to automate simple but repetitive tasks with ansible playbooks.","breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/starting-with-simple-ansible-playbooks\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Starting with Simple Ansible Playbooks"}]},{"@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\/16314","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=16314"}],"version-history":[{"count":1,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/16314\/revisions"}],"predecessor-version":[{"id":34730,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/16314\/revisions\/34730"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=16314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=16314"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=16314"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=16314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}