<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://www.youdidwhatwithtsql.com/feed.xml" rel="self" type="application/atom+xml" /><link href="http://www.youdidwhatwithtsql.com/" rel="alternate" type="text/html" /><updated>2026-01-27T19:15:22+00:00</updated><id>http://www.youdidwhatwithtsql.com/feed.xml</id><title type="html">Rhys Campbell</title><subtitle>This is the personal technical blog of Rhys Campbell</subtitle><entry><title type="html">Get Kubernetes Pod secrets with curl and the Service Account token</title><link href="http://www.youdidwhatwithtsql.com/kubernetes-pod-curl-get-secrets" rel="alternate" type="text/html" title="Get Kubernetes Pod secrets with curl and the Service Account token" /><published>2026-01-27T19:00:00+00:00</published><updated>2026-01-27T19:00:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/kubernetes-pod-curl-get-secrets</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/kubernetes-pod-curl-get-secrets"><![CDATA[<p>Here’s a simple explainer for how to access <a href="https://kubernetes.io/docs/concepts/configuration/secret/">secrets</a> a Kubernetes <a href="https://kubernetes.io/docs/concepts/workloads/pods/">Pod</a> is allowed to access with its default service account.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">--header</span> <span class="s2">"Authorization: Bearer </span><span class="si">$(</span><span class="nb">cat</span> /var/run/secrets/kubernetes.io/serviceaccount/token<span class="si">)</span><span class="s2">"</span> <span class="nt">--cacert</span> /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes/api/v1/namespaces/restricted/secrets
</code></pre></div></div>

<ul>
  <li>–header - We set an Authorization header with the token for the service account.</li>
  <li>–cacert - We also use the ca.crt file provided by the serviceaccount secret</li>
  <li>kubernetes - The host part of the url is the Kubernetes API service. You could also use the service ClusterIP if DNS isn’t working.</li>
  <li>restricted/ - This part of the path is the namespace you wish to access</li>
  <li>secrets/ - This is the object type you want to access</li>
</ul>

<p>To get a specific secret by name…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">--header</span> <span class="s2">"Authorization: Bearer </span><span class="si">$(</span><span class="nb">cat</span> /var/run/secrets/kubernetes.io/serviceaccount/token<span class="si">)</span><span class="s2">"</span> <span class="nt">--cacert</span> /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes/api/v1/namespaces/restricted/secrets/mySecret
</code></pre></div></div>

<ul>
  <li>mySecret is the specific name of the secret you wish to access.</li>
</ul>]]></content><author><name></name></author><category term="kubernetes" /><category term="secrets" /><category term="pods" /><category term="serviceaccounts" /><category term="curl" /><category term="kubernetes" /><category term="secrets" /><category term="pods" /><category term="serviceaccounts" /><category term="curl" /><summary type="html"><![CDATA[Here’s a simple explainer for how to access secrets a Kubernetes Pod is allowed to access with its default service account.]]></summary></entry><entry><title type="html">kubectl apply Vs kubectl create</title><link href="http://www.youdidwhatwithtsql.com/kubernetes-kubectl-apply-vs-create" rel="alternate" type="text/html" title="kubectl apply Vs kubectl create" /><published>2025-03-02T19:00:00+00:00</published><updated>2025-03-02T19:00:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/kubernetes-kubectl-apply-vs-create</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/kubernetes-kubectl-apply-vs-create"><![CDATA[<p>What’s the difference between <code class="language-plaintext highlighter-rouge">kubectl apply</code> and <code class="language-plaintext highlighter-rouge">kubectl create</code>?</p>

<p>There’s already a whole bunch of good explainers…</p>

<ul>
  <li><a href="https://www.baeldung.com/ops/kubectl-apply-create">Difference Between kubectl apply and kubectl create</a></li>
  <li><a href="https://stackoverflow.com/questions/47369351/kubectl-apply-vs-kubectl-create">Obligatory Stackoverflow thread</a></li>
  <li><a href="https://www.youtube.com/watch?v=oCl882Q-Lnw">YouTube Explainer</a></li>
</ul>

<p>But what, for example, assuming none of the K8s resources defined in the file exist, would the difference between…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create <span class="nt">-f</span> https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml
</code></pre></div></div>

<p>and</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl apply <span class="nt">-f</span> https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml
</code></pre></div></div>

<p>be? We should end up with the same result right? Sadly, this is not the case. The apply command will result in a failed deployment and report the following error…</p>

<p>`
The CustomResourceDefinition “installations.operator.tigera.io” is invalid: metadata.annotations: Too long: must have at most 262144 bytes
`</p>

<p>There’s a <a href="https://github.com/projectcalico/calico/issues/7826">Github thread going into detail</a> about this but basically <code class="language-plaintext highlighter-rouge">kubectl apply</code> should not be used as it was not designed to handle large resources. For [Calico] we should use <code class="language-plaintext highlighter-rouge">kubectl create</code> on deployment and <code class="language-plaintext highlighter-rouge">kubectl replace</code> on upgrade to handle this issue.</p>]]></content><author><name></name></author><category term="kubernetes" /><category term="kubectl" /><category term="kubernetes" /><category term="kubectl" /><summary type="html"><![CDATA[What’s the difference between kubectl apply and kubectl create?]]></summary></entry><entry><title type="html">CKA Exam Command Shortcuts</title><link href="http://www.youdidwhatwithtsql.com/kubernetes-cka-cmd-shortcuts" rel="alternate" type="text/html" title="CKA Exam Command Shortcuts" /><published>2025-02-01T16:00:00+00:00</published><updated>2025-02-01T16:00:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/kubernetes-cka-cmd-shortcuts</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/kubernetes-cka-cmd-shortcuts"><![CDATA[<p>Run these commands in your shell to make them available (or put in <a href="https://www.digitalocean.com/community/tutorials/bashrc-file-in-linux">.bashrc</a>)…</p>

<table>
  <thead>
    <tr>
      <th>Command   Example</th>
      <th>Description</th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">alias k=kubectl</code></td>
      <td>-</td>
      <td>Create an alias for kubectl</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">export do="--dry-run=client -o yaml"</code></td>
      <td><code class="language-plaintext highlighter-rouge">k create deploy nginx --image=nginx $do</code></td>
      <td>Generate YAML for deployment without applying it</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">export now="--force --grace-period 0"</code></td>
      <td><code class="language-plaintext highlighter-rouge">k delete pod x $now</code></td>
      <td>Force delete a pod immediately</td>
    </tr>
  </tbody>
</table>

<p>These shortcuts can help speed up command execution during the CKA exam.</p>]]></content><author><name></name></author><category term="kubernetes" /><category term="cka" /><category term="kubernetes" /><category term="cka" /><summary type="html"><![CDATA[Run these commands in your shell to make them available (or put in .bashrc)…]]></summary></entry><entry><title type="html">kubernetes.io documentation - Useful links for the CKA</title><link href="http://www.youdidwhatwithtsql.com/kubernetes-docs-useful-links-cka" rel="alternate" type="text/html" title="kubernetes.io documentation - Useful links for the CKA" /><published>2025-01-15T06:00:00+00:00</published><updated>2025-01-15T06:00:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/kubernetes-docs-useful-links-cka</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/kubernetes-docs-useful-links-cka"><![CDATA[<p>For the <a href="https://training.linuxfoundation.org/certification/certified-kubernetes-administrator-cka/">CKA Exam</a> it’s useful to know the documentation well, and to be able to navigate quickly to appropriate code snippets, commands and the like. I present here a short list of links that may be useful, in the exam, for specific question categories.</p>

<ul>
  <li><a href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/">Bootstrapping clusters with kubeadm</a></li>
  <li><a href="https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/">Upgrading kubeadm clusters</a></li>
  <li><a href="https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/">Operating etcd clusters for Kubernetes</a>
    <ul>
      <li>See <a href="https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#securing-communication">Securing communication</a> for running commands with tls certs.</li>
    </ul>
  </li>
  <li>Configure POD Resources
    <ul>
      <li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/">Memory Resources</a></li>
      <li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/">CPU Resources</a></li>
    </ul>
  </li>
  <li>Volumes
    <ul>
      <li><a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/">PersistentVolumes</a></li>
      <li><a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims">PersistentVolumeClaims</a></li>
      <li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storage/">Configure a volume for a POD</a></li>
      <li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/">Configure a POD to use a PersistentVolume</a></li>
    </ul>
  </li>
  <li><a href="https://kubernetes.io/docs/reference/kubectl/">kubectl</a>
    <ul>
      <li><a href="https://kubernetes.io/docs/reference/kubectl/quick-reference/">kubectl quick reference</a></li>
      <li><a href="https://kubernetes.io/docs/reference/kubectl/jsonpath/">JSONPath support</a></li>
      <li><a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_events/">kubectl events</a></li>
      <li>For kubectl examples search the documentation site for examples, e.g. <code class="language-plaintext highlighter-rouge">kubectl create &lt;object&gt;</code>.
        <ul>
          <li><a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret/">kubectl create secret generic</a></li>
          <li><a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_create/kubectl_create_deployment/">kubectl create deployment</a></li>
          <li><a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_create/kubectl_create_configmap/">kubectl create configmap</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/">Taints and tolerations</a></li>
  <li><a href="https://kubernetes.io/docs/concepts/services-networking/ingress/">Ingress</a></li>
  <li><a href="https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests">Certificate Signing Requests</a>
    <ul>
      <li><a href="https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#normal-user">How to issue a certificate for a user</a></li>
    </ul>
  </li>
</ul>

<p>Found a pretty <a href="https://github.com/datmt/CKA-Examples/blob/master/resources/bookmark.html">Comprehensive CKA Bookmark List</a> during my googling.</p>

<p><a href="https://devopscube.com/cka-exam-study-guide/">CKA Exam Study Guide</a> _ Up to date guide with lots of useful links.</p>]]></content><author><name></name></author><category term="kubernetes" /><category term="cka" /><category term="kubernetes" /><category term="cka" /><summary type="html"><![CDATA[For the CKA Exam it’s useful to know the documentation well, and to be able to navigate quickly to appropriate code snippets, commands and the like. I present here a short list of links that may be useful, in the exam, for specific question categories.]]></summary></entry><entry><title type="html">Simple Kubernetes Network Policy to open up a pod port</title><link href="http://www.youdidwhatwithtsql.com/kubernetes-network-poliy-open-pod-port" rel="alternate" type="text/html" title="Simple Kubernetes Network Policy to open up a pod port" /><published>2024-12-03T20:16:00+00:00</published><updated>2024-12-03T20:16:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/kubernetes-network-poliy-open-pod-port</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/kubernetes-network-poliy-open-pod-port"><![CDATA[<p>Below shows a very simple Kubernetes <a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/">Network Policy</a> object. This simply opens up port 80 to the outside in a locked-down environment. The key tags to understand are <em>run</em>, which should be a label on the pod you wish to match, and the <em>ports</em> block under <em>ingress</em>. This should be a list specifiying the ports you wish to open.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="na">apiVersion</span><span class="pi">:</span> <span class="s">networking.k8s.io/v1</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">NetworkPolicy</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">ingress-to-nptest</span>
  <span class="na">namespace</span><span class="pi">:</span> <span class="s">default</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">podSelector</span><span class="pi">:</span>
    <span class="na">matchLabels</span><span class="pi">:</span>
      <span class="na">run</span><span class="pi">:</span> <span class="s">np-test-1</span>
  <span class="na">policyTypes</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">Ingress</span>
  <span class="na">ingress</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">ports</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">protocol</span><span class="pi">:</span> <span class="s">TCP</span>
      <span class="na">port</span><span class="pi">:</span> <span class="m">80</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="kubernetes" /><category term="kubernetes" /><category term="networkpolicy" /><summary type="html"><![CDATA[Below shows a very simple Kubernetes Network Policy object. This simply opens up port 80 to the outside in a locked-down environment. The key tags to understand are run, which should be a label on the pod you wish to match, and the ports block under ingress. This should be a list specifiying the ports you wish to open.]]></summary></entry><entry><title type="html">Get RDS Instance Type RAM in Terraform</title><link href="http://www.youdidwhatwithtsql.com/terraform-rds-get-ram-instance-type" rel="alternate" type="text/html" title="Get RDS Instance Type RAM in Terraform" /><published>2024-03-09T18:54:00+00:00</published><updated>2024-03-09T18:54:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/terraform-rds-get-ram-instance-type</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/terraform-rds-get-ram-instance-type"><![CDATA[<p>For a monitoring project I’m currently working on I need to get the amount of RAM an <a href="https://aws.amazon.com/rds/">RDS</a> Instance has. Unfortunately the <a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance">aws_db_instance</a> resource doesn’t expose this type of information to us. Terraform does however give us an <a href="https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external">external datasource</a> that we can take advantage of to provide the data.</p>

<p>First we need to write a wrapper script around an <a href="https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/index.html">aws ec2</a> command. We use the <a href="https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/describe-instance-types.html">describe-instance-types</a> sub-command to get the amount of RAM an instance has. This instance type information, as far as I know, is still relevant to RDS Instance, so it’s safe to use for this purpose. I’m also using the <a href="https://github.com/jqlang/jq">jq</a> command on the final line to return the data in a form Terraform can handle…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="nb">set</span> <span class="nt">-e</span>

<span class="nb">trap</span> <span class="s1">'echo "Failed describing instance type $instance_type exit code $?"'</span> ERR

<span class="nb">eval</span> <span class="s2">"</span><span class="si">$(</span>jq <span class="nt">-r</span> <span class="s1">'@sh "INSTANCE_TYPE=\(.instance_type)"'</span><span class="si">)</span><span class="s2">"</span>

<span class="nv">MB</span><span class="o">=</span><span class="si">$(</span>aws ec2 describe-instance-types <span class="nt">--instance-type</span> <span class="s2">"</span><span class="nv">$INSTANCE_TYPE</span><span class="s2">"</span> <span class="nt">--query</span> <span class="s2">"InstanceTypes[0].MemoryInfo.SizeInMiB"</span><span class="si">)</span>

jq <span class="nt">-n</span> <span class="nt">--arg</span> mb <span class="s2">"</span><span class="nv">$MB</span><span class="s2">"</span> <span class="s1">'{"MB":$mb}'</span>
</code></pre></div></div>

<p>The next important thing is to wrap this script up into a data resource using the external provider…</p>

<div class="language-terraform highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">data</span> <span class="s2">"external"</span> <span class="s2">"rds"</span> <span class="p">{</span>
  <span class="nx">program</span> <span class="p">=</span> <span class="p">[</span><span class="s2">"bash"</span><span class="p">,</span> <span class="s2">"</span><span class="k">${</span><span class="nx">path</span><span class="p">.</span><span class="k">module}</span><span class="s2">/bash/rds-ram-mb.sh"</span><span class="p">]</span>

  <span class="nx">query</span> <span class="p">=</span> <span class="p">{</span>
    <span class="nx">instance_type</span> <span class="p">=</span> <span class="nx">join</span><span class="p">(</span><span class="s2">"."</span><span class="p">,</span> <span class="p">[</span><span class="nx">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">,</span> <span class="nx">aws_db_instance</span><span class="p">.</span><span class="nx">rds1</span><span class="p">.</span><span class="nx">instance_class</span><span class="p">)[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">,</span> <span class="nx">aws_db_instance</span><span class="p">.</span><span class="nx">rds1</span><span class="p">.</span><span class="nx">instance_class</span><span class="p">)[</span><span class="mi">2</span><span class="p">]])</span>
  <span class="p">}</span>

  <span class="nx">depends_on</span> <span class="p">=</span> <span class="p">[</span><span class="nx">aws_db_instance</span><span class="p">.</span><span class="nx">rds1</span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We’re setting the instance_type variable using a few Terraform functions. Basically this turns <code class="language-plaintext highlighter-rouge">db.t3.micro</code> into <code class="language-plaintext highlighter-rouge">t3.micro</code>. This is the format that the aws cli tool in the wrapper script requires. Also note the use of <code class="language-plaintext highlighter-rouge">depends_on</code> as the RDS Instance needs to exist before the datasource is run.</p>

<p>With all that in place we can then reference the RAM value like so…</p>

<div class="language-terraform highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">output</span> <span class="s2">"instance_ram"</span> <span class="p">{</span>
  <span class="nx">value</span> <span class="p">=</span> <span class="k">data</span><span class="p">.</span><span class="nx">external</span><span class="p">.</span><span class="nx">rds</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">MB</span>
<span class="p">}</span>
</code></pre></div></div>

<p>There’s a working demo over at <a href="https://github.com/rhysmeister/aws-rds-external-data-source-demo">github/rhysmeister</a></p>

<p>After performing a <code class="language-plaintext highlighter-rouge">terraform apply</code> you’ll see the output variable is set to the instance type’s RAM in MB. In this case the RDS instance is a db.t3.micro and it has 1024MB of RAM.</p>

<p><img src="assets/2024/03/terraform-rds-ram-output.png" alt="Terraform RDS Instance RAM Output" /></p>]]></content><author><name></name></author><category term="terraform" /><category term="rds" /><category term="terraform" /><category term="rds" /><summary type="html"><![CDATA[For a monitoring project I’m currently working on I need to get the amount of RAM an RDS Instance has. Unfortunately the aws_db_instance resource doesn’t expose this type of information to us. Terraform does however give us an external datasource that we can take advantage of to provide the data.]]></summary></entry><entry><title type="html">Why doesn’t SELinux log a denied message?</title><link href="http://www.youdidwhatwithtsql.com/selinux-no-denied-entries-audit-log" rel="alternate" type="text/html" title="Why doesn’t SELinux log a denied message?" /><published>2024-01-30T16:46:00+00:00</published><updated>2024-01-30T16:46:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/selinux-no-denied-entries-audit-log</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/selinux-no-denied-entries-audit-log"><![CDATA[<p>If you’re wondering why SELinux is not printing a “denied” message in /var/log/audit/audit.log it’s probably because somebody wanted to hide it! Yes, it’s possible to prevent an SELinux module from logging a denied message. Disable this behaviour by executing the following command:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>semodule <span class="nt">--disable_dontaudit</span> <span class="nt">--build</span>
</code></pre></div></div>

<p>Re-enable again with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>semodule <span class="nt">--build</span>
</code></pre></div></div>

<p>For more consult the <a href="https://www.linux.org/docs/man8/semodule.html">semodule man page</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security-enhanced_linux/sect-security-enhanced_linux-fixing_problems-possible_causes_of_silent_denials">Possible Causes of Silent Denials</a></p>]]></content><author><name></name></author><category term="selinux" /><category term="linux" /><category term="selinux" /><category term="linux" /><summary type="html"><![CDATA[If you’re wondering why SELinux is not printing a “denied” message in /var/log/audit/audit.log it’s probably because somebody wanted to hide it! Yes, it’s possible to prevent an SELinux module from logging a denied message. Disable this behaviour by executing the following command:]]></summary></entry><entry><title type="html">Terraform will damage your Computer</title><link href="http://www.youdidwhatwithtsql.com/macos-terraform-damage-computer" rel="alternate" type="text/html" title="Terraform will damage your Computer" /><published>2023-05-15T16:59:00+00:00</published><updated>2023-05-15T16:59:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/macos-terraform-damage-computer</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/macos-terraform-damage-computer"><![CDATA[<p>Today I experienced the following error on my Intel MacBook Pro when attempting to run <a href="https://www.terraform.io/">Terraform</a>…</p>

<p><img src="assets/2023/05/macos-terraform-damage-computer.png" alt="MacOS Terraform will damage your computer " /></p>

<p>The equivalent English error message is “Terraform will damage your computer. You should move it to the Trash.”. Hashicorp have cycled their keys used to sign their packages/executables. You can read more about that at the link below. I resolved it by simply removing the old terraform binary and replacing it with a newer version…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>which terraform
<span class="nb">sudo rm</span> /usr/local/bin/terraform
wget https://releases.hashicorp.com/terraform/1.4.6/terraform_1.4.6_darwin_amd64.zip
unzip terraform_1.4.6_darwin_amd64.zip
<span class="nb">sudo mv </span>terraform /usr/local/bin
terraform version
</code></pre></div></div>

<ul>
  <li>Further useful links
    <ul>
      <li><a href="https://support.hashicorp.com/hc/en-us/articles/13177506317203">HashiCorp Response to CircleCI</a></li>
      <li><a href="https://stackoverflow.com/questions/76129509/terraform-will-damage-your-computer-on-macos-intel">Stack Overflow - Terraform will damage your Computer</a></li>
      <li><a href="https://www.storagetutorials.com/solved-terraform-will-damage-your-computer/">Terraform will damage your Computer</a></li>
    </ul>
  </li>
</ul>]]></content><author><name></name></author><category term="terraform" /><category term="macos" /><category term="terraform" /><category term="macos" /><summary type="html"><![CDATA[Today I experienced the following error on my Intel MacBook Pro when attempting to run Terraform…]]></summary></entry><entry><title type="html">Generate BATS Unit Tests with ChatGPT</title><link href="http://www.youdidwhatwithtsql.com/generate-unit-tests-chatgpt" rel="alternate" type="text/html" title="Generate BATS Unit Tests with ChatGPT" /><published>2023-01-07T13:27:00+00:00</published><updated>2023-01-07T13:27:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/generate-unit-tests-chatgpt</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/generate-unit-tests-chatgpt"><![CDATA[<p>Of course everyone has now heard about <a href="https://openai.com/blog/chatgpt/">ChatGPT</a>. I’ve seen a few posts on <a href="https://www.linkedin.com">LinkedIn</a> where people have used it to generate code. I thought I’d have a quick go at seeing if ChatGPT would generate useful units tests. So I gave it the following bash function…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mytest <span class="o">()</span> <span class="o">{</span>
        <span class="nv">var</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span><span class="p">;</span>
        <span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="nv">$var</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"rhys"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
                </span><span class="nb">echo</span> <span class="s2">"Hello Rhys"</span>
        <span class="k">else
                </span><span class="nb">echo</span> <span class="s2">"Hello </span><span class="nv">$var</span><span class="s2">"</span>
        <span class="k">fi</span><span class="p">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>and I asked it…</p>

<blockquote>
  <p>Hello, Can you write me some test cases for this Bash function?</p>
</blockquote>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Sure! Here are some test cases for the Bash function:

    Test that the function correctly prints "Hello Rhys" when given "rhys" as an input:

test "rhys"

Expected output:

Hello Rhys

    Test that the function correctly prints "Hello [name]" when given a name other than "rhys" as an input:

test "John"

Expected output:

Hello John

    Test that the function correctly handles an empty input:

test ""

Expected output:

Hello

    Test that the function correctly handles inputs with spaces:

test "John Smith"

Expected output:

Hello John Smith

    Test that the function correctly handles inputs with special characters:

test "!@#$%^&amp;*()"

Expected output:

Hello !@#$%^&amp;*()
</code></pre></div></div>

<p>OK, pretty good but let’s try something a little more practical. I like using the <a href="https://github.com/sstephenson/bats">BATS Unit Testing Framework</a> for bash. So I asked it to generate the tests again using BATS…</p>

<blockquote>
  <p>Can you write the same test cases using the BATS framework?</p>
</blockquote>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Sure! Here are the test cases written using the BATS (Bash Automated Testing System) framework:
</code></pre></div></div>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Test that the function correctly prints "Hello Rhys" when given "rhys" as an input</span>
@test <span class="s2">"mytest prints 'Hello Rhys' when given 'rhys' as an input"</span> <span class="o">{</span>
  run mytest <span class="s2">"rhys"</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$status</span><span class="s2">"</span> <span class="nt">-eq</span> 0 <span class="o">]</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$output</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"Hello Rhys"</span> <span class="o">]</span>
<span class="o">}</span>

<span class="c"># Test that the function correctly prints "Hello [name]" when given a name other than "rhys" as an input</span>
@test <span class="s2">"mytest prints 'Hello [name]' when given a name other than 'rhys' as an input"</span> <span class="o">{</span>
  run mytest <span class="s2">"John"</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$status</span><span class="s2">"</span> <span class="nt">-eq</span> 0 <span class="o">]</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$output</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"Hello John"</span> <span class="o">]</span>
<span class="o">}</span>

<span class="c"># Test that the function correctly handles an empty input</span>
@test <span class="s2">"mytest handles an empty input"</span> <span class="o">{</span>
  run mytest <span class="s2">""</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$status</span><span class="s2">"</span> <span class="nt">-eq</span> 0 <span class="o">]</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$output</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"Hello"</span> <span class="o">]</span>
<span class="o">}</span>

<span class="c"># Test that the function correctly handles inputs with spaces</span>
@test <span class="s2">"mytest handles inputs with spaces"</span> <span class="o">{</span>
  run mytest <span class="s2">"John Smith"</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$status</span><span class="s2">"</span> <span class="nt">-eq</span> 0 <span class="o">]</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$output</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"Hello John Smith"</span> <span class="o">]</span>
<span class="o">}</span>

<span class="c"># Test that the function correctly handles inputs with special characters</span>
@test <span class="s2">"mytest handles inputs with special characters"</span> <span class="o">{</span>
  run mytest <span class="s2">"!@#</span><span class="nv">$%</span><span class="s2">^&amp;*()"</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$status</span><span class="s2">"</span> <span class="nt">-eq</span> 0 <span class="o">]</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$output</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"Hello !@#</span><span class="nv">$%</span><span class="s2">^&amp;*()"</span> <span class="o">]</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here’s the output when I run those tests…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ✓ mytest prints 'Hello Rhys' when given 'rhys' as an input 
 ✓ mytest prints 'Hello [name]' when given a name other than 'rhys' as an input 
 ✗ mytest handles an empty input
   (in test file tests.bats, line 20)
     `[ "$output" = "Hello" ]' failed
 ✓ mytest handles inputs with spaces 
 ✓ mytest handles inputs with special characters 

5 tests, 1 failure
</code></pre></div></div>

<p>One test is failing because it doesn’t account for the fact that whitespace will be returned in the output when an empty input is provided. Let’s ask ChatGPT to correct this…</p>

<blockquote>
  <p>In the test labelled “mytest handles an empty input” you don’t take account of that fact that whitespace will be returned in the output. Therefore the test will always fail. Can you correct this please?”</p>
</blockquote>

<p>It provided the following code…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Test that the function correctly handles an empty input</span>
@test <span class="s2">"mytest handles an empty input"</span> <span class="o">{</span>
  run mytest <span class="s2">""</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$status</span><span class="s2">"</span> <span class="nt">-eq</span> 0 <span class="o">]</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$output</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"Hello "</span> <span class="o">]</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Now all the tests run correctly…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ✓ mytest prints 'Hello Rhys' when given 'rhys' as an input 
 ✓ mytest prints 'Hello [name]' when given a name other than 'rhys' as an input 
 ✓ mytest handles an empty input 
 ✓ mytest handles inputs with spaces 
 ✓ mytest handles inputs with special characters 

5 tests, 0 failures
</code></pre></div></div>

<p>Now I am not surprised that ChatGPT made a mistake with the whitespace but, I am pretty impressed it could fix it, once I pointed out that mistake!</p>

<p>What else have I asked ChatGPT?</p>

<ul>
  <li>Hi ChatGPT, can you generate me an Ansible Playbook to install MariaDB on a CentOS system with some common settings changed?</li>
  <li>Can you do the same thing but for a Debian based system?</li>
  <li>Can you generate a testinfa class to validate a MariaDB server is running and the root login is secured?</li>
  <li>Can you also generate a test that will check the MariaDB server is listening on 3306?</li>
</ul>

<p>It gave pretty good answers for all of these, although probably not 100% production ready, it certainly provided a good starting point and takes out some of the tediousness of some of these tasks!</p>]]></content><author><name></name></author><category term="chatgpt" /><category term="unit tests" /><category term="bash" /><category term="chatgpt" /><category term="unit tests" /><category term="bash" /><category term="bats" /><summary type="html"><![CDATA[Of course everyone has now heard about ChatGPT. I’ve seen a few posts on LinkedIn where people have used it to generate code. I thought I’d have a quick go at seeing if ChatGPT would generate useful units tests. So I gave it the following bash function…]]></summary></entry><entry><title type="html">Install PyLint on Python 2.7</title><link href="http://www.youdidwhatwithtsql.com/install-pylint-python2.7" rel="alternate" type="text/html" title="Install PyLint on Python 2.7" /><published>2022-06-25T12:18:00+00:00</published><updated>2022-06-25T12:18:00+00:00</updated><id>http://www.youdidwhatwithtsql.com/install-pylint-python2.7</id><content type="html" xml:base="http://www.youdidwhatwithtsql.com/install-pylint-python2.7"><![CDATA[<p>When installing <a href="https://pypi.org/project/pylint/">pylint</a> with Python 2.7 you may encounter the following problem…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Collecting pylint
  Downloading https://files.pythonhosted.org/packages/d9/99/2958da59c0203fe40670bcbce52043b4db4e74ef0db14ab59d5b66c0ba6c/pylint-2.14.3.tar.gz (393kB)
  Running setup.py (path:/tmp/pip-build-VElRHY/pylint/setup.py) egg_info for package pylint produced metadata for project name unknown. Fix your #egg=pylint fragments.
Installing collected packages: unknown
  Running setup.py install for unknown: started
    Running setup.py install for unknown: finished with status 'done'
Successfully installed unknown-0.0.0
You are using pip version 8.1.2, however version 22.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
</code></pre></div></div>

<p>Note the package name of “unknown” in the output. Python 2.7 is no longer supported by newer versions of PyLint (from V2) and its dependencies. If you’re not in the position to update Python then the following fix should work…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install 'pylint==1.9.*' 'configparser==4.0.*' 'isort==4.3.*' 'lazy-object-proxy==1.6.*'
</code></pre></div></div>]]></content><author><name></name></author><category term="pylint" /><category term="python" /><category term="pylint" /><category term="python" /><summary type="html"><![CDATA[When installing pylint with Python 2.7 you may encounter the following problem…]]></summary></entry></feed>