<?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: Frederick Ollinger</title>
    <description>The latest articles on DEV Community by Frederick Ollinger (@frederickollinger).</description>
    <link>https://dev.to/frederickollinger</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%2F881205%2F8e1eeb85-d2b9-4ed7-a168-40747f2a06c7.png</url>
      <title>DEV Community: Frederick Ollinger</title>
      <link>https://dev.to/frederickollinger</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/frederickollinger"/>
    <language>en</language>
    <item>
      <title>Kubernetes Delete Stuck Deployment</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Thu, 19 Feb 2026 18:29:50 +0000</pubDate>
      <link>https://dev.to/frederickollinger/kubernetes-delete-stuck-deployment-2336</link>
      <guid>https://dev.to/frederickollinger/kubernetes-delete-stuck-deployment-2336</guid>
      <description>&lt;p&gt;Use case is a Kubernetes deployment in a namespace, but you want to keep part of the deployment such as Persistent Volume Claims (PVC) and Secrets, but you want to remove everything else.&lt;/p&gt;

&lt;p&gt;In this example, my namespace is named "ns".&lt;/p&gt;

&lt;p&gt;Normally, you can do this with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, there are cases where the deployment gets stuck often when you are in a CrashBackoffLoop.&lt;/p&gt;

&lt;p&gt;In these cases, deleting your namespace is the shortest path.&lt;/p&gt;

&lt;p&gt;But this will not work if you have a situation like mine with PVC and so on as they live in our namespace.&lt;/p&gt;

&lt;p&gt;DO NOT DO THIS IF YOU WANT TO KEEP PVC AND SECRETS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete namespace ns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, I wrote a script which will delete all the things I want to remove but keep pvc and secrets. Feel free from the script other things you want to keep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# This script is intended to take down everything in otel except&lt;/span&gt;
&lt;span class="c"&gt;# the Persistent Storage&lt;/span&gt;

&lt;span class="nv"&gt;NS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning this will take down everything in the given namespace"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"PLEASE ONLY USES THIS IF YOU KNOW WHAT YOU ARE DOING"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; namespace_to_delete"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi


&lt;/span&gt;kubectl scale deployment &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt; &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
kubectl scale statefulset &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt; &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
kubectl delete configmap &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt;
kubectl delete daemonset &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt;
kubectl delete statefulset &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt;
kubectl delete serviceaccount &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt;
kubectl delete ingress &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt;
kubectl delete pod &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt;
kubectl delete service &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NS&lt;/span&gt;
&lt;span class="c"&gt;# helm uninstall helm_service -n $NS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this script as manual-delete-deployment.sh and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bash manual-deplete-deployment.sh ns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be sure to replace the helm_service with any helm services you have as they will often stay stuck as well.&lt;/p&gt;

&lt;p&gt;You can find them with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm list -n ns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check to ensure that your deployment is gone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get all -n ns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>terraform</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>C# HTTPS REST Connections Using Self-Signed TLS Certificates</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Wed, 25 Jun 2025 16:03:50 +0000</pubDate>
      <link>https://dev.to/frederickollinger/restsharp-c-https-rest-connections-using-self-signed-tls-certificates-1gjg</link>
      <guid>https://dev.to/frederickollinger/restsharp-c-https-rest-connections-using-self-signed-tls-certificates-1gjg</guid>
      <description>&lt;p&gt;&lt;a href="//Simple%20REST%20and%20HTTP%20API%20Client%20for%20.NET"&gt;RestSharp&lt;/a&gt; is a C# library for making client side &lt;a href="https://en.wikipedia.org/wiki/REST" rel="noopener noreferrer"&gt;REST&lt;/a&gt; connections to servers.&lt;/p&gt;

&lt;p&gt;It can use HTTP or HTTPS, but it does not seem to like self-signed certificates to connect to a server.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>rest</category>
      <category>tls</category>
      <category>security</category>
    </item>
    <item>
      <title>Getting Shell Access to a Kubernetes Container</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Fri, 30 May 2025 17:22:35 +0000</pubDate>
      <link>https://dev.to/frederickollinger/getting-shell-access-to-a-kubernetes-container-1okc</link>
      <guid>https://dev.to/frederickollinger/getting-shell-access-to-a-kubernetes-container-1okc</guid>
      <description>&lt;p&gt;Problem: You have a running Kubernetes deployment, and you want to examine inside a container so you need to get shell access.&lt;/p&gt;

&lt;p&gt;First find the pod that you are interested in.&lt;/p&gt;

&lt;p&gt;NOTE: If you are running in a namespace, you need to include that as part of your listing with the -n flag, if not, you can skip -n. In this case, we'll name our namespace: namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; namespace get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME      READY   STATUS    RESTARTS   AGE
fun-pod-0   1/1     Running   0          21h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To connect to fun-pod-0, we do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; pod/fun-pod-0 &lt;span class="nt"&gt;-n&lt;/span&gt; namespace &lt;span class="nt"&gt;--&lt;/span&gt; sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: That we use sh for our shell as it's found in most linux pods. But your milage may vary and you might want to use bash or even /bin/bash instead of sh depending upon what shell is installed and what path.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using a Self-Signed Certificate with Git Clone Https</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Thu, 14 Nov 2024 00:28:02 +0000</pubDate>
      <link>https://dev.to/frederickollinger/using-a-self-signed-certificate-with-git-clone-https-2m93</link>
      <guid>https://dev.to/frederickollinger/using-a-self-signed-certificate-with-git-clone-https-2m93</guid>
      <description>&lt;p&gt;Ever have a problem when you need to clone from a git repo with https, and it fails because you have a self signed certificate?&lt;/p&gt;

&lt;p&gt;Every other post tells you to "turn off security".&lt;/p&gt;

&lt;p&gt;Don't do that.&lt;/p&gt;

&lt;p&gt;First download the certificate with this script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/env bash&lt;/span&gt;

&lt;span class="c"&gt;# User Variables&lt;/span&gt;
&lt;span class="nv"&gt;API_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;example.gitlab.com &lt;span class="c"&gt;# could be an ip address&lt;/span&gt;
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;443
&lt;span class="nv"&gt;CRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret.crt

&lt;span class="nv"&gt;BEGIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-----BEGIN CERTIFICATE-----"&lt;/span&gt;
&lt;span class="nv"&gt;END&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-----END CERTIFICATE-----"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$BEGIN&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$CRT&lt;/span&gt;
&lt;span class="nb"&gt;echo &lt;/span&gt;quit | openssl s_client &lt;span class="nt"&gt;-showcerts&lt;/span&gt; &lt;span class="nt"&gt;-servername&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;API_HOST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-connect&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;API_HOST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s2"&gt;"/&lt;/span&gt;&lt;span class="nv"&gt;$BEGIN&lt;/span&gt;&lt;span class="s2"&gt;/,/&lt;/span&gt;&lt;span class="nv"&gt;$END&lt;/span&gt;&lt;span class="s2"&gt;/!d;//d"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$CRT&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$END&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$CRT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the script to download your certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;
./download-certificate.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now tell git where your certificate is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config --global http.sslCAInfo ~/secret.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;Now you should be able to use git clone with your https server without issues.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>git</category>
      <category>bash</category>
    </item>
    <item>
      <title>Deploy Postgresql with Helm</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Thu, 26 Sep 2024 21:54:12 +0000</pubDate>
      <link>https://dev.to/frederickollinger/deploy-postgresql-with-helm-1ifi</link>
      <guid>https://dev.to/frederickollinger/deploy-postgresql-with-helm-1ifi</guid>
      <description>&lt;p&gt;Helm is the package manager for deploying pre-built packages to Kubernetes.&lt;/p&gt;

&lt;p&gt;I found the Postgresql package here: &lt;a href="https://artifacthub.io/packages/helm/bitnami/postgresql" rel="noopener noreferrer"&gt;https://artifacthub.io/packages/helm/bitnami/postgresql&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the TL;DR&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;my-release oci://registry-1.docker.io/bitnamicharts/postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks like has issues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl describe pod my-release-postgresql-0


  Warning  FailedScheduling  2m33s  default-scheduler  0/1 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/1 nodes are available: 1 Preemption is not helpful for scheduling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well that did not work out. Let's figure out what's wrong.&lt;/p&gt;

&lt;p&gt;Seems like it's related to a Persistent Volume Claim. What is that?&lt;/p&gt;

&lt;p&gt;A Persistent Volume is a piece of storage in your Kubernetes cluster. It is provisioned by the cluster administrator or dynamically provisioned using a storage class.&lt;/p&gt;

&lt;p&gt;It represents a physical storage resource, which can be backed by various storage systems (e.g., NFS, cloud storage like AWS EBS, etc.).&lt;/p&gt;

&lt;p&gt;"So a persistent volume (PV) is the "physical" volume on the host machine that stores your persistent data. A persistent volume claim (PVC) is a request for the platform to create a PV for you, and you attach PVs to your pods via a PVC." [1]&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Persistent volume vs. persistent volume claim &lt;a href="https://stackoverflow.com/questions/48956049/what-is-the-difference-between-persistent-volume-pv-and-persistent-volume-clai" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/48956049/what-is-the-difference-between-persistent-volume-pv-and-persistent-volume-clai&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>kubernetes</category>
      <category>postgres</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Setting Up Service Principle Deployments for Gitlab CI/CD Terraform Virtual Machine Deployments</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Tue, 07 May 2024 22:58:09 +0000</pubDate>
      <link>https://dev.to/frederickollinger/setting-up-service-principle-deployments-for-gitlab-cicd-terraform-virtual-machine-deployments-4ha2</link>
      <guid>https://dev.to/frederickollinger/setting-up-service-principle-deployments-for-gitlab-cicd-terraform-virtual-machine-deployments-4ha2</guid>
      <description>&lt;p&gt;In order to use Terraform to deploy to the cloud, you need to either be logged in to Azure all ready or you need to create a Service Principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to login to Azure?
&lt;/h2&gt;

&lt;p&gt;Given that you have an account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this won't work in the cloud as it's not headless and will leak credentials. So this is a non-starter. For testing, we need to stay logged out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az &lt;span class="nb"&gt;logout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That said, we do need to login to manipulate Service Principles. So log back in for this portion of this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Service Principle in Azure?
&lt;/h2&gt;

&lt;p&gt;"An Azure service principal is a security identity used by user-created apps, services, and automation tools to access specific Azure resources." &lt;a href="https://learn.microsoft.com/en-us/cli/azure/azure-cli-sp-tutorial-1?toc=%2Fazure%2Fazure-resource-manager%2Ftoc.json&amp;amp;view=azure-cli-latest&amp;amp;tabs=bash"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  List all your current Service Principles:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az ad sp list &lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;table &lt;span class="nt"&gt;--show-mine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a new Service Principle
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az ad sp create-for-rbac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/48096342/what-is-azure-service-principal"&gt;2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will give you the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                                                                                                                                                                                                                  &lt;/span&gt;&lt;span class="nl"&gt;"appId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;XXX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"displayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;XXX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;XXX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tenant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;XXX&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Map the Service Principle JSON to Terraform Variables
&lt;/h2&gt;

&lt;p&gt;In the provider block:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client_id: This is the appId from the Service Principal JSON object.&lt;/li&gt;
&lt;li&gt;client_secret: This is the password from the Service Principal JSON object.&lt;/li&gt;
&lt;li&gt;tenant_id: This is the tenant from the Service Principal JSON object.&lt;/li&gt;
&lt;li&gt;subscription_id: This is your Azure subscription ID. It's optional if the Service Principal has
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;features&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="c1"&gt;# Use the appId (client ID), password (client secret), and tenant ID (tenant)&lt;/span&gt;
  &lt;span class="nx"&gt;client_id&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client_id&lt;/span&gt;
  &lt;span class="nx"&gt;client_secret&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client_secret&lt;/span&gt;
  &lt;span class="nx"&gt;tenant_id&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tenant_id&lt;/span&gt;
  &lt;span class="nx"&gt;subscription_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscription_id&lt;/span&gt;  &lt;span class="c1"&gt;# Optional: specify your Azure subscription ID&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Official Azure Service Principle Docs: &lt;a href="https://learn.microsoft.com/en-us/cli/azure/azure-cli-sp-tutorial-1?toc=%2Fazure%2Fazure-resource-manager%2Ftoc.json&amp;amp;view=azure-cli-latest&amp;amp;tabs=bash"&gt;https://learn.microsoft.com/en-us/cli/azure/azure-cli-sp-tutorial-1?toc=%2Fazure%2Fazure-resource-manager%2Ftoc.json&amp;amp;view=azure-cli-latest&amp;amp;tabs=bash&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Azure Service Principle Creation: &lt;a href="https://stackoverflow.com/questions/48096342/what-is-azure-service-principal"&gt;https://stackoverflow.com/questions/48096342/what-is-azure-service-principal&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>cloud</category>
      <category>virtualmachine</category>
    </item>
    <item>
      <title>Manipulate Tags on Gitlab CI/CD</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Fri, 29 Mar 2024 00:26:43 +0000</pubDate>
      <link>https://dev.to/frederickollinger/manipulate-tags-on-gitlab-cicd-3ad7</link>
      <guid>https://dev.to/frederickollinger/manipulate-tags-on-gitlab-cicd-3ad7</guid>
      <description>&lt;p&gt;On a Gitlab CI/CD pipeline, how to list, create, and delete tags.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preliminaries
&lt;/h2&gt;

&lt;p&gt;This assumes that you have a Gitlab project with a Docker linux container with curl and jq installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Repository Access Token
&lt;/h2&gt;

&lt;p&gt;Access token is needed to give permission to access the Gitlab api.&lt;/p&gt;

&lt;p&gt;Navigate to your project then go to the sidebar -&amp;gt; Settings -&amp;gt; Access Tokens.&lt;/p&gt;

&lt;p&gt;Token name is "tag". Select scope check "api" and leave the rest unchecked. Then click project access token.&lt;/p&gt;

&lt;p&gt;Be sure to save the token locally as once it disappears, you can not get it back again and need to create a new one.&lt;/p&gt;

&lt;p&gt;Make a new Gitlab variable called GITLAB_TOKEN.&lt;/p&gt;

&lt;h2&gt;
  
  
  List Tags
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash                                                                                                                                                                                 &lt;/span&gt;

 &lt;span class="c"&gt;# list-tags.sh&lt;/span&gt;

&lt;span class="c"&gt;# List all Gitlab tags for a given project.                                                                                                                                           &lt;/span&gt;
&lt;span class="c"&gt;# $CI_PROJECT_ID is a Gitlab pre-defined variable                                                                                                                                           &lt;/span&gt;
&lt;span class="c"&gt;# $GITLAB_TOKEN is a project access token that needs to be                                                                                                                                  &lt;/span&gt;
&lt;span class="c"&gt;# a defined CI/CD variable.                                                                                                                                                                 &lt;/span&gt;

&lt;span class="nv"&gt;GITLAB_API_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://gitlab.com/api/v4/projects/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CI_PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;                                                                                                                   

curl &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"PRIVATE-TOKEN: &lt;/span&gt;&lt;span class="nv"&gt;$GITLAB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GITLAB_API_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/repository/tags"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Tag
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# create-tag.sh&lt;/span&gt;

&lt;span class="c"&gt;# $CI_PROJECT_ID is a Gitlab pre-defined variable&lt;/span&gt;
&lt;span class="c"&gt;# $GITLAB_TOKEN is a project access token that needs to be&lt;/span&gt;
&lt;span class="c"&gt;# a defined CI/CD variable.&lt;/span&gt;
&lt;span class="c"&gt;# TAG_NAME needs to be defined as a variable in the yaml.&lt;/span&gt;

&lt;span class="nv"&gt;GITLAB_API_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://gitlab.com/api/v4/projects/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CI_PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

curl &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"PRIVATE-TOKEN: &lt;/span&gt;&lt;span class="nv"&gt;$GITLAB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;$GITLAB_API_URL&lt;/span&gt;/repository/tags?tag_name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TAG_NAME&lt;/span&gt;&lt;span class="se"&gt;\&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$CI_COMMIT_SHA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding Code to Yaml
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
&lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&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;curl/curl-docker&lt;/span&gt;
  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Make TAG_NAME a more meaningful variable&lt;/span&gt;
    &lt;span class="na"&gt;TAG_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_COMMIT_SHA&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Create a Tag&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bash tag.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Update Gitlab On Prem Server Running in a Docker Container</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Mon, 12 Feb 2024 18:06:27 +0000</pubDate>
      <link>https://dev.to/frederickollinger/update-gitlab-on-prem-server-running-in-a-docker-container-3i8h</link>
      <guid>https://dev.to/frederickollinger/update-gitlab-on-prem-server-running-in-a-docker-container-3i8h</guid>
      <description>&lt;p&gt;Problem: We had a Gitlab server with repos in it that needed to be updated which was running on prem inside a Docker container. Worse, the container is not versioned. If we restarted the Docker container for any reason, we would wind up with the latest version being run which is not the one which was run when the container was set up. This means losing all our work.&lt;/p&gt;

&lt;p&gt;In this example, it's going to be assumed that one all ready has an instance of Gitlab server running in an official container using Docker and that one can start, stop, and connect to the running container.&lt;/p&gt;

&lt;p&gt;Surprisingly, that while there is online guides on how to host Gitlab on prem in a Docker container, and there's an official Gitlab Docker container on Docker Hub, there were no instructions on how to update Gitlab inside a Docker container.&lt;/p&gt;

&lt;p&gt;How to actually run Gitlab in a Docker container, is beyond the scope of this article.&lt;/p&gt;

&lt;p&gt;NOTE: One caveat is that you can NOT make a backup on one version then restore it to another version. In this guide, we suggest backing up twice. 1st before one updates then after an update. That way if things go badly with the update, you still have your original repos in the original backup.&lt;/p&gt;

&lt;p&gt;Solution.&lt;/p&gt;

&lt;p&gt;1st Step is to backup the container in place so if things go badly, we can restore it:&lt;/p&gt;

&lt;p&gt;1st we need to connect to the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nv"&gt;$CONTAINER&lt;/span&gt; /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then backup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/opt/gitlab/backups
/usr/bin/gitlab-backup create &lt;span class="nv"&gt;force&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes &lt;/span&gt;&lt;span class="nv"&gt;GZIP_RSYNCABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes &lt;/span&gt;&lt;span class="nv"&gt;STRATEGY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;copy &lt;span class="nv"&gt;CRON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nb"&gt;cp&lt;/span&gt; /etc/gitlab/gitlab-secrets.json /var/opt/gitlab/backups
&lt;span class="nb"&gt;cp&lt;/span&gt; /etc/gitlab/gitlab.rb /var/opt/gitlab/backups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update Gitlab:&lt;/p&gt;

&lt;p&gt;In this example, we'll use 14.9.1, but you should pick the version that's right for you via an upgrade path. More information on this is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.gitlab.com/ee/update/index.html#upgrade-paths"&gt;https://docs.gitlab.com/ee/update/index.html#upgrade-paths&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl ca-certificates openssh-server apt-utils perl
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | bash
apt update
apt &lt;span class="nb"&gt;install &lt;/span&gt;gitlab-ee&lt;span class="o"&gt;=&lt;/span&gt;14.9.5-ee.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now backup again as per the steps above.&lt;/p&gt;

&lt;p&gt;Finally, change the tag on the container. In this case, the tag should be 14.9.5-ee. then restart the Docker container.&lt;/p&gt;

&lt;p&gt;Finally, restore the latest back which matches the new version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BACKUPDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/git/data/backups
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$BACKUPDIR&lt;/span&gt;
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BACKUPDIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/gitlab-secrets.json /etc/gitlab
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BACKUPDIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/gitlab.rb /etc/gitlab
&lt;span class="nv"&gt;GITLAB_ASSUME_YES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 /usr/bin/gitlab-backup restore &lt;span class="nv"&gt;BACKUP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BACKUPFILE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
/usr/bin/gitlab-ctl restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able to go to your Gitlab web page and find that latest version is running and that all your repos are restored.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Pulling Git Submodules on Gitlab CI/CD Pipeline From a Different Repo</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Mon, 24 Apr 2023 17:46:30 +0000</pubDate>
      <link>https://dev.to/frederickollinger/pulling-git-submodules-on-gitlab-cicd-pipeline-from-a-different-repo-144e</link>
      <guid>https://dev.to/frederickollinger/pulling-git-submodules-on-gitlab-cicd-pipeline-from-a-different-repo-144e</guid>
      <description>&lt;p&gt;This is for solving the problem of building a repo with a different ssh key.&lt;/p&gt;

&lt;p&gt;In this case, we had some legacy code on a Gerrit server, and we wanted to pull this code so we could build it on our Gitlab server.&lt;/p&gt;

&lt;p&gt;In this example, our service account for Gerrit will be gitlab. The name shows that the Gerrit account is only for Gitlab to have access, and it is not tied to a real human's account. The linux user account on our workstation that we use for this example is testuser.&lt;/p&gt;

&lt;p&gt;The 1st step is to create a new ssh key solely for this purpose.&lt;/p&gt;

&lt;p&gt;I used ssh-keygen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it askes for the name of the key, I use gerrit.pem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter file in which to save the key (/home/testuser/.ssh/id_rsa): gerrit.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have 2 new files: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;gerrit.pem - private key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gerrit.pem.pub -  public key&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Put the private key in your Gitlab variables and call it GERRIT_PEM:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.gitlab.com/ee/ci/variables/#define-a-cicd-variable-in-the-ui"&gt;https://docs.gitlab.com/ee/ci/variables/#define-a-cicd-variable-in-the-ui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Put the public key into Gerrit. See Register SSH public key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://haiyanghaiyang.gitbooks.io/gerrit-user-manual/content/sheng-cheng-yu-zhu-ce-ssh-key.html"&gt;https://haiyanghaiyang.gitbooks.io/gerrit-user-manual/content/sheng-cheng-yu-zhu-ce-ssh-key.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you should test the ssh key on an linux account did not previously have access to the Gerrit repo. In the case, we'll call the user testuser.&lt;/p&gt;

&lt;p&gt;Copy the gerrit.pem file to the testuser home folder and give ownership of it to testuser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cp gerrit.pem /home/testuser
sudo chown testuser /home/testuser/gerrit.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this test, we will use ssh-agent.&lt;/p&gt;

&lt;p&gt;ssh-agent is a way to allow us to put ssh keys into RAM so we can use keys which are not part of our ~/.ssh folder.&lt;/p&gt;

&lt;p&gt;In this example, I pull one of the git submodules that I wanted to pull to make the test simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su testuser # become testuser
eval "$(ssh-agent -s)" # start ssh-agent
ssh-add ~/gerrit.pub # add ssh key to the agent
git clone ssh://gitlab@gerrit.testexample.com/source_code # note this will change depending upon what your actual server, username, and source code is called.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should pull the source code.&lt;/p&gt;

&lt;p&gt;If this works, we are almost home free.&lt;/p&gt;

&lt;p&gt;We need to add new Gitlab variables. In my case it was 2 new ones:&lt;br&gt;
GERRIT_KNOWN_HOSTS1 and GERRIT_KNOWN_HOSTS2.&lt;/p&gt;

&lt;p&gt;These are gotten from known hosts. Still as test user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /home/testuser/.ssh/known_hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There should be 2 new lines here. Add them to Gitlab variables as the variable names above. We have to split each line into a separate variables because of the way that line breaks get broken if we don't, and the known_hosts becomes invalid due to a missing line break.&lt;/p&gt;

&lt;p&gt;Next create a .gitlab-ci.yml file. We'll use the standard header:&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;build-code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&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;centos:7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next create the .ssh folder and known_hosts and change permissions. Ssh is super picky about these things:&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mkdir ~/.ssh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;touch ~/.ssh/known_hosts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chmod 600 ~/.ssh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chmod 644 ~/.ssh/known_hosts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now start the ssh-agent. Note it has to be installed in the container:&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;eval "$(ssh-agent -s)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now add the key to ssh-agent. But this time, we don't have it on our disk, we need to pull from Gitlab variables that we set above:&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ssh-add - &amp;lt;&amp;lt;&amp;lt; "${GERRIT_PEM}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the magic. We need to populate known_hosts with what worked with testuser.&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo ${GERRIT_KNOWN_HOSTS1} &amp;gt;&amp;gt; ~/.ssh/known_hosts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo ${GERRIT_KNOWN_HOSTS2} &amp;gt;&amp;gt; ~/.ssh/known_hosts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to tell ssh that we are using user gitlab instead of our container user. This will allow git submodules to work with a different user:&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "Host gerrit.testexample.com" &amp;gt; ~/.ssh/config&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "User gitlab" &amp;gt; ~/.ssh/config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we need to actually pull the submodules:&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git submodule update --init --recursive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to build our code. Your build system may differ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    - make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All in 1 script:&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;build-code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&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;centos:7&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mkdir ~/.ssh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;touch ~/.ssh/known_hosts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chmod 600 ~/.ssh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chmod 644 ~/.ssh/known_hosts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;eval "$(ssh-agent -s)"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ssh-add - &amp;lt;&amp;lt;&amp;lt; "${GERRIT_PEM}"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo ${GERRIT_KNOWN_HOSTS1} &amp;gt;&amp;gt; ~/.ssh/known_hosts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo ${GERRIT_KNOWN_HOSTS2} &amp;gt;&amp;gt; ~/.ssh/known_hosts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "Host gerrit.testexample.com" &amp;gt; ~/.ssh/config&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "User gitlab" &amp;gt; ~/.ssh/config&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git submodule update --init --recursive&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;make&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check this .gitlab-ci.yaml into your Gitlab repo and test it out.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Docker Same User Inside a Container Dynamically</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Mon, 06 Mar 2023 21:38:49 +0000</pubDate>
      <link>https://dev.to/frederickollinger/docker-same-user-inside-a-container-dynamically-3gd7</link>
      <guid>https://dev.to/frederickollinger/docker-same-user-inside-a-container-dynamically-3gd7</guid>
      <description>&lt;p&gt;In this post, we'll create a user dynamically inside a Docker container with the use UID and GID as the user on the host who ran the container.&lt;/p&gt;

&lt;p&gt;Previously, we addressed the issue of accessing a mounted volume inside a container as user root inside the container with Docker Compose here: &lt;a href="https://dev.to/frederickollinger/docker-compose-access-a-mounted-volume-inside-a-container-41kf"&gt;https://dev.to/frederickollinger/docker-compose-access-a-mounted-volume-inside-a-container-41kf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this solution wound up creating artifacts which were owned by root which meant that accessing them as a regular user on the host was more difficult. &lt;/p&gt;

&lt;p&gt;Thus, we actually want to have a user inside the Docker container which is the same as the host.&lt;/p&gt;

&lt;p&gt;The 1st step is to make a bash script which will create a new user inside the container dynamically.&lt;/p&gt;

&lt;p&gt;Create a script called entrypoint.sh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/env bash&lt;/span&gt;

&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;container

useradd &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /home/&lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;span class="nb"&gt;chown &lt;/span&gt;container /home/&lt;span class="nv"&gt;$USER&lt;/span&gt;
su &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script will basically add a new user called container when the Docker container is 1st run and use the user id passed into the container.&lt;/p&gt;

&lt;p&gt;Next create Dockerfile in the same directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;FROM centos:7                                                                                                            
USER root

COPY entrypoint.sh /usr/sbin/entrypoint.sh
RUN &lt;span class="nb"&gt;chmod &lt;/span&gt;a+x /usr/sbin/entrypoint.sh
ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/usr/sbin/entrypoint.sh"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Dockerfile will run our entrypoint.sh script when it's first run. It needs to start as root but then it will change to the container user which happens to have the same user id as whomever started the container.&lt;/p&gt;

&lt;p&gt;Build the container, in this example as userdemo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; userdemo &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run the container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   docker \
    run \
    --rm \
    --name=userdemo \
    --hostname=userdemo \
    --workdir=/home/container \
    -v `pwd`/project:/home/developer/project \
    userdemo \
    /bin/bash `id -u`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you will have a folder called "project" which is mounted inside the container as /home/container/project. You can change this or even add more lines with the volume mount flag.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Docker Compose Access A Mounted Volume Inside a Container</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Wed, 01 Mar 2023 18:21:44 +0000</pubDate>
      <link>https://dev.to/frederickollinger/docker-compose-access-a-mounted-volume-inside-a-container-41kf</link>
      <guid>https://dev.to/frederickollinger/docker-compose-access-a-mounted-volume-inside-a-container-41kf</guid>
      <description>&lt;p&gt;Problem: Using a container to build my project but I can't access the mounted volume due to permission issues.&lt;/p&gt;

&lt;p&gt;Assumptions: This tutorial assumes you are working on a reasonably up to date Linux box with Docker and Docker Compose installed, and that you have a basic familiarity with the Linux command line.&lt;/p&gt;

&lt;p&gt;A mounted volume is when you mount a directory from your filesystem inside a container. This allows you to access files which were not available when you built the container. Also, you have access to the build artifacts outside the container after building inside the containter.&lt;/p&gt;

&lt;p&gt;Docker Compose File:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;gcc&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gcc"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/bin/bash&lt;/span&gt;
    &lt;span class="na"&gt;group_add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;$GID&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${PWD}/fullbuild:/root/fullbuild&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file will pull the official gcc Docker container. It expects the group user id to be $GID and the source code to build to be at fullbuild.&lt;/p&gt;

&lt;p&gt;We usually make the $GID the same as the default group for the user who is currently running docker-compose on the host system.&lt;/p&gt;

&lt;p&gt;If we do not have the fullbuild directory make it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; fullbuild
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The copy any source code in.&lt;/p&gt;

&lt;p&gt;Before we run the function, we need to ensure that our default group has access to both fullbuild and its subdirs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find fullbuild &lt;span class="nt"&gt;-type&lt;/span&gt; d &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;chmod &lt;/span&gt;g+rwx &lt;span class="o"&gt;{}&lt;/span&gt; +
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, when we run and enter the container, ensure that $GID is set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; docker-compose run gcc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. After we run the last command, we'll be inside a Docker container with access to gcc as well as having access to all the source code inside the container. Source code is in /root/fullbuild. Build artifacts will be available in fullbuild outside of the container.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>Rust ^ cannot use the `?` operator in a function that returns `()`</title>
      <dc:creator>Frederick Ollinger</dc:creator>
      <pubDate>Mon, 27 Feb 2023 21:21:18 +0000</pubDate>
      <link>https://dev.to/frederickollinger/rust-cannot-use-the-operator-in-a-function-that-returns--5ef0</link>
      <guid>https://dev.to/frederickollinger/rust-cannot-use-the-operator-in-a-function-that-returns--5ef0</guid>
      <description>&lt;p&gt;Problem:&lt;/p&gt;

&lt;p&gt;When I try to run code with the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;invalid_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/AA.csv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run

   Compiling voxide v0.1.0 &lt;span class="o"&gt;(&lt;/span&gt;/rick/follinge-2020-08-10/projects/voxide&lt;span class="o"&gt;)&lt;/span&gt;
error[E0277]: the &lt;span class="sb"&gt;`&lt;/span&gt;?&lt;span class="sb"&gt;`&lt;/span&gt; operator can only be used &lt;span class="k"&gt;in &lt;/span&gt;a &lt;span class="k"&gt;function &lt;/span&gt;that returns &lt;span class="sb"&gt;`&lt;/span&gt;Result&lt;span class="sb"&gt;`&lt;/span&gt; or &lt;span class="sb"&gt;`&lt;/span&gt;Option&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;or another &lt;span class="nb"&gt;type &lt;/span&gt;that implements &lt;span class="sb"&gt;`&lt;/span&gt;FromResidual&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; src/main.rs:10:45
   |
9  | fn invalid_function&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   | &lt;span class="nt"&gt;---------------------&lt;/span&gt; this &lt;span class="k"&gt;function &lt;/span&gt;should &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;Result&lt;span class="sb"&gt;`&lt;/span&gt; or &lt;span class="sb"&gt;`&lt;/span&gt;Option&lt;span class="sb"&gt;`&lt;/span&gt; to accept &lt;span class="sb"&gt;`&lt;/span&gt;?&lt;span class="sb"&gt;`&lt;/span&gt;
10 |     &lt;span class="nb"&gt;let &lt;/span&gt;mut file &lt;span class="o"&gt;=&lt;/span&gt; File::open&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"data/AA.csv"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;?&lt;span class="p"&gt;;&lt;/span&gt;
   |                                             ^ cannot use the &lt;span class="sb"&gt;`&lt;/span&gt;?&lt;span class="sb"&gt;`&lt;/span&gt; operator &lt;span class="k"&gt;in &lt;/span&gt;a &lt;span class="k"&gt;function &lt;/span&gt;that returns &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
   |
   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;help&lt;/span&gt;: the trait &lt;span class="sb"&gt;`&lt;/span&gt;FromResidual&amp;lt;Result&amp;lt;Infallible, std::io::Error&amp;gt;&amp;gt;&lt;span class="sb"&gt;`&lt;/span&gt; is not implemented &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

For more information about this error, try &lt;span class="sb"&gt;`&lt;/span&gt;rustc &lt;span class="nt"&gt;--explain&lt;/span&gt; E0277&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
error: could not compile &lt;span class="sb"&gt;`&lt;/span&gt;voxide&lt;span class="sb"&gt;`&lt;/span&gt; due to previous error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 1st clue is in asking ourselves what does the question mark do in this context? The answer is error propagation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html"&gt;https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So basically it worked in main() because that was the top level function, and if we failed, we crashed as the error state was uncaught which is okay.&lt;/p&gt;

&lt;p&gt;But if we use the question mark operator in a function, we need to return the Result which tells the caller that they need to handle a potential error state.&lt;/p&gt;

&lt;p&gt;A better way to handle it is to either use the if or match keywords.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;valid_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/AA.csv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Do something with the file&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle the error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open a file, and check for errors.&lt;/p&gt;

&lt;p&gt;This pattern is used so often that Rust has a match keyword for dealing with enums:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;better_valid_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;file_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/AA.csv"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;file_result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Problem opening the file: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html"&gt;https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
