<?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>Forem: Pratik Tamgole</title>
    <description>The latest articles on Forem by Pratik Tamgole (@patglitch).</description>
    <link>https://forem.com/patglitch</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%2F767921%2Fa21016bf-4060-4bc6-9bc1-46cda363dfc4.jpeg</url>
      <title>Forem: Pratik Tamgole</title>
      <link>https://forem.com/patglitch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/patglitch"/>
    <language>en</language>
    <item>
      <title>Enhanced CIDR Block Calculator with Expanded Input Formats in Go</title>
      <dc:creator>Pratik Tamgole</dc:creator>
      <pubDate>Tue, 07 Jan 2025 02:52:49 +0000</pubDate>
      <link>https://forem.com/patglitch/enhanced-cidr-block-calculator-with-expanded-input-formats-in-go-2259</link>
      <guid>https://forem.com/patglitch/enhanced-cidr-block-calculator-with-expanded-input-formats-in-go-2259</guid>
      <description>&lt;p&gt;Efficient management of IP address ranges is critical in network engineering, cloud infrastructure, and cybersecurity. CIDR (Classless Inter-Domain Routing) blocks provide a compact way to represent IP address ranges but handling them manually can be cumbersome. Enter the CIDR-Converter, a Go-based utility designed to simplify this process while supporting expanded input formats.&lt;/p&gt;

&lt;p&gt;Check out my repo here: &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/pat-glitch" rel="noopener noreferrer"&gt;
        pat-glitch
      &lt;/a&gt; / &lt;a href="https://github.com/pat-glitch/cidr-converter" rel="noopener noreferrer"&gt;
        cidr-converter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A CIDR block-converter
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;CIDR Convert&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A command-line utility written in Go that processes, validates, and merges IP address ranges in various formats. The tool supports CIDR notation, wildcard notation, and multiple input/output formats.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Input Processing&lt;/h3&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Multiple input formats supported:
&lt;ul&gt;
&lt;li&gt;CIDR notation (e.g., "192.168.1.0/24")&lt;/li&gt;
&lt;li&gt;Wildcard notation (e.g., "192.168.1.*")&lt;/li&gt;
&lt;li&gt;CSV files containing CIDR blocks&lt;/li&gt;
&lt;li&gt;JSON files containing CIDR blocks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Interactive stdin mode for manual input&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;CIDR Operations&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Validates IP ranges and CIDR blocks&lt;/li&gt;
&lt;li&gt;Converts wildcard notation to CIDR format&lt;/li&gt;
&lt;li&gt;Merges overlapping CIDR blocks&lt;/li&gt;
&lt;li&gt;Sorts CIDR blocks for optimal organization&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Output Handling&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Automatically saves merged results to JSON file&lt;/li&gt;
&lt;li&gt;Pretty-printed JSON output&lt;/li&gt;
&lt;li&gt;Comprehensive error handling and reporting&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Ensure you have Go installed on your system, then:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone [repository-url]
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; [repository-name]
go build&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;The tool supports three input modes:&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. Standard Input Mode&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;./cidr-processor
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Enter CIDR blocks interactively, one per line:&lt;/span&gt;
192.168.1.0/24
10.0.0.&lt;span class="pl-k"&gt;*&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Press Ctrl+D (Linux/Mac) or Ctrl+Z (Windows) to&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/pat-glitch/cidr-converter" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I'm also planning to create a web-app with additional features, to increase functionality and scope of the application!&lt;/p&gt;

&lt;p&gt;This project was inspired by Andy Walker's cidr-convert repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Flexible Input Formats
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Supports traditional CIDR notation (e.g., 192.168.0.0/24)&lt;/li&gt;
&lt;li&gt;Parses wildcard notations (e.g., 192.168.&lt;em&gt;.&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Converts binary strings into CIDR blocks (e.g., 11000000101010000000000000000000/24)&lt;/li&gt;
&lt;li&gt;Reads CIDRs from CSV and JSON files&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Intelligent Merging
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Merges overlapping CIDRs into a minimal set, reducing redundancy&lt;/li&gt;
&lt;li&gt;Aggregates smaller subnets into larger ones where feasible&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. File I/O Support
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Parses input from files or standard input&lt;/li&gt;
&lt;li&gt;Saves merged CIDRs to a JSON file for easy sharing and storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Problem It Solves
&lt;/h2&gt;

&lt;p&gt;Handling large lists of CIDRs can be tedious, especially when dealing with overlapping or adjacent ranges. Manually aggregating these ranges is error-prone and time-consuming. This tool automates the process, ensuring optimal aggregation and reducing the risk of mismanagement.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Functionalities
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. CIDR Parsing and Validation
&lt;/h4&gt;

&lt;p&gt;The parseCIDR function ensures input conforms to valid CIDR notation.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Wildcard and Binary Parsing
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Wildcards (e.g., 192.168.&lt;em&gt;.&lt;/em&gt;) are converted into CIDRs by analyzing the mask length&lt;/li&gt;
&lt;li&gt;Binary strings (e.g., 11000000101010000000000000000000/24) are translated into IP addresses&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. CIDR Merging
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The mergeCIDRs function removes redundancy by merging overlapping ranges&lt;/li&gt;
&lt;li&gt;The aggregateCIDRs function combines smaller subnets into larger, encompassing blocks&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. File Parsing
&lt;/h4&gt;

&lt;p&gt;Reads CIDRs from CSV and JSON formats using parseCSV and parseJSON functions.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Output
&lt;/h4&gt;

&lt;p&gt;The merged CIDRs are saved to a JSON file for easy consumption by other tools or teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Command-Line Execution
&lt;/h3&gt;

&lt;p&gt;Run the tool directly from the terminal, specifying input type:&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;# Standard input&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go
Enter CIDR blocks, one per line. Press Ctrl+D &lt;span class="o"&gt;(&lt;/span&gt;Linux/Mac&lt;span class="o"&gt;)&lt;/span&gt; or Ctrl+Z &lt;span class="o"&gt;(&lt;/span&gt;Windows&lt;span class="o"&gt;)&lt;/span&gt; to end input:
192.168.0.0/24
192.168.1.0/24

&lt;span class="c"&gt;# CSV Input&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go input.csv

&lt;span class="c"&gt;# JSON Input&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go input.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sample Output
&lt;/h3&gt;

&lt;p&gt;Given the input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.0.0/24
192.168.1.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool outputs a single aggregated block:&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="s2"&gt;"192.168.0.0/23"&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;p&gt;Saved to merged_cidrs.json.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Parsing Wildcard Notation
&lt;/h3&gt;

&lt;p&gt;Wildcards like 192.168.&lt;em&gt;.&lt;/em&gt; are converted into CIDRs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;parseWildcard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPNet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;wildcardRegex&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustCompile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`^((?:\d{1,3}|\*)\.){3}(?:\d{1,3}|\*)$`&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function calculates the appropriate prefix length and constructs a CIDR block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Merging and Aggregation
&lt;/h3&gt;

&lt;p&gt;The mergeCIDRs function eliminates redundancy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;mergeCIDRs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cidrs&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPNet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPNet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cidrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&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;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cidrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cidrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aggregation follows with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;aggregateCIDRs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cidrs&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPNet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPNet&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step combines adjacent ranges into larger blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  File Parsing
&lt;/h3&gt;

&lt;p&gt;CSV and JSON input files are parsed with parseCSV and parseJSON, enabling seamless integration with existing workflows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;parseCSV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPNet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Go?
&lt;/h2&gt;

&lt;p&gt;Go's robust standard library, including packages like net, regexp, and encoding/json, makes it an excellent choice for building network-related tools. Its strong concurrency model ensures high performance, even with large datasets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Enhancements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. IPv6 Support
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Extend functionality to handle IPv6 ranges&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Dynamic Input Formats
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add support for YAML and XML&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Web Interface
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build a lightweight web application for interactive CIDR management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Enhanced CIDR Block Calculator simplifies CIDR management with expanded input formats, intelligent merging, and robust file support. Its versatility makes it a valuable tool for network engineers, cloud architects, and cybersecurity professionals. Inspired by Andy Walker's cidr-convert, this tool builds upon foundational ideas to offer a more comprehensive solution. Give it a try and streamline your CIDR workflows today!&lt;/p&gt;

</description>
      <category>go</category>
      <category>cloud</category>
      <category>cli</category>
      <category>network</category>
    </item>
    <item>
      <title>Digital Ocean Kubernetes Challenge - 2021 -Deploying an internal Container registry.</title>
      <dc:creator>Pratik Tamgole</dc:creator>
      <pubDate>Mon, 27 Dec 2021 15:16:32 +0000</pubDate>
      <link>https://forem.com/patglitch/digital-ocean-kubernetes-challenge-2021-deploying-an-internal-container-registry-4624</link>
      <guid>https://forem.com/patglitch/digital-ocean-kubernetes-challenge-2021-deploying-an-internal-container-registry-4624</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;As Kubernetes doesn't provide an internal container registry, the DigitalOcean Kubernetes Challenge, challenged us to build one with the  help of tools like Trow or Harbor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this guide: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I will try and explain how to create a Kubernetes Cluster on DigitalOcean using terraform.&lt;/li&gt;
&lt;li&gt;Then I will deploy Trow in the same cluster as an internal container registry.&lt;/li&gt;
&lt;li&gt;Then I will deploy an Nginx sample application on the pod via trow.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites:
&lt;/h2&gt;

&lt;p&gt;As we will be working with &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DigitalOcean&lt;/li&gt;
&lt;li&gt;Kubernetes &lt;/li&gt;
&lt;li&gt;Terraform &lt;/li&gt;
&lt;li&gt;Trow
it is natural we will have to set them up on our host machine configured to our liking.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Now onto THE CHALLENGE! :
&lt;/h2&gt;

&lt;p&gt;Firstly set up a Personal Access Token on the API Page of DO console, just click on the "Generate New Token" button and voila a token with read and write privileges to your console will be generated! - So simple right!&lt;/p&gt;

&lt;p&gt;Export the newly generated token as :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export DigitalOcean_Token=tokenid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;In your project directory(I set it up as do-kubernetes-challenge-2021), make a terraform configuration file as &lt;strong&gt;yourfilename.tf&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Deploy the actual Kubernetes Cluster
    resource "digitalocean_kubernetes_cluster" "kubernetes_cluster" {
    name = "do-kubernetes-challenge"
    region = "blr1"
    version = "1.19.15-do.0"

    tags =["my-tag"]

    #This default node pool configuration is mandatory
    node_pool{
      name      = "default-pool"
      size      = "s-1vcpu-2gb" #minimum size, list available options with 'doctl compute size list'
      auto-scale    = false
      node_count    = 2
      tags      = ["node-pool-tag"]
      labels = {
        "pratiktamgole.xyz"="up"
      }
    }

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

&lt;/div&gt;



&lt;p&gt;Make an accompaning file known as provider.tf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform{
  reqiured_providers {
    digitalocean = {
        source ="digitalocean/digitalocean"
    version = "~&amp;gt;2.0"
     }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Perform Terraform Deployment :
&lt;/h2&gt;

&lt;p&gt;terraform init&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patglitch19@patglitch19-HP:~/do-kubernetes-challenge-2021$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of digitalocean/digitalocean from the dependency lock file
- Using previously-installed digitalocean/digitalocean v2.16.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

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

&lt;/div&gt;



&lt;p&gt;terraform plan&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patglitch19@patglitch19:~/do-kubernetes-challenge-2021$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # digitalocean_kubernetes_cluster.kubernetes_cluster will be created
  + resource "digitalocean_kubernetes_cluster" "kubernetes_cluster" {
      + cluster_subnet = (known after apply)
      + created_at     = (known after apply)
      + endpoint       = (known after apply)
      + ha             = false
      + id             = (known after apply)
      + ipv4_address   = (known after apply)
      + kube_config    = (sensitive value)
      + name           = "terraform-do-cluster"
      + region         = "blr1"
      + service_subnet = (known after apply)
      + status         = (known after apply)
      + surge_upgrade  = true
      + tags           = [
          + "my-tag",
        ]
      + updated_at     = (known after apply)
      + urn            = (known after apply)
      + version        = "1.19.15-do.0"
      + vpc_uuid       = (known after apply)

      + maintenance_policy {
          + day        = (known after apply)
          + duration   = (known after apply)
          + start_time = (known after apply)
        }

      + node_pool {
          + actual_node_count = (known after apply)
          + auto_scale        = false
          + id                = (known after apply)
          + labels            = {
              + "dev.to/patglitch" = "up"
            }
          + name              = "default-pool"
          + node_count        = 2
          + nodes             = (known after apply)
          + size              = "s-1vcpu-2gb"
          + tags              = [
              + "node-pool-tag",
            ]
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform
apply" now.

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

&lt;/div&gt;



&lt;p&gt;terraform apply --auto-approve&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021$ terraform apply --auto-approve

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # digitalocean_kubernetes_cluster.kubernetes_cluster will be created
  + resource "digitalocean_kubernetes_cluster" "kubernetes_cluster" {
      + cluster_subnet = (known after apply)
      + created_at     = (known after apply)
      + endpoint       = (known after apply)
      + ha             = false
      + id             = (known after apply)
      + ipv4_address   = (known after apply)
      + kube_config    = (sensitive value)
      + name           = "terraform-do-cluster"
      + region         = "blr1"
      + service_subnet = (known after apply)
      + status         = (known after apply)
      + surge_upgrade  = true
      + tags           = [
          + "my-tag",
        ]
      + updated_at     = (known after apply)
      + urn            = (known after apply)
      + version        = "1.19.15-do.0"
      + vpc_uuid       = (known after apply)

      + maintenance_policy {
          + day        = (known after apply)
          + duration   = (known after apply)
          + start_time = (known after apply)
        }

      + node_pool {
          + actual_node_count = (known after apply)
          + auto_scale        = false
          + id                = (known after apply)
          + labels            = {
              + "dev.to/patglitch" = "up"
            }
          + name              = "default-pool"
          + node_count        = 2
          + nodes             = (known after apply)
          + size              = "s-1vcpu-2gb"
          + tags              = [
              + "node-pool-tag",
            ]
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.
digitalocean_kubernetes_cluster.kubernetes_cluster: Creating...
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [10s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [20s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [30s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [40s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [50s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [1m0s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [1m10s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [1m20s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [1m30s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [1m40s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [1m50s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [2m0s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [2m10s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [2m20s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [2m30s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [2m40s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [2m50s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [3m0s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [3m10s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [3m20s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [3m30s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [3m40s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [3m50s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [4m0s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [4m10s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [4m20s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [4m30s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [4m40s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [4m50s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [5m0s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [5m10s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [5m20s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [5m30s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [5m40s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [5m50s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [6m0s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [6m10s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [6m20s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [6m30s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Still creating... [6m40s elapsed]
digitalocean_kubernetes_cluster.kubernetes_cluster: Creation complete after 6m47s [id=88b84043-6683-4342-b7e2-2d68a2a691d9]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

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

&lt;/div&gt;



&lt;p&gt;With the last command, we will be able to see the cluster forming on our DigitalOcean Cloud Console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ass7E32c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btgceupztgfsrxqqd0yg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ass7E32c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btgceupztgfsrxqqd0yg.png" alt="Image description" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect to the Kubernetes Cluster
&lt;/h2&gt;

&lt;p&gt;Now to connect to our newly formed cluster, we need to to download the kubeconfig file but first create an enviroment variable with our clusterID&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export CLUSTER_ID= CLUSTERID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the configuration file of the cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X GET -H "Content-Type:application/json" -H "Authorization:Bearer $DIGITALOCEAN_TOKEN" "https://api.digitalocean.com/v2/  kubernetes/clusters/$CLUSTER_ID/kubeconfig" &amp;gt; config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now set the KUBECONFIG enviroment variable to point to the downloaded config file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export KUBECONFIG=$(pwd)/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hooray! We've got out shiny new Kubernetes Cluster running on our DO Console Account. Now to deploy a registry running with TLS. We can check 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;patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021$ kubectl cluster-info
Kubernetes control plane is running at https://88b84043-6683-4342-b7e2-2d68a2a691d9.k8s.ondigitalocean.com
CoreDNS is running at https://88b84043-6683-4342-b7e2-2d68a2a691d9.k8s.ondigitalocean.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

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

&lt;/div&gt;



&lt;p&gt;clone the trow project repository :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:ContainerSolutions/trow.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;cd into the cloned folder :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd trow &amp;amp;&amp;amp; cd quick-install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Trow on your Cluster :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;-To check it was properly installed :&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 pod -A 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above commands will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021$ git clone git@github.com:ContainerSolutions/trow.git
Cloning into 'trow'...
Warning: Permanently added the ECDSA host key for IP address '13.234.176.102' to the list of known hosts.
remote: Enumerating objects: 7063, done.
remote: Counting objects: 100% (923/923), done.
remote: Compressing objects: 100% (492/492), done.
remote: Total 7063 (delta 554), reused 721 (delta 427), pack-reused 6140
Receiving objects: 100% (7063/7063), 2.89 MiB | 1.97 MiB/s, done.
Resolving deltas: 100% (4469/4469), done.
patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021$ cd trow
patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow$ ./install.sh
bash: ./install.sh: No such file or directory
patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow$ cd quick-install
patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow/quick-install$ ./install.sh
Trow AutoInstaller for Kubernetes
=================================

This installer assumes kubectl is configured to point to the cluster you want to
install Trow on and that your user has cluster-admin rights.

This installer will perform the following steps:

  - Create a ServiceAccount and associated Roles for Trow 
  - Create a Kubernetes Service and Deployment
  - Request and sign a TLS certificate for Trow from the cluster CA
  - Copy the public certificate to all nodes in the cluster
  - Copy the public certificate to this machine (optional)
  - Register a ValidatingAdmissionWebhook (optional) 

If you're running on GKE, you may first need to give your user cluster-admin
rights:

  $ kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value core/account)

Also make sure port 31000 is open on the firewall so clients can connect.
If you're running on the Google cloud, the following should work:

  $ gcloud compute firewall-rules create trow --allow tcp:31000 --project &amp;lt;project name&amp;gt;

This script will install Trow to the kube-public namespace.
To choose a different namespace run:
  $ ./install.sh &amp;lt;my-namespace&amp;gt;

Do you want to continue? (y/n) Y
Installing Trow in namespace: kube-public

Starting Kubernetes Resources
serviceaccount/trow created
role.rbac.authorization.k8s.io/trow created
clusterrole.rbac.authorization.k8s.io/trow created
rolebinding.rbac.authorization.k8s.io/trow created
clusterrolebinding.rbac.authorization.k8s.io/trow created
deployment.apps/trow-deploy created
service/trow created

Adding entry to /etc/hosts for trow.kube-public

Exposing registry via /etc/hosts
This requires sudo privileges
312
253
206.189.137.94 trow.kube-public # added for trow registry

Successfully configured localhost

Do you want to configure Trow as a validation webhook (NB this will stop external images from being deployed to the cluster)? (y/n) y
Setting up trow as a validating webhook
WARNING: This will limit what images can run in your cluster
By default, only images in Trow and official Kubernetes images will be 
allowed

validatingwebhookconfiguration.admissionregistration.k8s.io/trow-validator created

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

&lt;/div&gt;



&lt;p&gt;The script has set up the domain trow.kube-public to point at your cluster. We can now tag and push our local image with the following three commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow/quick-install$ docker pull nginx:latest
latest: Pulling from library/nginx
Digest: sha256:366e9f1ddebdb844044c2fafd13b75271a9f620819370f8971220c2b330a9254
Status: Image is up to date for nginx:latest
docker.io/library/nginx:latest
patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow/quick-install$ docker tag nginx:latest trow.kube-public:31000/nginx:test
patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow/quick-install$ docker push trow.kube-public:31000/nginx:test
The push refers to repository [trow.kube-public:31000/nginx]
51a4ac025eb4: Pushed 
4ded77d16e76: Pushed 
32359d2cd6cd: Pushed 
4270b63061e5: Pushed 
5f5f780b24de: Pushed 
2edcec3590a4: Pushed 
test: digest: sha256:8ba07d07b05bf4a026082b484ed143ab335cbe5295e13f567cde3440718dcd93 size: 1570

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

&lt;/div&gt;



&lt;p&gt;And finally run it inside Kubernetes! :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow/quick-install$ kubectl run trow-test --image=trow.kube-public:31000/nginx:test
pod/trow-test created
patglitch19@patglitch19-HP-Pavilion-15-Notebook-PC:~/do-kubernetes-challenge-2021/trow/quick-install$ kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
trow-test   1/1     Running   0          39s


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

&lt;/div&gt;



&lt;p&gt;Good Lord! I have done it!! &lt;br&gt;
And I hope you could follow this very easily and &lt;br&gt;
successfully deployed Trow onto your cluster and pushed the Nginx image into the registry, after following this post!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cloud</category>
      <category>digitalocean</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
