<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Pete Bowden's Blog]]></title><description><![CDATA[Pete Bowden's Blog]]></description><link>https://blog.pete.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 02 Jun 2026 11:11:41 GMT</lastBuildDate><atom:link href="https://blog.pete.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Kubernetes Advanced Deployment Strategy - Part 3]]></title><description><![CDATA[A quick update regarding my last post: while I didn't discuss services and routes in detail, I wanted to address how Kubernetes routes traffic to the isolated Pod. I only had one label as part of the Deployment in my previous post, specifically app: ...]]></description><link>https://blog.pete.dev/kubernetes-advanced-deployment-strategy-part-3</link><guid isPermaLink="true">https://blog.pete.dev/kubernetes-advanced-deployment-strategy-part-3</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[deployment]]></category><category><![CDATA[containers]]></category><dc:creator><![CDATA[Pete Bowden]]></dc:creator><pubDate>Mon, 14 Mar 2022 23:16:42 GMT</pubDate><content:encoded><![CDATA[<p>A quick update regarding my last post: while I didn't discuss services and routes in detail, I wanted to address how Kubernetes routes traffic to the isolated Pod. I only had one label as part of the Deployment in my previous post, specifically <code>app: echoapp</code>. Only having one label will cause the Kubernetes service and, therefore, the route to stop sending traffic to that Pod when we modify the Pod to remove that label. </p>
<p>Services use labels to determine what Pods should be handling traffic. As an example, this is a Service definition we could use for our Deployment:</p>
<pre><code><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">echo-service</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">echoapp</span>    
  <span class="hljs-attr">ports:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">http</span>
      <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>
      <span class="hljs-attr">port:</span> <span class="hljs-number">8080</span>
      <span class="hljs-attr">targetPort:</span> <span class="hljs-number">8080</span>
</code></pre><p>Notice the selector field also specifies the same <code>app: echoapp</code> label. If we modify our Pod to remove this label, the Service will no longer send traffic to that Pod. In some cases, this behavior can be desired; you may want to allow a pod to finish processing any inflight transactions but not send any more work. But in the scenario we discussed in my first post, we would want the Service to continue to send traffic to the isolated Pod (at least at first, more on this later).</p>
<p>There's a straightforward fix: Add another label to our Deployment and reference it in the Service selector. In this example, I added the label "backend: default".</p>
<pre><code><span class="hljs-string">deployment.yaml</span>
<span class="hljs-string">...</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">echoapp</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">echoapp</span>
        <span class="hljs-attr">backend:</span> <span class="hljs-string">default</span>
</code></pre><p>We can now reference this label in our Service:</p>
<pre><code><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">echo-service</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-comment">#app: echoapp</span>
    <span class="hljs-attr">backend:</span> <span class="hljs-string">default</span>
  <span class="hljs-attr">ports:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">http</span>
      <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>
      <span class="hljs-attr">port:</span> <span class="hljs-number">8080</span>
      <span class="hljs-attr">targetPort:</span> <span class="hljs-number">8080</span>
</code></pre><p>Applying these changes will allow the isolated Pod to continue to receive traffic.</p>
<p>We can use this same concept to stop traffic from being sent to the isolated Pod once we're ready to shut it down. Edit the isolated Pod to remove the "backend: default" label. The Pod will no longer be part of the Service, and it will no longer receive traffic. Once the application running in the Pod has finished processing, the Pod can be safely stopped. This technique can be used on any Pod even if it's not isolated from a Replica Set.</p>
]]></content:encoded></item><item><title><![CDATA[Kubernetes Advanced Deployment Strategy - Part 2]]></title><description><![CDATA[In my last post, I talked about isolating a pod to solve a complicated deployment strategy. In this post, I will walk you through isolating a pod from a Replica Set and then adding it back to its original Replica Set. Replica Sets ensure that the des...]]></description><link>https://blog.pete.dev/kubernetes-advanced-deployment-strategy-part-2</link><guid isPermaLink="true">https://blog.pete.dev/kubernetes-advanced-deployment-strategy-part-2</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[deployment]]></category><dc:creator><![CDATA[Pete Bowden]]></dc:creator><pubDate>Wed, 09 Mar 2022 20:15:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/8YjiX21aPkY/upload/v1646856856510/VDWFKzlR3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my <a target="_blank" href="https://blog.pete.dev/kubernetes-advanced-deployment-strategy-part-1">last post</a>, I talked about isolating a pod to solve a complicated deployment strategy. In this post, I will walk you through isolating a pod from a Replica Set and then adding it back to its original Replica Set. Replica Sets ensure that the desired number of pods matches the current Deployment. In this post, I will be using OpenShift and its related <code>oc</code> CLI tool. Everything in this post applies to Kubernetes in general, and you can swap <code>oc</code> for <code>kubectl</code>.</p>
<p> Labels are a huge part of how Kubernetes components interact. When you create a Deployment, you may have noticed that you set different labels and label selectors. The Replica Set uses these labels to determine which Pods it's responsible for managing. For example, in the below snippet, the Replica Set will track pods with a label <code>echoapp</code> defined under the configuration's <code>selector</code> area.</p>
<pre><code><span class="hljs-string">...</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">echoapp</span>
  <span class="hljs-attr">template:</span>  
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">echoapp</span>
<span class="hljs-string">...</span>
</code></pre><p>We can use this to our advantage to isolate a specific pod by modifying the labels attached to that Pod. By doing an <code>oc edit</code> and removing the label <code>app: echoapp</code> from the Pod, the Replica Set will no longer consider this Pod part of its managed Pods. Since as far as the Replica Set is concerned, there is now one fewer Pod than the Deployment specifies, so it spins up another Pod.</p>
<p>Let's step through an example. We'll be using this Deployment if you want to try this at home:</p>
<pre><code><span class="hljs-attribute">apiVersion</span>: apps/v1
<span class="hljs-attribute">kind</span>: Deployment
<span class="hljs-attribute">metadata</span>:
  <span class="hljs-attribute">name</span>: echoapp-deployment
  <span class="hljs-attribute">labels</span>:
    <span class="hljs-attribute">app</span>: echoapp
<span class="hljs-attribute">spec</span>:
  <span class="hljs-attribute">replicas</span>: <span class="hljs-number">3</span>
  <span class="hljs-attribute">selector</span>:
    <span class="hljs-attribute">matchLabels</span>:
      <span class="hljs-attribute">app</span>: echoapp
  <span class="hljs-attribute">template</span>:  
    <span class="hljs-attribute">metadata</span>:
      <span class="hljs-attribute">labels</span>:
        <span class="hljs-attribute">app</span>: echoapp
    <span class="hljs-attribute">spec</span>:
     <span class="hljs-attribute">containers</span>:
        - <span class="hljs-attribute">name</span>: echo 
          <span class="hljs-attribute">image</span>: mendhak/<span class="hljs-attribute">http-https-echo</span>:<span class="hljs-number">23</span>
          <span class="hljs-attribute">ports</span>:
            - <span class="hljs-attribute">name</span>: http
              <span class="hljs-attribute">protocol</span>: TCP
              <span class="hljs-attribute">containerPort</span>: <span class="hljs-number">8080</span>
            - <span class="hljs-attribute">name</span>: https
              <span class="hljs-attribute">protocol</span>: TCP
              <span class="hljs-attribute">containerPort</span>: <span class="hljs-number">8443</span>
          <span class="hljs-attribute">resources</span>:
            <span class="hljs-attribute">limits</span>:
              <span class="hljs-attribute">memory</span>: <span class="hljs-string">"128Mi"</span>
              <span class="hljs-attribute">cpu</span>: <span class="hljs-string">"500m"</span>
</code></pre><p>Assuming you've saved this Deployment as <code>deployment.yaml</code>, you can deploy this configuration via an <code>oc apply -f deployment.yaml</code>.</p>
<p>Once you do so, running an <code>oc get pods</code> should give you an output similar to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646856453185/I-uAI9e-z.png" alt="Screenshot from 2022-03-08 17-04-25.png" /></p>
<p>If you edit one of the running pods with <code>oc edit &lt;podname&gt;</code>, you can remove the <code>app: echoapp</code> label from the Pod. Once you save the change, you should see a fourth Pod spun up by the Replication Controller.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646856617037/tkCdp8reQ.png" alt="Container Creating.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646856628786/WYX60Uz97.png" alt="Four Containers Running.png" /></p>
<p>Conversely, if we edit the Pod and add the label back to the Pod, the Replication Set will manage that Pod again. In this case, we will now have four running Pods when the Deployment calls for three. The Replication Set will now spin one of those Pods back down.</p>
<p>If you repeat the above steps while using the watch option of oc (<code>oc get pods -w</code>), you can watch the changes in real-time. I removed the label from a Pod and then added it back in the below example. You can see the Pod change states from being created, running, and finally, terminated in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646856669369/Yktn2TOAe.png" alt="FLow 2.png" /></p>
<p>One more thing of note, if you isolate a Pod using the above procedure, deleting the Deployment will not clean up the Pod. This behavior is expected since the Replication Set is not managing the lifecycle of the isolated Pod. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646856740731/6c0BSEaTE.png" alt="Pod Remaining after Deployment Deleted.png" /></p>
<p>I hope this post gives some insight into how Replication Sets function and how easmorey it is to isolate a Pod from a Replication Set. In a future post, I will introduce you to Kubernetes Controllers / Operators and discuss how to write an Operator that can automatically isolate a Pod during a maintenance window.</p>
]]></content:encoded></item><item><title><![CDATA[Kubernetes Advanced Deployment Strategy - Part 1]]></title><description><![CDATA[A customer presented me with a use case concerning an application they run on OpenShift. They have an application that requires at least five instances running at all times to handle their current traffic load. Unfortunately, they couldn't permanentl...]]></description><link>https://blog.pete.dev/kubernetes-advanced-deployment-strategy-part-1</link><guid isPermaLink="true">https://blog.pete.dev/kubernetes-advanced-deployment-strategy-part-1</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[deployment]]></category><category><![CDATA[containers]]></category><dc:creator><![CDATA[Pete Bowden]]></dc:creator><pubDate>Mon, 07 Mar 2022 23:26:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/WHPsxhB4mWQ/upload/v1646695457653/Bz1SyNKfM.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A customer presented me with a use case concerning an application they run on OpenShift. They have an application that requires at least five instances running at all times to handle their current traffic load. Unfortunately, they couldn't permanently scale this service beyond five pods. However, they still wanted to ensure that they would have enough capacity for the application to continue handling traffic during upgrades. They ran into the issue that the application takes a significant amount of time to come back online and see a performance impact during that restart time. They wanted to know if there might be a way to start a supplemental pod preemptively before Kubernetes shut down the existing pod. In this blog post, I will present several different options for solving this problem.</p>
<p>For those of you that may not be familiar with the internals of Kubernetes, I'd like to provide a little bit of background. In Kubernetes, when a deployment is created, a corresponding replica set is made for that deployment. This replica set monitors the number of pods that are currently running. If that number differentiates from the desired quantity, the replication controller will request a new pod either be created or destroyed. The replica set does not determine which node to place the pod; it simply requests that one is created. The scheduler in Kubernetes determines and deploys the pod on a node.</p>
<p>When you need to restart a worker node for maintenance (or for any reason), the draining process terminates pods on that node as part of the shutdown process. When the draining process removes that pod, Kubernetes will inform the pod's corresponding replica set that the current state does not match the desired state. The replica set will then request a new pod be deployed somewhere else on the cluster.
As mentioned earlier, what options do we have to alleviate this issue and prevent having any fewer than five pods running during maintenance?</p>
<p>One approach that I've seen discussed is to increase the current replica set count by one and then reduce it once the node has restarted. This change will cause Kubernetes to schedule an additional pod somewhere in the cluster. Once this pod is up and running, you can go ahead and shut down the node, which will kill the running pod on the node. But as you may have guessed, this will cause the replica set to detect that now there are only five pods instead of six, and it will attempt to spin up a sixth pod when we only need five. Of course, you can reduce your replica set count from six to five, which will cause the replica set to terminate a pod. Hopefully, the pod picked for termination is the pod the scheduler just created. Unfortunately, there is no guarantee which pod the Replica Set will select for termination.</p>
<p>Furthermore, I'm not too fond of this approach as it causes quite a bit of churn in the cluster by quickly scaling up and then scaling back down when you don't need the sixth pod. If there are pods with priorities, this could cause other unrelated pods to be deleted during the scale-up and down. So for all the reasons mentioned above, I'm not too fond of this approach.</p>
<p>Another technique would be to use a custom resource definition (CRD) by creating a CRD and then an underline controller (aka operator) to manage any created custom resources. In this case, the operator would only be slightly modifying how the standard deployment controller works, which means reimplementing a lot of code that the engineers of Kubernetes maintain. It's a lot of work to maintain a codebase for something that should be possible to do right out of the box.</p>
<p>Maybe we could write a custom scheduler. The schedule is responsible for placing pods on nodes based on various conditions. It might be possible to write a custom scheduler that would take advantage of knowing that nodes are marked as unschedulable and reschedule the pod somewhere else. One problem with doing so is that it breaks the separation of concerns model in Kubernetes; a deployment creates replica sets, which creates pods, which in turn the scheduler places on a node. The Kubernetes model uses these abstractions, and if we deviate from that model, we break Kubernetes operating concepts. And if somehow we didn't, we would still end up in a mess trying to figure out what Kubernetes component owns which resource. So again, using a custom scheduler isn't the right solution.</p>
<p>So, the best solution it's relatively simple. Pods managed by a replica set can be removed from the replica set and, therefore, no longer under the replica set's control. The Kubernetes documentation talks about using this feature to isolate a pod for data recovery or debugging purposes, and we're going to use it to solve our use case. Removing a pod from the replica set isolates it but does not cause it to terminate. When we remove the pod from the replica set, Kubernetes notifies the replica set that the current state does not match the desired state, and the replica set will spin up an additional pod. We can allow our orphaned sixth pod to continue to run and process data while the new pod managed to the replica set comes online. Once that pod is online, we can cleanly shut down the orphaned pod. Since the replica set is not responsible for the orphaned pod, the replica set will take no additional actions. A sysadmin can use pod isolation to spin up an extra pod during maintenance to handle the workload without losing capacity or performance.</p>
<p>For my next blog post, I'll walk through the above scenario with examples on how to manually make this happen. And in a future post, I'll discuss how we could automate this process using an operator.
Are there other solutions to this problem that I did not present? Please let me know in the comments below.</p>
]]></content:encoded></item><item><title><![CDATA[Extracting Data from the Ansible Tower API]]></title><description><![CDATA[Ansible Tower exposes a comprehensive RESTful API. In fact, Tower is first implemented as an API and then the UI is written to consume that API; anything that can be done from the UI can also be done by making calls to the API. In this article I will...]]></description><link>https://blog.pete.dev/extracting-data-from-the-ansible-tower-api</link><guid isPermaLink="true">https://blog.pete.dev/extracting-data-from-the-ansible-tower-api</guid><category><![CDATA[ansible]]></category><dc:creator><![CDATA[Pete Bowden]]></dc:creator><pubDate>Fri, 04 Mar 2022 19:50:19 GMT</pubDate><content:encoded><![CDATA[<p>Ansible Tower exposes a comprehensive RESTful API. In fact, Tower is first implemented as an API and then the UI is written to consume that API; anything that can be done from the UI can also be done by making calls to the API. In this article I will show you how to use this API to extract job information from Tower. As a sample use case, we’re going to capture details about specific jobs and store them externally to Tower. This sort of use case might come up as part of storing jobs for an audit purpose.</p>
<p>It’s easy to get started with the Tower API and there is documentation for the API running right alongside the API. If you have access to a Tower deployment you can find a browsable API by going to https://{your_tower_hostname}/api/v2 On this page you can browse the API and interact directly with the API from your browser. In our sample use case, we want to find and extract data related to jobs. </p>
<p>To do this we will first need to query for a list of jobs. We can do that by first quering the /api/v2/jobs/ endpoint. This endpoint contains information about all jobs that have been executed on the Tower node. In the sample code below, we simply iterate over every single job that has been executed on the node and then save the job IDs into a list. From there we can iterate over that list and query the /api/v2/jobs/{job_id}/job_events/ endpoint to gather data about the executed job. From there we can write this information to an archive for storage.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">requests</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">requests</span>.<span class="hljs-title">packages</span>.<span class="hljs-title">urllib3</span>.<span class="hljs-title">exceptions</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">InsecureRequestWarning</span>

<span class="hljs-title">requests</span>.<span class="hljs-title">packages</span>.<span class="hljs-title">urllib3</span>.<span class="hljs-title">disable_warnings</span>(<span class="hljs-title">InsecureRequestWarning</span>)

# <span class="hljs-title">Defining</span> <span class="hljs-title">tower</span> <span class="hljs-title">host</span>, <span class="hljs-title">user</span> <span class="hljs-title">and</span> <span class="hljs-title">password</span> #<span class="hljs-title">IMPROVE</span>
<span class="hljs-title">tower_username</span> <span class="hljs-operator">=</span> <span class="hljs-string">'apiuser'</span>
<span class="hljs-title">tower_password</span> <span class="hljs-operator">=</span> <span class="hljs-string">'apiuserpassword'</span>
<span class="hljs-title">tower_url</span> <span class="hljs-operator">=</span> <span class="hljs-string">'https://tower.demo.com'</span>
<span class="hljs-title">request_url</span> <span class="hljs-operator">=</span> <span class="hljs-title">tower_url</span> <span class="hljs-operator">+</span> <span class="hljs-string">'/api/v2/jobs/'</span>



# <span class="hljs-title">Instantiate</span> <span class="hljs-title">an</span> <span class="hljs-title">empty</span> <span class="hljs-title">array</span> <span class="hljs-title">to</span> <span class="hljs-title">hold</span> <span class="hljs-title">Job</span> <span class="hljs-title">IDs</span>
<span class="hljs-title">jobs</span> <span class="hljs-operator">=</span> []

# <span class="hljs-title">Create</span> <span class="hljs-title">a</span> <span class="hljs-title">list</span> <span class="hljs-title">of</span> <span class="hljs-title">all</span> <span class="hljs-title">Job</span> <span class="hljs-title">IDS</span>
# <span class="hljs-title">Get</span> <span class="hljs-title">initial</span> <span class="hljs-title">list</span>, <span class="hljs-title">and</span> <span class="hljs-title">keep</span> <span class="hljs-title">going</span> <span class="hljs-title">through</span> <span class="hljs-title">the</span> <span class="hljs-title">job</span> <span class="hljs-title">list</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">long</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-string">'next'</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">defined</span>
<span class="hljs-title"><span class="hljs-keyword">while</span></span>(<span class="hljs-title">True</span>):
   <span class="hljs-title">response</span> <span class="hljs-operator">=</span> <span class="hljs-title">requests</span>.<span class="hljs-title">get</span>(<span class="hljs-title">request_url</span>, <span class="hljs-title">auth</span><span class="hljs-operator">=</span>(<span class="hljs-title">tower_username</span>, <span class="hljs-title">tower_password</span>), <span class="hljs-title">verify</span><span class="hljs-operator">=</span><span class="hljs-title">False</span>)
   <span class="hljs-title">jsonResponse</span> <span class="hljs-operator">=</span> <span class="hljs-title">response</span>.<span class="hljs-title">json</span>()

   <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">job</span> <span class="hljs-title">in</span> <span class="hljs-title">jsonResponse</span>[<span class="hljs-string">"results"</span>]:
       <span class="hljs-title">jobs</span>.<span class="hljs-title">append</span>(<span class="hljs-title">job</span>[<span class="hljs-string">"id"</span>])

   <span class="hljs-title"><span class="hljs-keyword">if</span></span> (<span class="hljs-title">jsonResponse</span>[<span class="hljs-string">"next"</span>] <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-title">None</span>):
       <span class="hljs-title"><span class="hljs-keyword">break</span></span>
   <span class="hljs-title"><span class="hljs-keyword">else</span></span>:
       <span class="hljs-title">request_url</span> <span class="hljs-operator">=</span> <span class="hljs-title">tower_url</span> <span class="hljs-operator">+</span> <span class="hljs-title">jsonResponse</span>[<span class="hljs-string">"next"</span>] 


# <span class="hljs-title">Iterate</span> <span class="hljs-title">over</span> <span class="hljs-title">the</span> <span class="hljs-title">Job</span> <span class="hljs-title">IDS</span> <span class="hljs-title">to</span> <span class="hljs-title">get</span> <span class="hljs-title">events</span>
<span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">jobid</span> <span class="hljs-title">in</span> <span class="hljs-title">jobs</span>:
   <span class="hljs-title">request_url</span> <span class="hljs-operator">=</span> <span class="hljs-title">tower_url</span> <span class="hljs-operator">+</span> <span class="hljs-string">'/api/v2/jobs/'</span> <span class="hljs-operator">+</span> <span class="hljs-title">str</span>(<span class="hljs-title">jobid</span>) <span class="hljs-operator">+</span> <span class="hljs-string">'/job_events/'</span>
   <span class="hljs-title">response</span> <span class="hljs-operator">=</span> <span class="hljs-title">requests</span>.<span class="hljs-title">get</span>(<span class="hljs-title">request_url</span>, <span class="hljs-title">auth</span><span class="hljs-operator">=</span>(<span class="hljs-title">tower_username</span>, <span class="hljs-title">tower_password</span>), <span class="hljs-title">verify</span><span class="hljs-operator">=</span><span class="hljs-title">False</span>)
   <span class="hljs-title">jsonResponse</span> <span class="hljs-operator">=</span> <span class="hljs-title">response</span>.<span class="hljs-title">json</span>()
   # <span class="hljs-title">Iterate</span> <span class="hljs-title">over</span> <span class="hljs-title">tasks</span>
   <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">task</span> <span class="hljs-title">in</span> <span class="hljs-title">jsonResponse</span>[<span class="hljs-string">"results"</span>]:
       <span class="hljs-title">print</span>(<span class="hljs-string">'do something for the tasks'</span>)
</code></pre>]]></content:encoded></item></channel></rss>