<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Amit Bhatt</title>
    <description>The latest articles on DEV Community by Amit Bhatt (@amitbhatt818).</description>
    <link>https://dev.to/amitbhatt818</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F404393%2Fb6d61da8-5030-4e35-a515-11d57bfb8fa0.jpg</url>
      <title>DEV Community: Amit Bhatt</title>
      <link>https://dev.to/amitbhatt818</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amitbhatt818"/>
    <language>en</language>
    <item>
      <title>This declarative approach eased my work as an Automation Engineer</title>
      <dc:creator>Amit Bhatt</dc:creator>
      <pubDate>Fri, 21 Aug 2020 17:52:36 +0000</pubDate>
      <link>https://dev.to/amitbhatt818/this-declarative-approach-eased-my-work-as-an-automation-engineer-k5n</link>
      <guid>https://dev.to/amitbhatt818/this-declarative-approach-eased-my-work-as-an-automation-engineer-k5n</guid>
      <description>&lt;div class="ltag__user ltag__user__id__404393"&gt;
    &lt;a href="/amitbhatt818" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F404393%2Fb6d61da8-5030-4e35-a515-11d57bfb8fa0.jpg" alt="amitbhatt818 image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/amitbhatt818"&gt;Amit Bhatt&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/amitbhatt818"&gt;Software Engineer at Acquia || Ex MayaData ||CKA || Chaos Engineering || Contributer @LitmusChaos || Kubernetes || DevOps || GoLang&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I have been using &lt;strong&gt;Ansible&lt;/strong&gt; for a while to automate everything related to Kubernetes. One of the irritants for me was the mix of bash, awk, sed, loops, and conditions along with Ansible YAML to get my job automated. This is when I decided to invest some time to learn more about the pure declarative intents that Kubernetes operator pattern offered. This post is a summary of my experience of this investment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;So what is this declarative approach?&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This definitely is not something that has its origins within Kubernetes. In-fact if you have written any Jenkinsfile (i.e. groovy scripts) or Terraform or used YAMLs to express configurations of an application then you have already experienced the declarative nuances of programming. However, being declarative the Kubernetes way needs to be grasped with a pinch of salt. Kubernetes has been advocating the use of custom resources and backing controllers to let teams handle their infrastructure. One can think of html &amp;amp; backing javascript as an analogy where we are often advised to have clear separation of responsibilities &amp;amp; avoid mixing user interface styling with logic. If done right, html defines the look and feel of the web page while javascript handles the behavioral part. Alas few care about the advice and the best practices. We often find loads of javascript embedded inside the html specifications. The same can be said about other declarative approaches where logic finds its way into the declarations. Kubernetes on the other hand advocates that these declarations remain pure. Hence one does not find templating or loops inside Pod specifications.&lt;/p&gt;

&lt;p&gt;In the world of Kubernetes, custom resources are used to express the declarative intents that are free from side effects (read logic). It does not end here. These specifications define the desired state and corresponding controllers have the responsibility to make this desired state a reality. Since we are not here to dig deep into Kubernetes control loops, let's get straight to the point. All we need when dealing with Kubernetes is its CLI and a bunch of YAMLs to convey our intentions to the Kubernetes cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Introduction to d-operators&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I started experimenting with &lt;a href="https://github.com/mayadata-io/d-operators" rel="noopener noreferrer"&gt;d-operators&lt;/a&gt; to define declarative intents that look like imperative workflows to manage Kubernetes resources. On the whole, I wanted to avoid using kubectl and other command based invocations inside my YAMLs. D-operators make use of the &lt;a href="https://github.com/AmitKumarDas/metac" rel="noopener noreferrer"&gt;metacontroller&lt;/a&gt; SDK under the hood. My intention is to enable yaml authors to create, delete, update, assert, patch, clone, schedule, etc. one or more Kubernetes resources (native as well as custom) using a yaml file. This yaml file is in turn governed by a backing Kubernetes controller that deals with reconciliation and other Kubernetes internals.&lt;/p&gt;

&lt;p&gt;Needless to say, the project tries its best to follow a pure intent based approach to define specifications instead of having to deal with yamls that are cluttered with scripts, kubectl, loops, conditions, templating and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Show me the c̶o̶d̶e̶ YAML&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Following is an automated way to run CRUD operations with respect to a Kubernetes Pod.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dope.metacontroller.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Recipe&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;crud-ops-on-pod&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;d-testing&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;d-testing.dope.metacontroller.io/enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                       &lt;span class="c1"&gt;### -----&amp;gt; Add multiple operations via tasks&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apply-a-namespace&lt;/span&gt;    &lt;span class="c1"&gt;### ----&amp;gt; This applies a Namespace&lt;/span&gt;
    &lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-ns&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;create-a-pod&lt;/span&gt;         &lt;span class="c1"&gt;### -----&amp;gt; This creates a Pod&lt;/span&gt;
    &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-pod&lt;/span&gt;
          &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-ns&lt;/span&gt;
        &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
            &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delete-the-pod&lt;/span&gt;       &lt;span class="c1"&gt;### -----&amp;gt; This deletes the Pod&lt;/span&gt;
    &lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-pod&lt;/span&gt;
          &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-ns&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delete-the-namespace&lt;/span&gt;  &lt;span class="c1"&gt;### ----&amp;gt; This deletes the Namespace&lt;/span&gt;
    &lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-ns&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assert-presence-of-pod&lt;/span&gt; &lt;span class="c1"&gt;### ----&amp;gt; Check presence of Pod&lt;/span&gt;
    &lt;span class="na"&gt;assert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
          &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Result&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can see the result of the above yaml in the description of the job itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;crud-ops-on-pod&lt;/span&gt;
&lt;span class="na"&gt;Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;d-testing&lt;/span&gt;
&lt;span class="na"&gt;Labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;d-testing.dope.metacontroller.io/enabled=true&lt;/span&gt;
              &lt;span class="s"&gt;job.dope.metacontroller.io/phase=Completed&lt;/span&gt;
&lt;span class="na"&gt;Annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;&amp;lt;none&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;API Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;dope.metacontroller.io/v1&lt;/span&gt;
&lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;Recipe&lt;/span&gt;
&lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Creation Timestamp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;2020-07-21T18:59:09Z&lt;/span&gt;
  &lt;span class="na"&gt;Generation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;Resource Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="m"&gt;33101724&lt;/span&gt;
  &lt;span class="na"&gt;Self Link&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;/apis/metacontroller.app/v1/namespaces/d-testing/jobs/crud-ops-on-pod&lt;/span&gt;
  &lt;span class="na"&gt;UID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                 &lt;span class="s"&gt;2eb8f663-15cd-4836-bfd5-14b3ca4aefd3&lt;/span&gt;
&lt;span class="na"&gt;Spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Apply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;State&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;API Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;Namespace&lt;/span&gt;
        &lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;my-ns&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;apply-a-namespace&lt;/span&gt;
    &lt;span class="na"&gt;Create&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;State&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;API Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;Pod&lt;/span&gt;
        &lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;my-pod&lt;/span&gt;
          &lt;span class="na"&gt;Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;my-ns&lt;/span&gt;
        &lt;span class="na"&gt;Spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;Image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;nginx&lt;/span&gt;
            &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;web&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;create-a-pod&lt;/span&gt;
    &lt;span class="na"&gt;Delete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;State&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;API Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;Pod&lt;/span&gt;
        &lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;my-pod&lt;/span&gt;
          &lt;span class="na"&gt;Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;my-ns&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             &lt;span class="s"&gt;delete-the-pod&lt;/span&gt;
    &lt;span class="na"&gt;Delete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;State&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;API Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;Namespace&lt;/span&gt;
        &lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;my-ns&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;delete-the-namespace&lt;/span&gt;
    &lt;span class="na"&gt;Assert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;State&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;API Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;v1&lt;/span&gt;
        &lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;Pod&lt;/span&gt;
        &lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;nginx&lt;/span&gt;
          &lt;span class="na"&gt;Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             &lt;span class="s"&gt;assert-presence-of-pod&lt;/span&gt;
&lt;span class="na"&gt;Status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Failed Task Count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="na"&gt;Message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;            
  &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;              &lt;span class="s"&gt;Completed&lt;/span&gt;
  &lt;span class="na"&gt;Reason&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             
  &lt;span class="na"&gt;Task Count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;5&lt;/span&gt;
  &lt;span class="na"&gt;Task List Status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Apply - A - Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Message:  Create resource  my-ns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GVK /v1, Kind=Namespace&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;Assert - Presence - Of - Pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Message:  StateCheckEquals: Resource test nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GVK /v1, Kind=Pod&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TaskName assert-presence-of-pod&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;5&lt;/span&gt;
    &lt;span class="na"&gt;Create - A - Pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Message:  Create action: Resource my-ns my-pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GVK /v1, Kind=Pod&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TaskName create-a-pod&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="na"&gt;Crud - Ops - On - Pod - Lock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Internal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;Message:   Create: Lock d-testing crud-ops-on-pod-lock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GVK /v1, Kind=ConfigMap&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="na"&gt;Crud - Ops - On - Pod - Unlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Internal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;Message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;Locked forever&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="m"&gt;7&lt;/span&gt;
    &lt;span class="na"&gt;Delete - The - Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Message:  Delete: Resource  my-ns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GVK /v1, Kind=Namespace&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;4&lt;/span&gt;
    &lt;span class="na"&gt;Delete - The - Pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Message:  Delete: Resource my-ns my-pod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GVK /v1, Kind=Pod&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="na"&gt;Job - Elapsed - Time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Elapsed Time In Seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;0.239145302&lt;/span&gt;
      &lt;span class="na"&gt;Internal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                 &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;Phase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                    &lt;span class="s"&gt;Passed&lt;/span&gt;
      &lt;span class="na"&gt;Step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                     &lt;span class="m"&gt;6&lt;/span&gt;
&lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                         &lt;span class="s"&gt;&amp;lt;none&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Conclusion&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this example, we saw how we can convert a bunch of Kubernetes operations into a declarative specification. We also were able to avoid kubectl and other imperative logic inside our yaml. While there is more to what can be achieved via d-operators this article shows an approach to re-imagine handling infrastructure using Kubernetes. In other words, it pays to think like Kubernetes (read pure declarations) when operating on Kubernetes.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>testing</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
