<?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: Kadir Belkuyu</title>
    <description>The latest articles on DEV Community by Kadir Belkuyu (@kadirbelkuyu).</description>
    <link>https://dev.to/kadirbelkuyu</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%2F871568%2Fe19b1c78-dd39-41b3-a86b-b0ed2b67b4ca.png</url>
      <title>DEV Community: Kadir Belkuyu</title>
      <link>https://dev.to/kadirbelkuyu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kadirbelkuyu"/>
    <language>en</language>
    <item>
      <title>The Kubernetes Context Switching Nightmare is Over</title>
      <dc:creator>Kadir Belkuyu</dc:creator>
      <pubDate>Tue, 09 Dec 2025 19:42:10 +0000</pubDate>
      <link>https://dev.to/kadirbelkuyu/the-kubernetes-context-switching-nightmare-is-over-1jkg</link>
      <guid>https://dev.to/kadirbelkuyu/the-kubernetes-context-switching-nightmare-is-over-1jkg</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fospax3akz66ifzetiba1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fospax3akz66ifzetiba1.gif" alt=" " width="1151" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you work with multiple Kubernetes clusters daily, you know the pain. Production, staging, development, that random test cluster someone spun up last month — they all live in your kubeconfig file, and switching between them feels like navigating a maze blindfolded.&lt;/p&gt;

&lt;p&gt;I got tired of it. So I built &lt;code&gt;kubecfg&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is kubecfg?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;kubecfg&lt;/code&gt; is a CLI tool that simplifies kubeconfig management. It lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add&lt;/strong&gt; new cluster configs with custom names&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;List&lt;/strong&gt; all your contexts at a glance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switch&lt;/strong&gt; contexts with optional namespace selection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage&lt;/strong&gt; namespaces interactively&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rename&lt;/strong&gt; contexts to something memorable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove&lt;/strong&gt; contexts you no longer need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge&lt;/strong&gt; multiple kubeconfig files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The killer feature? Interactive pickers with fuzzy selection. No more copy-pasting long context names.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Demo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Switching Context with Namespace
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mermaid.live/edit#pako:eNqtkF9vmzAUxb-K5T4ujQAXEnjYRPjTpJGqSe0eNuiDBxeCQjCyTdo0zXefQ7wkU6Vpq8ID8oFzfvf4bnHGcsAeLmr2nC0ol-gxTBukHj9J8bL7CVlRok4ASjLWSHiRT-i6Qcma1h08pVip689osp2J_eeipiVqOQho5JfdgTPZO97u2RsKkofnSmYLpEmINfXm6dz1HcQbCrchgx63oGtAFPWzfuPCkzFKHkCihq5AtDQDJJmazdZVDjnS_c4i-wZx8sirsgSOKtWA00xWasKJ0FbZEriOxf3VbpMY9p2PJoEKzlZorlbDG5BK-19nOnLbR6ZJWIm2pps_pgioQZ1Yo73T3jtLvglV5_BTnKZoU9Sb7pJAb0z0C1T3-4Tuj60FSG2fHewHEfRi_i6rvYe3kJsakI-Kqq69qxvfNSJrICRnS_CurMgOxr6W189VLhee1b4MMlYz7l0VRXEOmWhIbPuORY6QwByFpvkOcp4MP5yMddI1TBJHx6QzMeJg9K_Fby8BmV4CMrsEJNKQURQSyzxC7NgnpvvXbd59ODn_ryQe4JJXOfYKWgsY4BXwFd1rvN1DUywXsIIUe-qYQ0G7WqY4bXYq19LmB2Mr7EneqSRnXbk4cro2pxLCipacnizQ5MAD1jUSe25PwN4Wv2DPtI2hbatduzYZEWKQAd5gj9jW0CHEJpYzconlGvZugF_7mcbQGVnOjTt2DDK2jLFh7n4BE8qrBQ" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNqtkF9vmzAUxb-K5T4ujQAXEnjYRPjTpJGqSe0eNuiDBxeCQjCyTdo0zXefQ7wkU6Vpq8ID8oFzfvf4bnHGcsAeLmr2nC0ol-gxTBukHj9J8bL7CVlRok4ASjLWSHiRT-i6Qcma1h08pVip689osp2J_eeipiVqOQho5JfdgTPZO97u2RsKkofnSmYLpEmINfXm6dz1HcQbCrchgx63oGtAFPWzfuPCkzFKHkCihq5AtDQDJJmazdZVDjnS_c4i-wZx8sirsgSOKtWA00xWasKJ0FbZEriOxf3VbpMY9p2PJoEKzlZorlbDG5BK-19nOnLbR6ZJWIm2pps_pgioQZ1Yo73T3jtLvglV5_BTnKZoU9Sb7pJAb0z0C1T3-4Tuj60FSG2fHewHEfRi_i6rvYe3kJsakI-Kqq69qxvfNSJrICRnS_CurMgOxr6W189VLhee1b4MMlYz7l0VRXEOmWhIbPuORY6QwByFpvkOcp4MP5yMddI1TBJHx6QzMeJg9K_Fby8BmV4CMrsEJNKQURQSyzxC7NgnpvvXbd59ODn_ryQe4JJXOfYKWgsY4BXwFd1rvN1DUywXsIIUe-qYQ0G7WqY4bXYq19LmB2Mr7EneqSRnXbk4cro2pxLCipacnizQ5MAD1jUSe25PwN4Wv2DPtI2hbatduzYZEWKQAd5gj9jW0CHEJpYzconlGvZugF_7mcbQGVnOjTt2DDK2jLFh7n4BE8qrBQ%3Ftype%3Dpng" width="733" height="1254"&gt;&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;kubecfg use &lt;span class="nt"&gt;-n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. One command. It shows you an interactive context picker, then asks which namespace you want. Both selections happen in one flow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Select context
  minikube
▸ production-eks
  staging-gke
  dev-local

✓ production-eks

Select namespace
  default
  kube-system
▸ backend-services
  frontend
  monitoring

✓ backend-services

Switched to context 'production-eks' with namespace 'backend-services'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you just want to switch context without the namespace prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg use production-eks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need a specific namespace directly?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg use production-eks &lt;span class="nt"&gt;-n&lt;/span&gt; backend-services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-n&lt;/code&gt; flag is smart. Use it without a value for interactive selection, or pass a namespace directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Homebrew (macOS)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap kadirbelkuyu/tap
brew &lt;span class="nb"&gt;install &lt;/span&gt;kadirbelkuyu/tap/kubecfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Go Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/kadirbelkuyu/kubecfg@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  From Source
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kadirbelkuyu/kubecfg.git
&lt;span class="nb"&gt;cd &lt;/span&gt;kubecfg
go build &lt;span class="nt"&gt;-o&lt;/span&gt; kubecfg &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;kubecfg /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Commands in Detail
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Adding a New Cluster
&lt;/h3&gt;

&lt;p&gt;When you download a kubeconfig from AWS EKS, GCP GKE, or Azure AKS, the context names are usually terrible. Something like &lt;code&gt;arn:aws:eks:us-east-1:123456789:cluster/my-cluster&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;With &lt;code&gt;kubecfg&lt;/code&gt;, you can import it with a sensible name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg add ~/Downloads/eks-config.yaml &lt;span class="nt"&gt;--name&lt;/span&gt; production-eks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original file stays untouched. The context gets added to your main kubeconfig with the name you chose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Listing All Contexts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CURRENT  NAME            CLUSTER         SERVER                              NAMESPACE
*        production-eks  production-eks  https://xxx.eks.amazonaws.com       backend
         staging-gke     staging-gke     https://xxx.gke.googleapis.com      -
         dev-local       minikube        https://192.168.49.2:8443           default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean, tabular output. The asterisk shows your current context. Namespace shows what's configured, or &lt;code&gt;-&lt;/code&gt; if using default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive Context Switching
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg use
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No arguments needed. An interactive picker appears. Use arrow keys to navigate, Enter to select.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Select context
  minikube
▸ production-eks
  staging-gke

✓ production-eks

Switched to context 'production-eks'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Namespace Management
&lt;/h3&gt;

&lt;p&gt;Switch namespace for your current context:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Interactive picker pulls namespaces directly from 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;Select namespace
  default
  kube-system
▸ backend-services
  monitoring

✓ backend-services

Namespace set to 'backend-services'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or set it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg ns kube-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check current namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg ns current
&lt;span class="c"&gt;# Output: backend-services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Renaming Contexts
&lt;/h3&gt;

&lt;p&gt;That auto-generated context name bugging you?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg rename arn:aws:eks:us-east-1:123456789:cluster/prod production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean and simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  Removing Contexts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg remove old-cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll get a confirmation prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Remove context 'old-cluster'? [y/N]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skip the prompt with &lt;code&gt;--force&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg remove old-cluster &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Merging Configs
&lt;/h3&gt;

&lt;p&gt;Got kubeconfig files scattered everywhere?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubecfg merge config1.yaml config2.yaml config3.yaml &lt;span class="nt"&gt;-o&lt;/span&gt; merged.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All contexts, clusters, and users get combined into one file. Duplicates are handled gracefully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mermaid.live/edit#pako:eNqtk8uK2zAYhV9FKNCVE3QZ37Qo-EoXUyhddDH2LIQtO6ayFRSZmTTk3as4qpmSzSzihfCvc853QEhn2KhWQAY7qd6aPdcGPP-sJ2C_BFeNmrqhx7sTH-Ur2G6_grT6wfVRgC_gF5dDy414dW7i3OSj22nUafReS5chq74L3QvwrPqhccRsUfIqF-18kENju0AxGT2Io3Pki6OovvGplQJktsP6zD-5WOSyGq_o9lZ9U27r0ZxsKsGgG6Rkm6ckRgXxjkar34JtSOFnUeLG7dvQmj0jh3evUVJptum67j8KeQiFPoKSOkjpJwGhKyTDYY7xHeRjMnPJGGFaFmsySFGZhZ-tzx8BKRwkzTEq0AqJUpQk0WchpYOERU4JXiF-mVAc30GgB3s9tJB1XB6FB-21Gfl1hucrtIZmL0ZRQ2Z_W9HxWZoa1tPF5g58elFqhMzo2Sa1mvv9ypkP12eSD7zXfFx3tZhaoTM1TwYyTBcGZGf4bicf7XzfHl_s05BSZMUTZNQnu4BSn5IgjCmJkX_x4J-lFe2CkARPcRQgGhEUIXz5C9QTMNI" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNqtk8uK2zAYhV9FKNCVE3QZ37Qo-EoXUyhddDH2LIQtO6ayFRSZmTTk3as4qpmSzSzihfCvc853QEhn2KhWQAY7qd6aPdcGPP-sJ2C_BFeNmrqhx7sTH-Ur2G6_grT6wfVRgC_gF5dDy414dW7i3OSj22nUafReS5chq74L3QvwrPqhccRsUfIqF-18kENju0AxGT2Io3Pki6OovvGplQJktsP6zD-5WOSyGq_o9lZ9U27r0ZxsKsGgG6Rkm6ckRgXxjkar34JtSOFnUeLG7dvQmj0jh3evUVJptum67j8KeQiFPoKSOkjpJwGhKyTDYY7xHeRjMnPJGGFaFmsySFGZhZ-tzx8BKRwkzTEq0AqJUpQk0WchpYOERU4JXiF-mVAc30GgB3s9tJB1XB6FB-21Gfl1hucrtIZmL0ZRQ2Z_W9HxWZoa1tPF5g58elFqhMzo2Sa1mvv9ypkP12eSD7zXfFx3tZhaoTM1TwYyTBcGZGf4bicf7XzfHl_s05BSZMUTZNQnu4BSn5IgjCmJkX_x4J-lFe2CkARPcRQgGhEUIXz5C9QTMNI%3Ftype%3Dpng" width="784" height="172"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Deep Dive
&lt;/h2&gt;

&lt;p&gt;I built &lt;code&gt;kubecfg&lt;/code&gt; with Clean Architecture principles. Not because it's trendy, but because I wanted the codebase to be maintainable and testable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubecfg/
├── cmd/                    # CLI commands (Cobra)
│   ├── root.go
│   ├── add.go
│   ├── list.go
│   ├── use.go
│   ├── ns.go
│   ├── remove.go
│   ├── rename.go
│   └── merge.go
├── internal/
│   ├── domain/             # Core business entities
│   │   ├── kubeconfig.go
│   │   ├── repository.go
│   │   └── errors.go
│   ├── application/        # Business logic
│   │   └── service.go
│   └── infrastructure/     # External implementations
│       ├── file_repository.go
│       └── kubernetes_client.go
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://mermaid.live/edit#pako:eNqdVl1um0AQvgravDoJhuAfVEXC2JasOG2VtA8t7gPGg70KsGhZkrhRblC1UtWX9qXX6Hl6gfYIXVh-1jaNYiPZ7Mw33yw7-83CA_LIApCJltSNV8qbwSxS-JWkc-GYRD51E0ZTj6UUnBn6-_Pbpy2vMnXXQGfog-Bmlz2dOPyn2CQM3WiRvJjT03ObzKmrjKkbwh2hN1L4GAdwBTFxykGCGaHrnPXOupwqk9NXUvhFL7EDDBFzLtI50AgYFI6cwWHFej0pCBAtxGBrZVYcB9hzGSYRX9bvH9___PoiOxtWdQ30FnvgFPd8skGa4AiSRJmSJfak4LcJ2CRicM-ceignu8PMW728dooBr0oSux5IIZdAl-Dk_5zv42UigVcQcYojbrvpryAktxmc3Tbh_1VkSEIXR_kef_1cWA1VGEUMMwyJYxO-96Ulbw_fFPG8Tj2UxRGkCQPKmXTtyIYcI564iJGMzQoXSarRRgFiMuE86vOiOrWolMopr4lSQhOnWLOwmquVqfr4-LzUgnCWst1FKqnuQoWRA7VCdrFSKLtIroxdt5BEkz_TgvDXE-ZQuYsFqZixAcqnbPCLORuBbNIGoLRyqNZJAyhLpAmW1NEAV9powDY00oALIWw0C1sHsH3--TgIzKPuaKhr7RZ3kxswj4yxpbf7hXl8hxdsZerxvZxGPm1Ejr7a1sejKkdnoI7t7pM5CskK-pnVV0daRddGht2znqRnchZcqzfqWNuPL4dWIn9mfC39ZxJKrYpwu9sdjsfbpfBIQKh55Pu-zJTUvD-5Uvv-VNEN-_OKbjmEmHfT_sRK1oVW7UF_1NsWSjO17s0DyHLvHkKXevsAetX7B3A3zoYD-OLseCYRtfgHGF4g03eDBFooBMrbmtvoIcs5Q2wF_EhHJh8uwHfTgM3QLHrkvNiN3hMSIpMfR5xJSbpcVXnSeOEyGGKXv-HDykv5Ow2oTdKIIVNT8xzIfED3yGwb6olh8GOob-hdXVf1FlojUze0k46uG7rW6fZ1ra8ajy30MZ9VPel0tc5Zv9dR9Z6m9tT24z9sV1FM" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNqdVl1um0AQvgravDoJhuAfVEXC2JasOG2VtA8t7gPGg70KsGhZkrhRblC1UtWX9qXX6Hl6gfYIXVh-1jaNYiPZ7Mw33yw7-83CA_LIApCJltSNV8qbwSxS-JWkc-GYRD51E0ZTj6UUnBn6-_Pbpy2vMnXXQGfog-Bmlz2dOPyn2CQM3WiRvJjT03ObzKmrjKkbwh2hN1L4GAdwBTFxykGCGaHrnPXOupwqk9NXUvhFL7EDDBFzLtI50AgYFI6cwWHFej0pCBAtxGBrZVYcB9hzGSYRX9bvH9___PoiOxtWdQ30FnvgFPd8skGa4AiSRJmSJfak4LcJ2CRicM-ceignu8PMW728dooBr0oSux5IIZdAl-Dk_5zv42UigVcQcYojbrvpryAktxmc3Tbh_1VkSEIXR_kef_1cWA1VGEUMMwyJYxO-96Ulbw_fFPG8Tj2UxRGkCQPKmXTtyIYcI564iJGMzQoXSarRRgFiMuE86vOiOrWolMopr4lSQhOnWLOwmquVqfr4-LzUgnCWst1FKqnuQoWRA7VCdrFSKLtIroxdt5BEkz_TgvDXE-ZQuYsFqZixAcqnbPCLORuBbNIGoLRyqNZJAyhLpAmW1NEAV9powDY00oALIWw0C1sHsH3--TgIzKPuaKhr7RZ3kxswj4yxpbf7hXl8hxdsZerxvZxGPm1Ejr7a1sejKkdnoI7t7pM5CskK-pnVV0daRddGht2znqRnchZcqzfqWNuPL4dWIn9mfC39ZxJKrYpwu9sdjsfbpfBIQKh55Pu-zJTUvD-5Uvv-VNEN-_OKbjmEmHfT_sRK1oVW7UF_1NsWSjO17s0DyHLvHkKXevsAetX7B3A3zoYD-OLseCYRtfgHGF4g03eDBFooBMrbmtvoIcs5Q2wF_EhHJh8uwHfTgM3QLHrkvNiN3hMSIpMfR5xJSbpcVXnSeOEyGGKXv-HDykv5Ow2oTdKIIVNT8xzIfED3yGwb6olh8GOob-hdXVf1FlojUze0k46uG7rW6fZ1ra8ajy30MZ9VPel0tc5Zv9dR9Z6m9tT24z9sV1FM%3Ftype%3Dpng" width="784" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Layer
&lt;/h3&gt;

&lt;p&gt;Pure Go structs representing kubeconfig structure:&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;type&lt;/span&gt; &lt;span class="n"&gt;KubeConfig&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;APIVersion&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Kind&lt;/span&gt;           &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;CurrentContext&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Clusters&lt;/span&gt;       &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;ClusterEntry&lt;/span&gt;
    &lt;span class="n"&gt;Contexts&lt;/span&gt;       &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;ContextEntry&lt;/span&gt;
    &lt;span class="n"&gt;Users&lt;/span&gt;          &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;UserEntry&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No dependencies on external packages. Just the core data model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Layer
&lt;/h3&gt;

&lt;p&gt;Business logic lives here. The &lt;code&gt;Service&lt;/code&gt; struct handles all operations:&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;type&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Repository&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;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;UseContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contextName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="kt"&gt;string&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="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&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;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contextName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;idx&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrContextNotFound&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contextName&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;namespace&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;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&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;The service doesn't know how configs are stored or loaded. It works with the repository interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure Layer
&lt;/h3&gt;

&lt;p&gt;Concrete implementations for file I/O and Kubernetes API calls:&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;type&lt;/span&gt; &lt;span class="n"&gt;FileRepository&lt;/span&gt; &lt;span class="k"&gt;struct&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;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;FileRepository&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="n"&gt;path&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;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KubeConfig&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KubeConfig&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrInvalidConfig&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Kubernetes client fetches namespaces directly from the cluster for the interactive picker:&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;type&lt;/span&gt; &lt;span class="n"&gt;KubernetesClient&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;kubeconfigPath&lt;/span&gt; &lt;span class="kt"&gt;string&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;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;KubernetesClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ListNamespaces&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&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;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;clientcmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BuildConfigFromFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubeconfigPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;clientset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewForConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;namespaceList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;clientset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CoreV1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespaces&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
        &lt;span class="n"&gt;metav1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListOptions&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;namespaces&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespaceList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&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;ns&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;namespaceList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;namespaces&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;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&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;namespaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Smart Namespace Flag
&lt;/h2&gt;

&lt;p&gt;One feature I'm particularly proud of is the &lt;code&gt;-n&lt;/code&gt; flag behavior on the &lt;code&gt;use&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;The challenge: How do you make a single flag that can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do nothing (just switch context)&lt;/li&gt;
&lt;li&gt;Trigger interactive selection&lt;/li&gt;
&lt;li&gt;Accept a direct value&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cobra's &lt;code&gt;NoOptDefVal&lt;/code&gt; made this possible:&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;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;useCmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringVarP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;namespaceFlag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="s"&gt;"set namespace (use -n without value for interactive selection)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;useCmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoOptDefVal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"__interactive__"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the flag works three ways:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kubecfg use prod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch context only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kubecfg use prod -n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch context + interactive namespace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kubecfg use prod -n backend&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch context + set namespace&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The resolution logic is clean:&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;resolveNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cobra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contextName&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Changed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"namespace"&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="s"&gt;""&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;namespaceFlag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"__interactive__"&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;selectNamespaceForContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contextName&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;namespaceFlag&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;

&lt;p&gt;I defined domain-specific errors that are meaningful to users:&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;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ErrConfigNotFound&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"kubeconfig file not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ErrContextNotFound&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"context not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ErrContextExists&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"context already exists"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ErrInvalidConfig&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"invalid kubeconfig format"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ErrNoCurrentContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"no current context set"&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;When something goes wrong, you get a clear message instead of a stack trace.&lt;/p&gt;




&lt;h2&gt;
  
  
  Backup System
&lt;/h2&gt;

&lt;p&gt;Before any modification, &lt;code&gt;kubecfg&lt;/code&gt; creates a timestamped backup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.kube/config.backup.20241208-143022
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accidentally removed the wrong context? Your backup is right there.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go 1.24&lt;/strong&gt; - Fast compilation, single binary output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cobra&lt;/strong&gt; - Industry standard CLI framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;promptui&lt;/strong&gt; - Beautiful interactive prompts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;client-go&lt;/strong&gt; - Official Kubernetes client library&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;yaml.v3&lt;/strong&gt; - YAML parsing with proper type handling&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;I've been working with Kubernetes for years. The tooling around kubeconfig management always felt like an afterthought. You either use kubectl's verbose commands or install multiple tools for context and namespace management.&lt;/p&gt;

&lt;p&gt;I wanted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;One tool&lt;/strong&gt; that handles both context and namespace&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive pickers&lt;/strong&gt; that actually pull from the cluster&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean output&lt;/strong&gt; that's easy to read&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe operations&lt;/strong&gt; with backups and confirmations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensible codebase&lt;/strong&gt; that I can maintain&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;kubecfg&lt;/code&gt; is the result. It's the tool I wish I had when I started working with multiple clusters.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;A few things on my roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shell completions&lt;/strong&gt; - Bash, Zsh, Fish&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Config validation&lt;/strong&gt; - Detect broken references&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context groups&lt;/strong&gt; - Organize contexts by environment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export command&lt;/strong&gt; - Extract a single context to a file&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Out
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/kadirbelkuyu/kubecfg@latest
kubecfg use &lt;span class="nt"&gt;-n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is open source. Star the repo if you find it useful, and feel free to open issues or PRs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/kadirbelkuyu/kubecfg" rel="noopener noreferrer"&gt;github.com/kadirbelkuyu/kubecfg&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building developer tools is satisfying in a way that application development sometimes isn’t. You’re solving real problems you face daily. Every feature comes from actual pain points.&lt;/p&gt;

&lt;p&gt;If you manage multiple Kubernetes clusters, give kubecfg a try. And if you've built similar tools to scratch your own itch, I'd love to hear about them&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow me for more Kubernetes and Go content. If you found this useful, a clap or share helps others discover the tool.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18yqx1czm7k932iezh0p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18yqx1czm7k932iezh0p.gif" alt=" " width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Conventional Commits</title>
      <dc:creator>Kadir Belkuyu</dc:creator>
      <pubDate>Sun, 16 Nov 2025 12:20:18 +0000</pubDate>
      <link>https://dev.to/kadirbelkuyu/conventional-commits-3g3h</link>
      <guid>https://dev.to/kadirbelkuyu/conventional-commits-3g3h</guid>
      <description>&lt;h2&gt;
  
  
  Conventional Commits Rehberi
&lt;/h2&gt;

&lt;p&gt;Bu rehber, &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;https://www.conventionalcommits.org/en/v1.0.0/&lt;/a&gt; adresi referans alınarak hazırlanmıştır.&lt;/p&gt;

&lt;h2&gt;
  
  
  Temel Yapı
&lt;/h2&gt;

&lt;p&gt;Her commit mesajı şu formata uygun olmalıdır:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;

[optional body]

[optional footer(s)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bileşenler
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;type:&lt;/strong&gt; Yaptığınız değişikliğin türünü belirtir.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;scope (opsiyonel):&lt;/strong&gt; Değişikliğin hangi bölümünü etkilediğini belirtir.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;description:&lt;/strong&gt; Değişikliğin kısa ve öz açıklaması.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;body (opsiyonel):&lt;/strong&gt; Daha detaylı açıklama yapılabilir.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;footer (opsiyonel):&lt;/strong&gt; Ek bilgiler veya referanslar içerir.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Type (Tür)
&lt;/h2&gt;

&lt;p&gt;Kullanabileceğiniz commit türleri şöyledir:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Açıklama&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;feat&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yeni bir özellik eklendi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;fix&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bir hata düzeltildi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;docs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dokümantasyon güncellendi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;style&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kod formatı veya stil değişiklikleri (işlevsel olmayan)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;refactor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kod yeniden düzenlendi, işlev değişmedi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;test&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Testler eklendi veya güncellendi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;chore&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yapılandırma/bakım gibi diğer değişiklikler&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Scope (Opsiyonel)
&lt;/h2&gt;

&lt;p&gt;Scope, değişikliğin hangi alanı etkilediğini belirtir. Örnekler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;feat(login)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fix(database)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs(readme)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;style(css)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scope tamamen isteğe bağlıdır ancak büyük projelerde anlaşılabilirlik sağlar.&lt;/p&gt;




&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;Description, commit mesajının en kritik kısmıdır.&lt;br&gt;
&lt;strong&gt;Kısa, öz ve eylem odaklı olmalıdır.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Örnek:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(auth): kullanıcı girişi özelliği eklendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Body (Opsiyonel)
&lt;/h2&gt;

&lt;p&gt;Body kısmı, değişiklik hakkında daha fazla detay vermek için kullanılır.&lt;/p&gt;

&lt;p&gt;Örnek:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api): ürün listeleme endpointi güncellendi

Yeni filtreleme parametreleri eklendi:
- category
- price_range
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Footer (Opsiyonel)
&lt;/h2&gt;

&lt;p&gt;Footer genellikle şu amaçlarla kullanılır:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Breaking Changes
&lt;/h3&gt;

&lt;p&gt;Önceki sürümlerle uyumsuz değişiklikler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BREAKING CHANGE: auth token yapısı tamamen yenilendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Issue Referansları
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Closes #123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Örnek Commit Mesajları
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(login): kullanıcı adı ve şifre ile giriş imkanı eklendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(database): veritabanı bağlantı hatası düzeltildi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs(readme): kurulum talimatları eklendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;style(css): stiller yeniden düzenlendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;refactor(api): kod daha modüler hale getirildi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test(unit): yeni birim testleri eklendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chore(deps): bağımlılıklar güncellendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Silme ve Ekleme İşlemleri
&lt;/h2&gt;

&lt;p&gt;Silme veya ekleme işlemleri yine type üzerinden ifade edilir.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ekleme:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  feat(feature): yeni özellik eklendi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Silme/fix:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  fix(bug): hatalı kod kaldırıldı
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Commit Mesajlarının İngilizce Olması
&lt;/h2&gt;

&lt;p&gt;Mesajlar Türkçe olabilir ancak uluslararası projelerde &lt;strong&gt;İngilizce kullanılmalıdır&lt;/strong&gt;.&lt;br&gt;
Bu standart, ekipler ve open-source projelerde iletişimi kolaylaştırır.&lt;/p&gt;




&lt;h2&gt;
  
  
  Daha Fazla Bilgi
&lt;/h2&gt;

&lt;p&gt;Detaylı dokümantasyon için:&lt;br&gt;
&lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;https://www.conventionalcommits.org/en/v1.0.0/&lt;/a&gt;&lt;/p&gt;




</description>
      <category>git</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Beginner’s Journey into Ansible: The Ultimate Guide</title>
      <dc:creator>Kadir Belkuyu</dc:creator>
      <pubDate>Mon, 20 Mar 2023 05:11:27 +0000</pubDate>
      <link>https://dev.to/kadirbelkuyu/a-beginners-journey-into-ansible-the-ultimate-guide-3aln</link>
      <guid>https://dev.to/kadirbelkuyu/a-beginners-journey-into-ansible-the-ultimate-guide-3aln</guid>
      <description>&lt;p&gt;&lt;strong&gt;Embark on your path to mastering IT automation with Ansible’s versatile and user-friendly capabilities&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
Ansible has emerged as a leading open-source solution for IT automation, allowing users to efficiently manage and configure their infrastructure. By simplifying repetitive tasks, streamlining configuration updates, and facilitating application deployment, Ansible has become an indispensable tool for many. In this comprehensive guide, we’ll explore the foundations of Ansible, delve into its critical components, and demonstrate how to craft a basic playbook to automate tasks on your servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ansible: An Overview&lt;/li&gt;
&lt;li&gt;Installing Ansible&lt;/li&gt;
&lt;li&gt;Organizing Hosts with Inventory Files&lt;/li&gt;
&lt;li&gt;Mastering Ad-Hoc Commands&lt;/li&gt;
&lt;li&gt;Playbooks, Roles, and Their Significance&lt;/li&gt;
&lt;li&gt;Crafting Your First Playbook&lt;/li&gt;
&lt;li&gt;Best Practices for Success&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;1. Ansible: An Overview&lt;/strong&gt;&lt;br&gt;
As a powerful automation platform, Ansible simplifies complex tasks and enhances server and application management. Some of its key advantages include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No agent requirements&lt;/li&gt;
&lt;li&gt;Human-readable YAML playbooks&lt;/li&gt;
&lt;li&gt;A vast array of modules&lt;/li&gt;
&lt;li&gt;Compatibility with tools like Docker, Kubernetes, and Terraform&lt;/li&gt;
&lt;li&gt;Customizability via modules and plugins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Installing Ansible&lt;/strong&gt;&lt;br&gt;
To set up Ansible on your control machine (typically your local computer), follow the instructions below:&lt;br&gt;
&lt;em&gt;For Ubuntu/Debian:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt update $ sudo apt install ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;For CentOS/RHEL:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo yum install epel-release $ sudo yum install ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;For macOS:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew install ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Organizing Hosts with Inventory Files&lt;/strong&gt;&lt;br&gt;
To define the hosts you’ll manage, Ansible employs inventory files. Create a file named &lt;code&gt;inventory.ini&lt;/code&gt; and list your hosts in the format shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[webservers]
web1.example.com
web2.example.com

[dbservers]
db1.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Mastering Ad-Hoc Commands&lt;/strong&gt;&lt;br&gt;
Ad-hoc commands enable you to complete swift tasks on your hosts without the need for a playbook. For instance, to check the uptime of all web servers, execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ansible web_servers -i inventory.ini -m command -a "uptime" -u &amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Playbooks, Roles, and Their Significance&lt;/strong&gt;&lt;br&gt;
Playbooks are the heart of Ansible. These YAML files detail the tasks and configurations to apply to your hosts. Roles, on the other hand, are sets of tasks and variables that can be reused throughout multiple playbooks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Crafting Your First Playbook&lt;/strong&gt;&lt;br&gt;
Create a file named &lt;code&gt;update_packages.yml&lt;/code&gt; and insert the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
- name: Update packages on all servers
  hosts: all
  become: yes
  tasks:
    - name: Update package list
      ansible.builtin.apt:
        update_cache: yes

    - name: Upgrade packages
      ansible.builtin.apt:
        upgrade: safe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;To execute the playbook, use this command:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ansible-playbook -i inventory.ini update_packages.yml -u &amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7. Best Practices for Success&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintain modular and reusable playbooks&lt;/li&gt;
&lt;li&gt;Leverage roles to structure your tasks&lt;/li&gt;
&lt;li&gt;Secure sensitive data with Ansible Vault&lt;/li&gt;
&lt;li&gt;Utilize Git for version control and collaboration&lt;/li&gt;
&lt;li&gt;Employ CI/CD pipelines for automated testing and deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;8. Final Thoughts&lt;/strong&gt;&lt;br&gt;
Ansible’s powerful capabilities have made it a go-to tool for IT infrastructure management. By following&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ansible</category>
    </item>
    <item>
      <title>Dockerize edilmiş PostgreSQL veritabanını yedekleme</title>
      <dc:creator>Kadir Belkuyu</dc:creator>
      <pubDate>Thu, 17 Nov 2022 08:22:42 +0000</pubDate>
      <link>https://dev.to/kadirbelkuyu/dockerize-edilmis-postgresql-veritabanini-yedekleme-1cl5</link>
      <guid>https://dev.to/kadirbelkuyu/dockerize-edilmis-postgresql-veritabanini-yedekleme-1cl5</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
Bir PostgreSQL veritabanını yedeklemek ve geri yüklemek, herhangi bir sistem yöneticisi için önemli bir görevdir. Bu görevi kolaylaştıran psql yardımcı programları pg_dump ve pg_restore sayesinde bu işlem çok kısa bir sürede hallolabiliyor.&lt;/p&gt;

&lt;p&gt;Bu yardımcı programları kullanarak sistem yöneticileri, yerel olarak veya uzaktan sürekli bir yedekleme oluşturabilir.&lt;/p&gt;

&lt;p&gt;PostgreSQL, yaygın olarak kullanılan ilişkisel bir veritabanı sistemidir. Açık kaynaklıdır ve görevleri hızlı bir şekilde gerçekleştirmek için çok çeşitli araçlar sunar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pg_dump&lt;/strong&gt;&lt;br&gt;
pg_dumpbir PostgreSQL veritabanını komutudur. Veritabanını bir komut dosyasına veya başka bir arşiv dosyasına çıkarır. Bu yardımcı program veritabanlarını yedeklemek içindir. Yardımcı program, veritabanı aynı anda kullanılıyor olsa bile tutarlı yedeklemeler yapar. Okuyucular, yazarlar ve diğer kullanıcılar veritabanını kullanırken engellenmeyecektir pg_dump.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pg_restore&lt;/strong&gt;&lt;br&gt;
pg_restore — pg_dump tarafından oluşturulan bir arşiv dosyasından bir PostgreSQL veritabanını geri yüklemeye yarayan psql yardımcı programıdır. İki kodunda detaylı kullanımı aşağıdaki kodlarda gösterilmiştir.&lt;/p&gt;

&lt;p&gt;NOT: Aşağıdaki kodlar docker container ile yedekleme işlemi için değildir.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pg_dump [connection-option…] [option…] [dbname]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;pg_dump örnekleri:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# testdb veritabanını sql biçiminde kaydetmek
pg_dump testdb &amp;gt; db.sql

# testdb veri tabanını tar biçiminde yedeklemek
pg_dump -U postgres -F c testdb &amp;gt; testdb.tar

# testdb veri tabanını bir dizin biçiminde yedeklemek
pg_dump -U postgres -F d testdb &amp;gt; db1_backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;pg_restore örnekleri&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pg_restore -U postgres -Ft -d db &amp;lt; db.tar&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;pg_dumpall örnekleri:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# dumpall tüm veritabanını yedekliyecektir.
pg_dumpall -f dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql

#dump_date kullanımında cihazın tarih ve saat bilgilerini alarak dosya ismi olarak atar bu sayede karışıklılık olmadan yedekleme işlemini gerçekleştirebilirsiniz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;PostgreSQL veritabanını Docker tarafında yedeğini almanın bir çok yolu vardır. Bu yazıda en az uğraştırıcı olan ve ilerde otomatik bir şekilde günlük yedek almak istersenin kullanabileceğiz kodları paylaşacağım. Otomatik günlük veritabanı yedeği içinde bir çok yol bulunmaktadır. Yine en basit yöntem olarak yazacağınız script için cron job oluşturabilirsiniz. Bu yazıda Backup almak için bir bash dosyasıda kullanacağız.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Docker ile psql yedeği alma ve yedeği yükleme:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# pg_dumpall (yedeği alma)
# container name postgreSQL container ismidir. container ismini öğrenmek için:
# docker images komutunu kullanabilirsiniz.
docker exec -t container_Name pg_dumpall -c -U postgres &amp;gt; dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql

# pg_restore (veri tabanı yedeği yükleme)
cat dump.sql | docker exec -i container_Name psql -U postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restore işlemi CLI tarafında yazdığımız kodlardan biraz farklı bununsebebi Docker.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bash dosyası:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#! /usr/bin/env bash
CONTAINER_NAME=PostgreSQLContainerName
# pg_dumpall için database ismi gerekmiyor 
DATABASE_NAME=Your_db

if [ -z $CONTAINER_NAME ]
then
echo "Usage: $0 [container name] [database name]"
exit 1
fi

if [ -z $DATABASE_NAME ]
then
echo "Usage: $0 [container name] [database name]"
exit 1
fi

set -e
set -o pipefail

# backups yedek klasörünü oluşturma 
mkdir -p "./backups"

cd backups

# PostgreSQL veri tabanı yedeği oluşturma 
# bu satırda pg_dump kullanıp istediğiniz veri tabanın yedekleyebilirsiniz
docker exec -t "$CONTAINER_NAME" pg_dumpall -c -U postgres &amp;gt; dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql

echo ""
echo "Exporting file from container..."
echo "Done!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>postgres</category>
      <category>linux</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
