{"id":822,"date":"2021-05-10T13:12:26","date_gmt":"2021-05-10T12:12:26","guid":{"rendered":"https:\/\/nine30.info\/?p=822"},"modified":"2021-05-10T13:12:26","modified_gmt":"2021-05-10T12:12:26","slug":"vra-saltstack-config-event-driven-automation","status":"publish","type":"post","link":"https:\/\/nine30.nxt70.com\/index.php\/2021\/05\/10\/vra-saltstack-config-event-driven-automation\/","title":{"rendered":"vRA SaltStack Config \u2013 Event-Driven Automation"},"content":{"rendered":"\n<p>In the <a rel=\"noreferrer noopener\" href=\"https:\/\/nine30.info\/vra-saltstack-config-declarative-configuration-management\/\" target=\"_blank\">previous post<\/a> we introduced State Files and explored a bit how they allow a declarative approach to configuration management. We also covered how States Files can be applied to Targets through Commands and Jobs and we will explore in the future the concept of Highstate. All of this is human initiated: an operator user choose to apply a State File to a Target. However, Salt also supports an <strong>event-driven<\/strong> approach: Salt executes automation tasks (not necessarily applying State Files) as a reaction to specific event(s).<\/p>\n\n\n\n<p>Event-driven is a distinctive capability of Salt and it is one of its foundation elements. Indeed, Salt is built around an event infrastructure that can be leveraged and extended to drive reactive provisioning, configuration, and management across all devices in your infrastructure. Hereafter there are some examples of things that people do with Salt&#8217;s event driven automation:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Instantly restore a configuration file when an unauthorized change is made;<\/li><li>Notify a Slack channel when a build fails;<\/li><li>Send an email when a user logs on to a production server;<\/li><li>Automatically scale compute resources;<\/li><\/ul>\n\n\n\n<p>The schema below shows the main components of the Salt&#8217;s event driven systems. Wow, honestly it looks more complex than actually it is! I made it a bit more complex than actually needed because I wanted to stress the point that there are different type of events and commands (actions). Let&#8217;s start with events (red arrows), please note the following is not orthodox (aka Salt fully compliant), but it helped me to understand it and I hope this works for you as well: 1) internal events in my schema are those generated by the Master, 2) of course events are generated from Minions and 3) Beacon events are fired from a Beacon configurations (still generated from Minions) and are the output of a monitoring activity.  On the other side, commands (in green): 1) commands executed on the Master(s) such as Salt Runners (i.e. tasks you would start using&nbsp;<code>salt-run<\/code>) and Wheels (commands to manage your Salt environment such as tasks you would start using&nbsp;<code>salt-key<\/code> utility); 2) remote execution, these run an execution module on the targeted minions (tasks you would start using&nbsp;<code>salt<\/code>).<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"833\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/Reactor-Schema-Numbers.jpg\" alt=\"\" class=\"wp-image-833\"\/><\/figure>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Events<\/h2>\n\n\n\n<p>Salt\u2019s internal components communicate with each other by sending and listening to events. In Salt, events are sent for about everything you could imagine: Salt Minion connects, Key is accepted or rejected, Job is sent, Job results are returned from a Minion, etc. Events are made up of two main parts: <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Tag<\/strong>: which identifies the event that was fired. All Salt events are prefixed with&nbsp;<code>salt\/<\/code>, with additional levels based on the type of event. For example, Job events are prefixed with&nbsp;<code>salt\/job\/<\/code>. Each event tag part is separated using&nbsp;<code>\/<\/code>&nbsp;to provide simple namespacing and can include specific details such as a Job ID or Minion ID;<\/li><li><strong>Data<\/strong>: that contains details about the event. Each event contains a&nbsp;<code>timestamp<\/code>&nbsp;and additional keys and values that are unique to that specific event. <\/li><\/ul>\n\n\n\n<p>Salt comes with tons of built-in events, in addition to that you can enable some additional events in the Salt system, as well as generate your own custom events (that&#8217;s super easy!). In addition to these, you can also use Beacons to monitor and raise events for things that are not Salt-related (e.g. systems logins, disk usage, service status, etc.)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Beacons<\/h2>\n\n\n\n<p>The Beacon system allows the minion to hook into a variety of system processes and continually monitor these processes. When monitored activity occurs in a system process, an event is sent on the Salt event bus. Salt Beacons can currently monitor and send Salt events for many system activities, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>file system changes;<\/li><li>system load;<\/li><li>service status;<\/li><li>shell activity, such as user login;<\/li><li>network and disk usage;<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Reactors<\/h2>\n\n\n\n<p>Salt\u2019s Reactor mechanism gives you the ability to trigger actions in response to any event. Not only can you trigger actions when Jobs and tasks complete, you can trigger actions when services go down, users log in, files are changed, and from anywhere that you can send a custom event (end of a build script, cron job, etc.). A Salt Reactor is a configuration that defines how to react (what action execute) to specific events that are fired within the event system. <\/p>\n\n\n\n<p>Reactors States are State Files that are executed to react against specific events. There are three types of reactions:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Remote execution<\/strong>: run an execution module on the targeted Minions. This is anything you would do by calling the&nbsp;<code>salt<\/code>&nbsp;command including applying a State or Highstate;<\/li><li><strong>Salt Runners<\/strong>: these are tasks you would start using&nbsp;<code>salt-run<\/code>. For example, the&nbsp;<a href=\"https:\/\/docs.saltstack.com\/en\/latest\/ref\/runners\/all\/salt.runners.http.html\">HTTP<\/a>&nbsp;runner can trigger a webhook;<\/li><li><strong>Wheel<\/strong>:  these commands manage your Salt environment, performing tasks such as accepting keys and updating configuration settings. Some of these tasks are exposed by the&nbsp;<code>salt-key<\/code>&nbsp;utility.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Lab Time!<\/h2>\n\n\n\n<p>I am going to close this post with a super basic example of event-driven automation. We will use Salt to ensure a specific web page is served from a web server :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>we will use a Salt Beacon to monitor the status of a file (our web page) and this will notify Salt Master if the file is changed<\/li><li>we will configure a Salt Reactor to react upon Beacon event in order to restore the original file<\/li><\/ul>\n\n\n\n<p>As a prerequisite we just need a CentOS machine with Salt Minion installed (see <a rel=\"noreferrer noopener\" href=\"https:\/\/nine30.info\/vra-saltstack-config-add-minions-and-commands\/\" target=\"_blank\">this post<\/a> for instructions). Here after there is the list of macro steps: <\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Apache Web Server installed and serving the following static web page <code style=\"font-size: 21px; background-color: rgb(221, 221, 221);\">\/var\/www\/html<\/code><code>\/index.php<\/code><\/li><li>Python package named <code>pyinotify<\/code> installed<\/li><li>A Beacons on the Minion that notify whenever a change is applied to the file <code>\/var\/www\/html\/index.php<\/code><\/li><li>A Reactor that triggers a State File designed to restore the original file when a change is notified from the Beacon    <\/li><\/ol>\n\n\n\n<p>We will implement steps from 1 to 3 with Salt (of course) using the following single State File. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Install and configure Apache HTTPD on CentOS\/RHEL\n# Deploy Beacon with prerequisites to monitor file \/var\/www\/html\/index.php\n\n# Prerequisites for Beacons\n\ninstall_epel_pip:\n  pkg.installed:\n    - pkgs: \n      - epel-release\n      - python2-pip\n    - reload_modules: True\n\ninstall_inotify:\n  pip.installed:\n    - name: pyinotify\n    - bin_env: \/usr\/bin\/python\n    - require:\n      - pkg: install_epel_pip\n\n# Install and configure Apache HTTPD\n\ninstall_apache:\n  pkg.installed:\n    - pkgs:\n      - httpd\n      - php\n\nconfigure_apache:\n  file.managed:\n    - name: \/etc\/httpd\/conf\/httpd.conf\n    - source: salt:\/\/applications\/apache\/files\/httpd.conf\n    - template: jinja\n    - require:\n      - pkg: install_apache\n    - defaults:\n        admin_email: user@host.org\n        group: apache\n        user: apache\n        http_port: 80\n\n# Deploy sample web page\n\nconfigure_web_page:\n  file.managed:\n    - name: \/var\/www\/html\/index.php\n    - source: salt:\/\/applications\/apache\/files\/index.php\n    - require:\n      - pkg: install_apache\n\n# Deploy Beacons\n\ndeploy_beacons_file:\n  file.managed:\n    - name: \/etc\/salt\/minion.d\/beacons.conf\n    - source: salt:\/\/applications\/apache\/files\/beacons.conf\n    - makedirs: True\n\n# Restart Apache HTTPD and Salt Minion processes upon respective config files are updated\n\nrestart_salt-minion:\n  service.running:\n    - name: salt-minion\n    - enable: True\n    - watch:\n      - deploy_beacons_file\n\nstart_apache:\n  service.running:\n    - name: httpd\n    - enable: True\n    - watch:\n      - file: configure_apache<\/code><\/pre>\n\n\n\n<p>The State File above is actually the same used in my <a rel=\"noreferrer noopener\" href=\"https:\/\/nine30.info\/vra-saltstack-config-declarative-configuration-management\/\" target=\"_blank\">previous post<\/a> with the additions of <code>index.php<\/code> and <code>beacons.conf<\/code> deployments, install of Beacon prerequisites and php. You can proceed it by updating it. Here is detail about changes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Prerequisites for Beacons\n\ninstall_epel_pip:\n  pkg.installed:\n    - pkgs: \n      - epel-release\n      - python2-pip\n    - reload_modules: True\n\ninstall_inotify:\n  pip.installed:\n    - name: pyinotify\n    - bin_env: \/usr\/bin\/python\n    - require:\n      - pkg: install_epel_pip<\/code><\/pre>\n\n\n\n<p>Prerequisite for Beacons is the Python package named <code>pyinotify<\/code>, in order to install it we need to have <code>pip<\/code> installed from <code>epel-release<\/code> repo. Please, note the followings in the snippet above: <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>option <code>reload_module<\/code> is set to <code>True<\/code>. This allows you to force Salt to reload all modules. In many cases Salt is clever enough to transparently reload the modules, but here we need it to make sure we can actually use the pip state module in the <code>install_inotify<\/code> section of the state file<\/li><li>in the <code>install_inotify<\/code> section we use the <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.saltproject.io\/en\/latest\/ref\/states\/all\/salt.states.pip_state.html\" target=\"_blank\">pip state module<\/a> to install the <code>pyinotify<\/code> Python package<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code># Install and configure Apache HTTPD\n\ninstall_apache:\n  pkg.installed:\n    - pkgs:\n      - httpd\n      - php<\/code><\/pre>\n\n\n\n<p>In the <code>install_apache<\/code> section we also install php that is needed to run the sample web page.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Deploy sample web page\n\nconfigure_web_page:\n  file.managed:\n    - name: \/var\/www\/html\/index.php\n    - source: salt:\/\/applications\/apache\/files\/index.php\n    - require:\n      - pkg: install_apache\n\n# Deploy Beacons\n\ndeploy_beacons_file:\n  file.managed:\n    - name: \/etc\/salt\/minion.d\/beacons.conf\n    - source: salt:\/\/applications\/apache\/files\/beacons.conf\n    - makedirs: True<\/code><\/pre>\n\n\n\n<p>With the snippet above we deploy on the targeted machine the <code>index.php<\/code> and the <code>beacon.conf<\/code> files, later in this post we will make sure these files are available in the Salt Master File Server. The only thing worth to mention is that in the <code>deploy_bacons_file<\/code> section we use the option <code>makedirs<\/code> set to <code>True<\/code> which functionality is pretty obvious.  <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Restart Apache HTTPD and Salt Minion processes upon respective config files are updated\n\nrestart_salt-minion:\n  service.running:\n    - name: salt-minion\n    - enable: True\n    - watch:\n      - deploy_beacons_file<\/code><\/pre>\n\n\n\n<p>The new Beacon configuration require a Salt Minion restart.<\/p>\n\n\n\n<p>As mentioned above we need to make sure both <code>index.php<\/code> and the <code>beacon.conf<\/code> files are available in the Salt Master File Server. Through the vRA SaltStack Config user interface add the following sample web page file under <code>\/applications\/apache\/files<\/code>\/<code>index.php<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;Event Driven Automation Test Page&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Web Server Test Page&lt;\/h1&gt;\n    &lt;?php\n    echo 'Serving this page from Host IP Address : '. $_SERVER&#91;'HTTP_HOST'];\n    ?&gt; \n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"846\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/02.add_.index_.file_.png\" alt=\"\" class=\"wp-image-846\"\/><\/figure>\n<\/figure>\n\n\n\n<p>Than add also the following <code>beacons.conf<\/code> under the same path. As you can see the Beacon configuration is pretty simple it just states the absolute path of the file to be monitored and the mask option specify what action on the file should trigger the Beacon Event. It should be wise to add t the end of the <code>beacons.conf<\/code> file the <code>disable_during_state_run:&nbsp;True<\/code>&nbsp;parameter prevents the inotify beacon from generating Reactor events due to Salt itself modifying the file. In this case it is not strictly required as we opted for the <code>close_write<\/code> action to fire the Beacon Event.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Beacons file that watched \/var\/www\/html\/index.php\n\nbeacons:\n  inotify:\n    - files:\n      \/var\/www\/html\/index.php\n        mask:\n          - close_write<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"864\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/03.add_.beacons.file_.png\" alt=\"\" class=\"wp-image-864\"\/><\/figure>\n<\/figure>\n\n\n\n<p>Ok now it is time to configure the Reactor mechanism, in our case this is comprised by 3 elements:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>A <code>reacotr.conf<\/code> file on the Master: this file specify what events we want Salt to react and what action(s) Salt need to execute. As we said earlier in this post Salt actions within a Reactor can be: Remote executions, Salt Runners and Wheels<\/li><li>An orchestration state file: this allows to the Reactor to apply a specific state file as a reaction to a specific event. Orchestration is a broad concept that we are not touching here<\/li><li>State File: this is the declarative automation that make sure the required <code>index.php<\/code> is in place in the right path<\/li><\/ol>\n\n\n\n<p>Let&#8217;s start from the <code>reactor.conf<\/code> configuration file. Make sure the <code>reactor.conf<\/code> below is placed on the Salt Master in the following path <code>\/etc\/salt\/master.d<\/code> or to append the two final lines to the existing <code>reactor.conf<\/code> if you have one in place already. You can do this manually or through Salt (at this point you should know how to do that), just make sure to restart the Salt Master process after updating the Reactor file. This file is simply instructing Salt Master to execute the <code>fix-index-file.orch<\/code> state file when it receives an event with the following tag <code>salt\/beacon\/*\/inotify\/\/var\/www\/html\/index.php<\/code> <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Reactor configuration to be located \/etc\/salt\/master.d\/reactor.conf on the Salt Master\n\nreactor:\n  - 'salt\/beacon\/*\/inotify\/\/var\/www\/html\/index.php':\n    - 'salt:\/\/reactor\/orchestrate\/fix-index-file.orch'<\/code><\/pre>\n\n\n\n<p>In the Reactor file we are referring to a state file named <code>fix-index-file.orch<\/code>, we need to make sure it exist in the File Server. Through the vRA SaltStack Config user interface add the State file in the snippet below under <code>\/reactor\/orchestrate\/fix-index-file.orch<\/code>. This State file is an Orchestration that applies a State file located in <code>\/applications\/apache\/index-file.sls<\/code> (<code>arg<\/code> parameter) to the target specified in the <code>tgt<\/code> parameters. You surely noted that the <code>tgt<\/code> has a parametric value, the <code>{{ data['id'] }}<\/code> syntax is instructing the state file to use as Target the event payload value identified by the key <code>'id'<\/code>. In our case this is the Minion ID that fired the Beacon Event.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Orchestrator to react on index.php file changes\n\nfix_index_file:\n  local.state.apply:\n    - tgt: {{ data&#91;'id'] }}\n    - arg: \n      - applications.apache.index-file<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"868\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/04.add_.orch_.file_.png\" alt=\"\" class=\"wp-image-868\"\/><\/figure>\n<\/figure>\n\n\n\n<p>In the above Orchestration we refer to another State file, we need to make sure this exists in our File Server. Through the vRA SaltStack Config user interface add the State file in the snippet below under this path <code>\/applications\/apache\/index-file.sls<\/code>. This State file simply make sure the original <code>index.php<\/code> is present in the right location on the targeted machine. Nothing special here, we just need to note that I had to add a 20 second delay in order to allow me to test\/demonstrate this use case because Salt is so fast that fix the issue in a couple of seconds.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># State file used to restore the original index.php file\n\n# Need to sleep 20 sec because salt is too fast!!!\nsleep_20:\n  cmd.run:\n    - name: sleep 20\n\ndeploy_index_file:\n  file.managed:\n    - name: \/var\/www\/html\/index.php\n    - source: salt:\/\/applications\/apache\/files\/index.php\n    - require:\n      - sleep 20\n\nrestart_apache:\n  service.running:\n    - name: httpd\n    - enable: True\n    - watch:\n      - deploy_index_file<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Test<\/h2>\n\n\n\n<p>As first thing we need to apply the state files that install Apache Web Server along with our sample web page, Beacon and its prerequisites. Select your Minion, click on run Command button, fill the form with <code>state.apply<\/code> function and the path to our apache State file.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"872\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/03.run_-1.png\" alt=\"\" class=\"wp-image-872\"\/><\/figure>\n<\/figure>\n\n\n\n<p>Once the Job is successfully completed access the sample web page through <code>http:\/\/&lt;machine-ip-or-fqdn&gt;<\/code> in your browser.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-6 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"873\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/05.original.page_.png\" alt=\"\" class=\"wp-image-873\"\/><\/figure>\n<\/figure>\n\n\n\n<p>Now ssh to your machine and edit <code>\/var\/www\/html\/index.php<\/code> with your favourite editor, apply some changes than save it. Here the 20 seconds delay in our Reactor mechanism allows us to refresh the web page to actually see the change. Without this delay it would be almost impossible for us to refresh the page, of course the delay is just for test\/demonstration purposes.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-7 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"874\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/06.edited.page_.png\" alt=\"\" class=\"wp-image-874\"\/><\/figure>\n<\/figure>\n\n\n\n<p>The Reactor triggers the State file to be applied against our Minion and once it is completed the original web page is restored.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-8 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"875\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/07.job_.run_.png\" alt=\"\" class=\"wp-image-875\"\/><\/figure>\n<\/figure>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-9 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"876\" src=\"https:\/\/nine30.info\/wp-content\/uploads\/2021\/04\/08.restored.page_.png\" alt=\"\" class=\"wp-image-876\"\/><\/figure>\n<\/figure>\n\n\n\n<p>This is just a trivial example to get you introduced to the powerful and funny world of Event Driven Automation. Now it is your time to experiment! <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous post we introduced State Files and explored a bit how they allow a declarative approach to configuration management. We also covered how States Files can be applied to Targets through Commands and Jobs and we will explore in the future the concept of Highstate. All of this is human initiated: an operator&hellip; <a class=\"more-link\" href=\"https:\/\/nine30.nxt70.com\/index.php\/2021\/05\/10\/vra-saltstack-config-event-driven-automation\/\">Continue reading <span class=\"screen-reader-text\">vRA SaltStack Config \u2013 Event-Driven Automation<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":249,"comment_status":"open","ping_status":"open","sticky":false,"template":"templates\/template-cover.php","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[13,23,40,41,60,88,99,122,126,143,145,178,185,186],"class_list":["post-822","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech","tag-apache","tag-automation","tag-configuration","tag-configurationmanagement","tag-eventdriven","tag-iac","tag-linux","tag-opensource","tag-oss","tag-salt","tag-saltstack","tag-vmware","tag-vrealize","tag-vrealizeautomation","entry"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/posts\/822","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/comments?post=822"}],"version-history":[{"count":0,"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/posts\/822\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/media?parent=822"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/categories?post=822"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nine30.nxt70.com\/index.php\/wp-json\/wp\/v2\/tags?post=822"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}