<?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: Boris Quiroz</title>
    <description>The latest articles on DEV Community by Boris Quiroz (@boris).</description>
    <link>https://dev.to/boris</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%2F6534%2F5e88e836-54a0-4296-8a0e-f35e42af9dbf.jpg</url>
      <title>DEV Community: Boris Quiroz</title>
      <link>https://dev.to/boris</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/boris"/>
    <language>en</language>
    <item>
      <title>Github as Helm repository</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Fri, 28 Jun 2024 02:39:43 +0000</pubDate>
      <link>https://dev.to/boris/github-as-helm-repository-1lcf</link>
      <guid>https://dev.to/boris/github-as-helm-repository-1lcf</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted in &lt;a href="https://borisquiroz.dev/posts/github-as-helm-repository/"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For my personal projects, I use Github as a Helm repository. This is a simple way to share Helm charts with the community. In this post, I'll show you how to create a Helm repository using Github Pages either for personal use or for your organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;p&gt;This post will assume your already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know what &lt;a href="https://kubernetes.io/"&gt;kubernetes&lt;/a&gt; is&lt;/li&gt;
&lt;li&gt;Have a basic understanding of &lt;a href="https://helm.sh/"&gt;helm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Have a &lt;a href="https://github.com"&gt;Github&lt;/a&gt; account and repository&lt;/li&gt;
&lt;li&gt;Have coded a Helm chart&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;Having all the above already in place, there are some things we need to do before we can use Github as a Helm repository. In particular, we need to enable Github Pages for our repository and add at least one &lt;code&gt;index.html&lt;/code&gt; file to it. According to &lt;a href="https://v2.helm.sh/docs/chart_repository/#github-pages-example"&gt;this&lt;/a&gt; documentation, the &lt;code&gt;index.html&lt;/code&gt; file shouldn't be needed, but in reallity it is necessary for Helm to recognize the repository as a Helm repository.&lt;/p&gt;

&lt;p&gt;Once having that and assuming our first chart is ready, we need to start packaging and adding it to the repository. The following steps will guide you through the process. All the directory structure assumed below is based on &lt;a href="https://github.com/boris/kubernetes"&gt;my own&lt;/a&gt; repository.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Package the chart
&lt;/li&gt;
&lt;/ol&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;helm package mychart
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;mychart-0.1.0.tgz helm/charts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the index
&lt;/li&gt;
&lt;/ol&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;helm repo index helm/charts &lt;span class="nt"&gt;--url&lt;/span&gt; https://boris.github.io/kubernetes/helm/charts
&lt;span class="nv"&gt;$ &lt;/span&gt;git add helm/charts/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add mychart-0.1.0"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above we're now ready to add our repository to Helm and install our chart:&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;helm repo add boris https://boris.github.io/kubernetes/helm/charts
&lt;span class="nv"&gt;$ &lt;/span&gt;helm repo list
NAME                    URL
ealenn                  https://ealenn.github.io/charts
bitnami                 https://charts.bitnami.com/bitnami
kubernetes-dashboard    https://kubernetes.github.io/dashboard/
argo                    https://argoproj.github.io/argo-helm
boris                   https://boris.github.io/kubernetes/helm/charts/
&lt;span class="nv"&gt;$ &lt;/span&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;mychart boris/mychart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>github</category>
      <category>kubernetes</category>
      <category>helm</category>
      <category>deployment</category>
    </item>
    <item>
      <title>🐍 Testing exit codes with Pytest</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Sat, 10 Oct 2020 22:45:33 +0000</pubDate>
      <link>https://dev.to/boris/testing-exit-codes-with-pytest-1g27</link>
      <guid>https://dev.to/boris/testing-exit-codes-with-pytest-1g27</guid>
      <description>&lt;p&gt;As almost every other sysadmin I know, python is the language of choice to do some scripting. And, as we all know, testing is an important part of any development.&lt;/p&gt;

&lt;p&gt;My code is a simple parser that interacts with some Linux commands using &lt;a href="https://docs.python.org/3/library/subprocess.html#module-subprocess"&gt;subprocess&lt;/a&gt;, which instead of raising an exception it returns something != 0. In fact, the exit code is 2. How to test that with pytest? This is what I did (which might not be &lt;em&gt;the best&lt;/em&gt; way to do it):&lt;/p&gt;

&lt;p&gt;The parser is pretty simple, this is the &lt;code&gt;cli.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;argparse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ArgumentParser&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_parser&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'list'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'List something'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;parser&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_parser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_something_to_test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# The command to test
&lt;/span&gt;        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'some'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'commands'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;# Here's the trick
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;SystemExit&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>sysadmin</category>
      <category>testing</category>
    </item>
    <item>
      <title>Microk8s: Unable to connect to the server: x509: certificate has expired or is not yet valid</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Mon, 04 May 2020 00:14:07 +0000</pubDate>
      <link>https://dev.to/boris/microk8s-unable-to-connect-to-the-server-x509-certificate-has-expired-or-is-not-yet-valid-2b73</link>
      <guid>https://dev.to/boris/microk8s-unable-to-connect-to-the-server-x509-certificate-has-expired-or-is-not-yet-valid-2b73</guid>
      <description>&lt;p&gt;This is an error that you might see once every 10 years, so it's very likely you'll forget the solution.&lt;br&gt;
The behavior is the following: When trying to do anything that interacts with API server you'll get the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;boris@ubuntu:~$ microk8s kubectl get all --all-namespaces
Unable to connect to the server: x509: certificate has expired or is not yet valid: current time 2020-05-03T23:53:06Z is after 2020-05-03T16:38:01Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to solve it?
&lt;/h2&gt;

&lt;p&gt;Easy, just renew your certificates. But first, it's a good idea to check expiration time of current installed certificates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;boris@ubuntu:~$ sudo microk8s.refresh-certs -c
The CA certificate will expire in 0 days.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, we're a but out-of-date, let's renew them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;boris@ubuntu:~$ sudo microk8s.refresh-certs -i
Backing up certificates under /var/snap/microk8s/1385/var/log/ca-backup/
Creating new certificates
Signature ok
subject=/C=GB/ST=Canonical/L=Canonical/O=Canonical/OU=Canonical/CN=127.0.0.1
Getting CA Private Key
Signature ok
subject=/CN=front-proxy-client
Getting CA Private Key
1
Creating new kubeconfig file
Stopped.
Started.

The CA certificates have been replaced. Kubernetes will restart the pods of your workloads.
Any worker nodes you may have in your cluster need to be removed and re-joined to become aware of the new CA.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>microk8s</category>
      <category>devops</category>
    </item>
    <item>
      <title>Discuss: Would you join a dev.to IRC channel?</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Sun, 05 Jan 2020 02:39:30 +0000</pubDate>
      <link>https://dev.to/boris/discuss-would-you-join-a-dev-to-irc-channel-42gf</link>
      <guid>https://dev.to/boris/discuss-would-you-join-a-dev-to-irc-channel-42gf</guid>
      <description>&lt;p&gt;This might sound a bit old-school, but IRC is still one of the tools I use on a daily basis so would be interesting to have some tech and non-tech conversations with the community in freenode or somewhere else.&lt;/p&gt;

&lt;p&gt;Opening the discussion on this matter.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>irc</category>
      <category>devops</category>
      <category>help</category>
    </item>
    <item>
      <title>Create VPC using awscli</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Sun, 29 Dec 2019 23:35:37 +0000</pubDate>
      <link>https://dev.to/boris/create-vpc-using-awscli-k40</link>
      <guid>https://dev.to/boris/create-vpc-using-awscli-k40</guid>
      <description>&lt;p&gt;The main idea of this post is to have an easy way to remind how to setup a VPC using &lt;a href="https://aws.amazon.com/cli/"&gt;awscli&lt;/a&gt;, and it's not intended to explain how a VPC works and what are the benefits of them.&lt;/p&gt;

&lt;h1&gt;
  
  
  The setup
&lt;/h1&gt;

&lt;p&gt;Assuming that you already have awscli in place and configured, this is what we should do in order to have a working VPC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a VPC with a /16 subnet (it can be /17, /18, etc. but never less than /16). I'll be using &lt;strong&gt;10.88.0.0/16&lt;/strong&gt; for this example.&lt;/li&gt;
&lt;li&gt;Create, at least, in different availability zones:

&lt;ul&gt;
&lt;li&gt;Two public subnet: &lt;strong&gt;10.88.0.0/24&lt;/strong&gt; and &lt;strong&gt;10.88.1.0/24&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Two private subnet: &lt;strong&gt;10.88.2.0/24&lt;/strong&gt; and &lt;strong&gt;10.88.3.0/24&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create an Internet gateway and attach it to the VPC.&lt;/li&gt;
&lt;li&gt;Create an Elastic IP Address.&lt;/li&gt;
&lt;li&gt;Create a NAT gateway, attach to it the Elastic IP and place the NAT gateway in the public subnet.&lt;/li&gt;
&lt;li&gt;Create a couple of routing tables:

&lt;ul&gt;
&lt;li&gt;Assign public subnet to Internet gateway with destination of 0.0.0.0/0&lt;/li&gt;
&lt;li&gt;Assign the private subnet to NAT gateway with destination of 0.0.0.0/0&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How it should be done.
&lt;/h1&gt;

&lt;p&gt;This is the full list of commands that reflects the scenario described in the setup section. I won't explain each command, but feel free to ask in the comments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 create-vpc &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.88.0.0/16
aws ec2 create-subnet &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &lt;span class="nv"&gt;$VPC_ID&lt;/span&gt; &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.88.0.0/24 &lt;span class="nt"&gt;--availability-zone&lt;/span&gt; us-east-1e
aws ec2 create-subnet &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &lt;span class="nv"&gt;$VPC_ID&lt;/span&gt; &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.88.1.0/24 &lt;span class="nt"&gt;--availability-zone&lt;/span&gt; us-east-1f
aws ec2 create-subnet &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &lt;span class="nv"&gt;$VPC_ID&lt;/span&gt; &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.88.2.0/24 &lt;span class="nt"&gt;--availability-zone&lt;/span&gt; us-east-1e
aws ec2 create-subnet &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &lt;span class="nv"&gt;$VPC_ID&lt;/span&gt; &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.88.3.0/24 &lt;span class="nt"&gt;--availability-zone&lt;/span&gt; us-east-1f
aws ec2 create-internet-gateway
aws ec2 attach-internet-gateway &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &lt;span class="nv"&gt;$VPC_ID&lt;/span&gt; &lt;span class="nt"&gt;--internet-gateway-id&lt;/span&gt; &lt;span class="nv"&gt;$IGW&lt;/span&gt;
aws ec2 create-route-table &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &lt;span class="nv"&gt;$VPC_ID&lt;/span&gt;
aws ec2 create-route &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &lt;span class="nv"&gt;$RTB&lt;/span&gt; &lt;span class="nt"&gt;--destination-cidr-block&lt;/span&gt; 0.0.0.0/0 &lt;span class="nt"&gt;--gateway-id&lt;/span&gt; &lt;span class="nv"&gt;$IGW&lt;/span&gt;
aws ec2 allocate-address &lt;span class="nt"&gt;--domain&lt;/span&gt; vpc
aws ec2 create-nat-gateway &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &lt;span class="nv"&gt;$PUBLIC_SUBNET&lt;/span&gt; &lt;span class="nt"&gt;--allocation-id&lt;/span&gt; &lt;span class="nv"&gt;$EIP&lt;/span&gt;
aws ec2 create-route-table &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &lt;span class="nv"&gt;$VPC_ID&lt;/span&gt;
aws ec2 create-route &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &lt;span class="nv"&gt;$RTB_PRIVATE&lt;/span&gt; &lt;span class="nt"&gt;--destination-cidr-block&lt;/span&gt; 0.0.0.0/0 &lt;span class="nt"&gt;--gateway-id&lt;/span&gt; &lt;span class="nv"&gt;$NGW&lt;/span&gt;
aws ec2 associate-route-table &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &lt;span class="nv"&gt;$PUBLIC_SUBNET0&lt;/span&gt; &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &lt;span class="nv"&gt;$RTB_PUB&lt;/span&gt;
aws ec2 associate-route-table &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &lt;span class="nv"&gt;$PUBLIC_SUBNET1&lt;/span&gt; &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &lt;span class="nv"&gt;$RTB_PUB&lt;/span&gt;
aws ec2 associate-route-table &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &lt;span class="nv"&gt;$PRIVATE_SUBNET2&lt;/span&gt; &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &lt;span class="nv"&gt;$RTB_PRIV&lt;/span&gt;
aws ec2 associate-route-table &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &lt;span class="nv"&gt;$PRIVATE_SUBNET3&lt;/span&gt; &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &lt;span class="nv"&gt;$RTB_PRIV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Tips and tricks.
&lt;/h1&gt;

&lt;p&gt;As a lot of reference to previously created resources is needed, I found useful to create a file with the following format:&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;export &lt;/span&gt;&lt;span class="nv"&gt;VPC_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"vpc-&amp;lt;some_long_id&amp;gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PRIV_SUBNET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"subnet-&amp;lt;some_long_id&amp;gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PUB_SUBNET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"subnet-&amp;lt;some_long_id&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And time to time I run &lt;code&gt;source file_with_var&lt;/code&gt; so I can easily access them using the &lt;code&gt;$&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>vpc</category>
    </item>
    <item>
      <title>Using YAML to manage Python configurations</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Mon, 02 Dec 2019 01:30:48 +0000</pubDate>
      <link>https://dev.to/boris/using-yaml-to-manage-python-configurations-1j9c</link>
      <guid>https://dev.to/boris/using-yaml-to-manage-python-configurations-1j9c</guid>
      <description>&lt;p&gt;On my last &lt;a href="https://github.com/boris/usd_clp"&gt;weekend project&lt;/a&gt; I needed to talk to an API using an &lt;code&gt;AUTH_KEY&lt;/code&gt; which should be private but should be included in the request instead of using any auth method.&lt;/p&gt;

&lt;p&gt;The request I needed to run was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requests.get('https://&amp;lt;URL&amp;gt;/&amp;lt;SOMETHING&amp;gt;/&amp;lt;SOMETHING_ELSE&amp;gt;.json/?auth_key=YOUR_AUTH_KEY')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/l378lrNMtCj4tfyRa/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l378lrNMtCj4tfyRa/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I decided to use &lt;a href="https://pypi.org/project/PyYAML/"&gt;pyyaml&lt;/a&gt;, and it's very easy to use! Here's a short example of the python file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;yaml&lt;/span&gt;

&lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'config.yml'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Loader&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullLoader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'https://&amp;lt;URL&amp;gt;/&amp;lt;SOMETHING&amp;gt;/&amp;lt;SOMETHING_ELSE&amp;gt;.json/?auth_key='&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# then, everything else
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the &lt;code&gt;config.yml&lt;/code&gt; is something like this:&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;auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_AUTH_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And not I can have my &lt;code&gt;config.yml&lt;/code&gt; stored only in my laptop or, even better, in some secret place like a vault or something but not publicly accessible to anybody in GitHub.&lt;/p&gt;

&lt;p&gt;Enjoy.&lt;/p&gt;

</description>
      <category>python</category>
      <category>configuration</category>
      <category>tips</category>
      <category>devops</category>
    </item>
    <item>
      <title>[Halp!] How do you take notes?</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Sat, 05 Oct 2019 14:54:21 +0000</pubDate>
      <link>https://dev.to/boris/halp-how-do-you-take-notes-2m61</link>
      <guid>https://dev.to/boris/halp-how-do-you-take-notes-2m61</guid>
      <description>&lt;p&gt;Notes are important, as brain is not able to retain all the information. In particular technical notes, as they can help us to avoid making the same mistake twice. Or three times.&lt;/p&gt;

&lt;p&gt;Typically, I use a regular Castelli/Moleskinke/Other (any other on sale) regular note taking notebook using an old-school tool called &lt;strong&gt;pen&lt;/strong&gt;. But this proven method is not fulfilling all my needs, which are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notes must be clear (this is on my side, and solved pretty well so far)&lt;/li&gt;
&lt;li&gt;Notes must be searchable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's where the downside of old-school method appears: There's no efficient way to search for &lt;em&gt;something&lt;/em&gt; in a 80 pages note taking notebook. The good thing about using pen and paper is that notes seems to be stored clearly in my brain, but not bullet proof.&lt;/p&gt;

&lt;p&gt;I've also tested digital method: I wrote a small python app that, by using tags and/or date, I can search for notes I've taken, and I've been using it for the last couple of months. The problem with this is that I use the search option more often as information is not so well retained in my brain. Maybe I just need some training?&lt;/p&gt;

&lt;p&gt;What do you use? How do you take notes? Do you see any disadvantages in your method?&lt;/p&gt;

&lt;p&gt;Any help or comments are welcome. &lt;/p&gt;

</description>
      <category>productivity</category>
      <category>devops</category>
      <category>discuss</category>
      <category>help</category>
    </item>
    <item>
      <title>Running tor using docker</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Fri, 19 Jul 2019 19:58:21 +0000</pubDate>
      <link>https://dev.to/boris/running-tor-using-docker-4d7h</link>
      <guid>https://dev.to/boris/running-tor-using-docker-4d7h</guid>
      <description>&lt;p&gt;If you want to connect to &lt;a href="https://www.torproject.org/" rel="noopener noreferrer"&gt;tor&lt;/a&gt; network without using tor browser, docker is the solution!&lt;/p&gt;

&lt;p&gt;Just copy this code into a Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM alpine:edge

RUN apk update
RUN apk add tor

RUN echo "Log notice stdout" &amp;gt;&amp;gt; /etc/torrc
RUN echo "SocksPort 0.0.0.0:9150" &amp;gt;&amp;gt; /etc/torrc

EXPOSE 9150

CMD tor -f /etc/torrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build it with &lt;code&gt;docker build -t tor -f Dockerfile .&lt;/code&gt; and run it with:&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 -d --rm --name tor -p 9150:9150 tor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, if you don't want to do the build just run:&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 -d --rm --name tor -p 9150:9150 boris/tor:alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you'll have a tor proxy running in your &lt;code&gt;127.0.0.1:9150&lt;/code&gt; so go ahead and configure your browser of choice to use a SOCKS proxy on &lt;code&gt;127.0.0.1:9150&lt;/code&gt; and you'll go from this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq15oemam0pyxdfy64bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq15oemam0pyxdfy64bg.png" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58miva1resfuuqp69kgt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58miva1resfuuqp69kgt.png" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enjoy your privacy :)&lt;/p&gt;

&lt;p&gt;PS: Code for my Dockerfile is &lt;a href="https://github.com/boris/docker/blob/master/tor/Dockerfile-alpine" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the image in Docker hub is &lt;a href="https://hub.docker.com/r/boris/tor" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>tor</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Ubuntu: Remove disabled snaps</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Thu, 11 Jul 2019 03:02:17 +0000</pubDate>
      <link>https://dev.to/boris/ubuntu-remove-disabled-snaps-2mfj</link>
      <guid>https://dev.to/boris/ubuntu-remove-disabled-snaps-2mfj</guid>
      <description>&lt;p&gt;In October 2015, Ubuntu 15.10 was shipped with something called &lt;code&gt;snappy&lt;/code&gt;, which is the "software deployment and package management system developed by Canonical" (copy/paste from &lt;a href="https://en.wikipedia.org/wiki/Snappy_(package_manager)"&gt;Wikipedia&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;By now, most of Ubuntu users are not aware of &lt;em&gt;snaps&lt;/em&gt; until they run a &lt;code&gt;df -h&lt;/code&gt; and they see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dev/loop1                   174M  174M     0 100% /snap/spotify/34
/dev/loop4                    55M   55M     0 100% /snap/core18/1049
/dev/loop3                   141M  141M     0 100% /snap/gnome-3-26-1604/88
/dev/loop5                   4.2M  4.2M     0 100% /snap/gnome-calculator/406
/dev/loop7                    89M   89M     0 100% /snap/core/7270
/dev/loop8                   2.8M  2.8M     0 100% /snap/telegram-cli/25
/dev/loop9                   1.0M  1.0M     0 100% /snap/gnome-logs/61
/dev/loop10                   36M   36M     0 100% /snap/gtk-common-themes/1198
/dev/loop11                  436M  436M     0 100% /snap/libreoffice/133
/dev/loop12                  150M  150M     0 100% /snap/gnome-3-28-1804/63
/dev/loop13                   89M   89M     0 100% /snap/core/7169
/dev/loop14                   57M   57M     0 100% /snap/snapcraft/3059
/dev/loop15                   15M   15M     0 100% /snap/gnome-characters/292
/dev/loop16                  181M  181M     0 100% /snap/spotify/35
/dev/loop17                  3.8M  3.8M     0 100% /snap/gnome-system-monitor/95
/dev/loop20                  141M  141M     0 100% /snap/gnome-3-26-1604/90
/dev/loop21                  419M  419M     0 100% /snap/libreoffice/134
/dev/loop2                   3.8M  3.8M     0 100% /snap/gnome-system-monitor/100
/dev/loop22                   15M   15M     0 100% /snap/gnome-characters/296
/dev/loop23                  150M  150M     0 100% /snap/gnome-3-28-1804/67
/dev/loop24                   43M   43M     0 100% /snap/gtk-common-themes/1313
/dev/loop0                    55M   55M     0 100% /snap/core18/1055

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

&lt;/div&gt;



&lt;p&gt;The thing is, when an snap is installed the previous version &lt;strong&gt;is not&lt;/strong&gt; uninstalled or removed, and you manually need to do that. Also, keep in mind that "updates" are, in fact, the install of a new version... So by doing the math, in a few months your &lt;code&gt;df -h&lt;/code&gt; will be a mess.&lt;/p&gt;

&lt;p&gt;To identify with more detail snaps installed in my computer, the best option is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ snap list --all                      
Name                  Version                     Rev   Tracking  Publisher       Notes
core                  16-2.39.3                   7270  stable    canonical✓      core
core                  16-2.39.2                   7169  stable    canonical✓      core,disabled
core18                20190627                    1049  stable    canonical✓      base,disabled
core18                20190704                    1055  stable    canonical✓      base
gnome-3-26-1604       3.26.0.20190705             90    stable/…  canonical✓      -
gnome-3-26-1604       3.26.0.20190621             88    stable/…  canonical✓      disabled
gnome-3-28-1804       3.28.0-10-gaa70833.aa70833  67    stable    canonical✓      -
gnome-3-28-1804       3.28.0-10-gaa70833.aa70833  63    stable    canonical✓      disabled
gnome-calculator      3.32.1                      406   stable/…  canonical✓      -
gnome-characters      v3.32.1+git2.3367201        292   stable/…  canonical✓      disabled
gnome-characters      v3.32.1+git2.3367201        296   stable/…  canonical✓      -
gnome-logs            3.32.0-4-ge8f3f37ca8        61    stable/…  canonical✓      -
gnome-system-monitor  3.32.1-2-ga7c19eaeff        95    stable/…  canonical✓      disabled
gnome-system-monitor  3.32.1-3-g0ea89b4922        100   stable/…  canonical✓      -
gtk-common-themes     0.1-16-g2287c87             1198  stable/…  canonical✓      disabled
gtk-common-themes     0.1-22-gab0a26b             1313  stable/…  canonical✓      -
libreoffice           6.2.5.2                     134   stable    canonical✓      -
libreoffice           6.2.5.2                     133   stable    canonical✓      disabled
snapcraft             3.6                         3059  stable    canonical✓      classic
spotify               1.1.5.153.gf614956d-16      35    stable    spotify✓        -
spotify               1.1.0.237.g378f6f25-11      34    stable    spotify✓        disabled
telegram-cli          1.4.5                       25    stable    marius-quabeck  -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's something interesting: The &lt;strong&gt;Notes&lt;/strong&gt; column. Maybe we can use that column to filter and remove unused or &lt;strong&gt;disabled&lt;/strong&gt; snaps? Yes, we can! And I do it with the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -eu

snap list --all | awk '/disabled/{print $1, $3}' |
    while read s r; do
        sudo snap remove "$s" --revision="$r"
    done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As usual, I hope it helps :)&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ubuntu</category>
      <category>snap</category>
    </item>
    <item>
      <title>Unlimited git repositories</title>
      <dc:creator>Boris Quiroz</dc:creator>
      <pubDate>Fri, 28 Jun 2019 18:54:35 +0000</pubDate>
      <link>https://dev.to/boris/unlimited-git-repositories-185e</link>
      <guid>https://dev.to/boris/unlimited-git-repositories-185e</guid>
      <description>&lt;p&gt;Many developers owns one or more instances in any of the many "cloud providers" out there. And most of them uses git to track their project. For this, github or gitlab are pretty good alternatives but, is there any other alternative?&lt;/p&gt;

&lt;p&gt;Yes, you can use nothing or go for Bitbucket or manage your own! Which is, in fact, something ridiculous simple and you just need to have an instance/virtual machine running anywhere &lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The process:
&lt;/h2&gt;

&lt;p&gt;In your local machine (read: your laptop), create your project repository and git init it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;local: ~ $ cd ~/Code/sample
local: ~/Code/sample $ git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, on your remote server let's init a git bare repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;remote: ~ $ mkdir ~/git
remote: ~ $ cd ~/git
remote: ~/git $ git init --bare sample.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, assuming that you can reach your remote service using a fancy name, like &lt;code&gt;dev.mydomain.io&lt;/code&gt;, let's configure our local using that name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;local: ~ $ git remote add origin boris@dev.mydomain.io:/git/sample.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing that, just use your git repository as usual.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Anywhere reachable by ssh ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>git</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
