{"id":6618,"date":"2020-11-16T12:16:15","date_gmt":"2020-11-16T18:16:15","guid":{"rendered":"http:\/\/gregsowell.com\/?p=6618"},"modified":"2020-11-16T12:16:15","modified_gmt":"2020-11-16T18:16:15","slug":"using-servicenow-as-an-cmdb-in-ansible-automation-platform","status":"publish","type":"post","link":"https:\/\/gregsowell.com\/?p=6618","title":{"rendered":"Using ServiceNow As An CMDB In Ansible Automation Platform"},"content":{"rendered":"<p>Pulling in hosts from SNOW really isn&#8217;t too bad, and in fact, there&#8217;s an <a href=\"https:\/\/www.ansible.com\/blog\/using-an-inventory-plugin-from-a-collection-in-ansible-tower\">Ansible blog post on it here<\/a>.  I&#8217;m not reinventing the wheel here, but I figure it&#8217;s always nice to have another perspective on the process.<\/p>\n<h2>Demo Video<\/h2>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/Nmfv_zNg6M8\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<h2>SNOW CMDBs<\/h2>\n<p>First things first, where can I find the SNOW CMBDs?  I use a developer instance, so there is already some material to work with, so your install may look different.<br \/>\n<a href=\"https:\/\/docs.servicenow.com\/bundle\/paris-servicenow-platform\/page\/product\/configuration-management\/concept\/c_OptionsToPopulateCMDB.html\">Here&#8217;s an article<\/a> that shows how to quickly add entries to your CMDB, but also where to access everything.<\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow1-300x167.png\" alt=\"\" width=\"300\" height=\"167\" class=\"aligncenter size-medium wp-image-6621\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow1-300x167.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow1.png 526w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nIn SNOW type in &#8220;ci class manager&#8221; in the search field.  Once there, click on the &#8220;Hierarchy&#8221; button.<\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow2-253x300.png\" alt=\"\" width=\"253\" height=\"300\" class=\"aligncenter size-medium wp-image-6622\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow2-253x300.png 253w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow2.png 699w\" sizes=\"auto, (max-width: 253px) 100vw, 253px\" \/><\/a><br \/>\nIn here I browsed under hardware, network gear, and finally into ip switch.<\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow3-300x121.png\" alt=\"\" width=\"300\" height=\"121\" class=\"aligncenter size-medium wp-image-6623\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow3-300x121.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow3-768x311.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow3-1024x414.png 1024w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow3.png 1340w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nOnce there to view all of the devices(or to add\/edit them), click &#8220;ci list&#8221;.  These entries were added by me; I put the manufacturer and IP addresses specifically.  In the Tower section I use the manufacturer entry to assign the devices to a group as they are imported.<\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow4-300x300.png\" alt=\"\" width=\"300\" height=\"300\" class=\"aligncenter size-medium wp-image-6624\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow4-300x300.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow4-150x150.png 150w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/snow4.png 744w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nIf I&#8217;m curious about what columns are available in the table, I&#8217;ll browse the attribute section under class info.<\/p>\n<h2>Playbooks<\/h2>\n<p><a href=\"https:\/\/github.com\/gregsowell\/ansible-servicenow-cmdb\">Relevant Github found here<\/a>.<\/p>\n<p>First I&#8217;m using a <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/collections_using.html\">collection<\/a> in the dynamic inventory script.  This is a new method Ansible is using to package files together.  I can manually install the collection ahead of time, or I can specify it in a requirements file and it will be pulled at run-time.  The requirements.yml file is saved in a folder named collections.  Here&#8217;s the contents of my requirements file:<br \/>\n<script src=\"http:\/\/gist-it.appspot.com\/https:\/\/github.com\/gregsowell\/ansible-servicenow-cmdb\/blob\/main\/collections\/requirements.yml\"><\/script><\/p>\n<p>Now that I&#8217;ve got that out of the way, I&#8217;ll take a look at the dynamic inventory file.  In this case I&#8217;ve named it snow-switch-now.yml.  <strong>Keep in mind that there is some arbitrary requirement that this file end with &#8220;now.yml&#8221;<\/strong>, so keep that in mind.<br \/>\n<script src=\"http:\/\/gist-it.appspot.com\/https:\/\/github.com\/gregsowell\/ansible-servicenow-cmdb\/blob\/main\/snow-switch-now.yml\"><\/script><br \/>\nHaving a look at this file, the plugin will always be the same(just how we are pulling everything).<br \/>\nThe table will change based on which specific CMBD I want to pull.  In this case I want all of the ip_switches.  This name can be found above in the SNOW &#8220;ci class manager&#8221; section.<\/p>\n<p>The fields section are the info that will be returned.  Ultimately these will be added as hostvars for the inventory objects.<\/p>\n<p>They keyed_groups section will add the hosts to groups based on returned CMDB information.  In this case I&#8217;m going based on manufacturer, so all of my Cisco kit will end up in the cisco group.<\/p>\n<h2>Tower<\/h2>\n<p>First I need to setup a credential, and I created a custom credential to pass in my SNOW instance, username, and password via environment variables:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower1-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower1-1-297x300.png\" alt=\"\" width=\"297\" height=\"300\" class=\"aligncenter size-medium wp-image-6627\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower1-1-297x300.png 297w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower1-1.png 667w\" sizes=\"auto, (max-width: 297px) 100vw, 297px\" \/><\/a><\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">fields:\r\n  - id: supp_snow_instance\r\n    type: string\r\n    label: Instance Name\r\n  - id: supp_snow_username\r\n    type: string\r\n    label: Username\r\n  - id: supp_snow_password\r\n    type: string\r\n    label: Password\r\n    secret: true\r\nrequired:\r\n  - supp_snow_instance\r\n  - supp_snow_username\r\n  - supp_snow_password<\/code><\/pre>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">env:\r\n  SN_INSTANCE: &#039;{{ supp_snow_instance }}&#039;\r\n  SN_PASSWORD: &#039;{{ supp_snow_password }}&#039;\r\n  SN_USERNAME: &#039;{{ supp_snow_username }}&#039;<\/code><\/pre>\n<p>Once that&#8217;s created and I added in my custom credential, I then create the inventory.<\/p>\n<p>I&#8217;ll go ahead and add the repo I just created as a project; this will pull in all of my custom inventory yaml files.<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower4-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower4-1-300x147.png\" alt=\"\" width=\"300\" height=\"147\" class=\"aligncenter size-medium wp-image-6630\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower4-1-300x147.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower4-1-768x378.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower4-1.png 889w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower2-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower2-1-300x99.png\" alt=\"\" width=\"300\" height=\"99\" class=\"aligncenter size-medium wp-image-6628\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower2-1-300x99.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower2-1-768x255.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower2-1.png 854w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nWhere it diverges is that I click the sources section and add a custom source.<\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower3-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower3-1-300x98.png\" alt=\"\" width=\"300\" height=\"98\" class=\"aligncenter size-medium wp-image-6629\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower3-1-300x98.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower3-1-768x251.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower3-1-1024x335.png 1024w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower3-1.png 1322w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nOnce in the custom source I choose sourced from project, use my SNOW credentials I just created, choose the project holding my custom import script, and choose the yaml file.<\/p>\n<p>Now when I syncronize the inventory it pulls in my CMDB objects from SNOW:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower5-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower5-1-300x171.png\" alt=\"\" width=\"300\" height=\"171\" class=\"aligncenter size-medium wp-image-6631\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower5-1-300x171.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower5-1.png 665w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower6-300x196.png\" alt=\"\" width=\"300\" height=\"196\" class=\"aligncenter size-medium wp-image-6632\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower6-300x196.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower6.png 678w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower7.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower7-300x155.png\" alt=\"\" width=\"300\" height=\"155\" class=\"aligncenter size-medium wp-image-6633\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower7-300x155.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower7-768x396.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/11\/tower7.png 836w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>Conclusion<\/h2>\n<p>While none of this is too terribly difficult, the first one can take a few minutes to sort out.  Most of my problems surrounded formatting on the import yaml file, so be sure all of your column names are correct.  I like the flexibility and power of this; how it allows you to very granularly separate inventories based on tables.<\/p>\n<p>Let me know how you can see using this, questions, and comments.<\/p>\n<p>Thanks and happy automating!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pulling in hosts from SNOW really isn&#8217;t too bad, and in fact, there&#8217;s an Ansible blog post on it here. I&#8217;m not reinventing the\u2026<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49],"tags":[],"class_list":["post-6618","post","type-post","status-publish","format-standard","hentry","category-ansible"],"_links":{"self":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6618","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6618"}],"version-history":[{"count":6,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6618\/revisions"}],"predecessor-version":[{"id":6635,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6618\/revisions\/6635"}],"wp:attachment":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6618"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6618"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6618"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}