<?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: Hamid Haghdoost</title>
    <description>The latest articles on DEV Community by Hamid Haghdoost (@haamid).</description>
    <link>https://dev.to/haamid</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%2F586876%2F4dc21a11-884a-41ed-ba6f-16e119f90a4d.jpg</url>
      <title>DEV Community: Hamid Haghdoost</title>
      <link>https://dev.to/haamid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/haamid"/>
    <language>en</language>
    <item>
      <title>PHP Attributes: Modern Metadata in Your Code</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Thu, 11 Sep 2025 13:56:52 +0000</pubDate>
      <link>https://dev.to/haamid/php-attributes-modern-metadata-in-your-code-4g98</link>
      <guid>https://dev.to/haamid/php-attributes-modern-metadata-in-your-code-4g98</guid>
      <description>&lt;p&gt;Since PHP 8, we’ve had &lt;strong&gt;attributes&lt;/strong&gt; — a modern way to add metadata directly to classes, methods, or properties. Think of them like annotations in Java or decorators in Python.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔖 What are attributes?
&lt;/h3&gt;

&lt;p&gt;Attributes let you “tag” parts of your code with extra information. Frameworks or libraries can then read these tags at runtime and act on them.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="na"&gt;#[Route('/home', methods: ['GET'])]&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomeController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;Route&lt;/code&gt; attribute describes how this controller should be exposed.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚙️ How do you define an attribute?
&lt;/h3&gt;

&lt;p&gt;Attributes are just classes marked with &lt;code&gt;#[Attribute]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="na"&gt;#[Attribute]&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$methods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🔍 How to read attributes with Reflection
&lt;/h3&gt;

&lt;p&gt;You can fetch and use attributes at runtime via the &lt;strong&gt;Reflection API&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$reflection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ReflectionClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HomeController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Get all attributes on the class&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$reflection&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Turn attribute into a real object&lt;/span&gt;
    &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$attr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;newInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// "/home"&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "GET"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how frameworks like Symfony or Doctrine process metadata and apply logic automatically.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Why use attributes?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Cleaner than PHPDoc comments&lt;/li&gt;
&lt;li&gt;More flexible than marker interfaces&lt;/li&gt;
&lt;li&gt;Supported natively by PHP, no hacks needed&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🏛️ Where are they used?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Symfony&lt;/strong&gt; → &lt;code&gt;#[Route]&lt;/code&gt; for controllers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Doctrine ORM&lt;/strong&gt; → &lt;code&gt;#[Entity]&lt;/code&gt;, &lt;code&gt;#[Column]&lt;/code&gt; for database mapping&lt;/li&gt;
&lt;li&gt;Custom apps → logging, caching, validation rules&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🔑 &lt;strong&gt;In short:&lt;/strong&gt; Attributes bring structured, modern metadata to PHP. They’re concise, powerful, and built right into the language — and with reflection, they let your code adapt based on annotations.&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>symfony</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Freed Up Tons of Storage on My Mac</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Sun, 24 Aug 2025 10:25:26 +0000</pubDate>
      <link>https://dev.to/haamid/how-i-freed-up-tons-of-storage-on-my-mac-3gif</link>
      <guid>https://dev.to/haamid/how-i-freed-up-tons-of-storage-on-my-mac-3gif</guid>
      <description>&lt;p&gt;My Mac was almost full. It said that &lt;strong&gt;“Documents” used 39 GB&lt;/strong&gt;, but I didn’t know what was taking so much space. As a software developer, I have tools like &lt;strong&gt;npm, Docker, and Homebrew&lt;/strong&gt; that keep files to work faster. These files can get very big. Here’s how I fixed it.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Look at Documents&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I checked my Documents folder in Finder, but the files there were much smaller than 39 GB. Then I used Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; ~/Documents/&lt;span class="k"&gt;*&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows the size of each file and folder. Most were small. So the big files were &lt;strong&gt;hidden in caches and tools&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Clear developer tool caches&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;npm (Node.js)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; ~/.npm
npm cache clean &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This freed &lt;strong&gt;3.5 GB&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker system &lt;span class="nb"&gt;df
&lt;/span&gt;docker builder prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My Docker cache alone was &lt;strong&gt;19 GB&lt;/strong&gt;!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Homebrew&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; ~/Library/Caches/Homebrew
brew cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This cleared hundreds of MBs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;VSCode&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/Library/Application&lt;span class="se"&gt;\ &lt;/span&gt;Support/Code/Cache/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/Library/Application&lt;span class="se"&gt;\ &lt;/span&gt;Support/Code/CachedData/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/Library/Application&lt;span class="se"&gt;\ &lt;/span&gt;Support/Code/User/workspaceStorage/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This freed about &lt;strong&gt;5 GB&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Remove old tools you don’t use&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I had old versions of PHP and some apps I didn’t use. I removed them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew uninstall php@7.1 php@7.4 php@8.0
brew uninstall &lt;span class="nt"&gt;--cask&lt;/span&gt; fig
brew uninstall nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Check other caches&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Other tools also store caches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python pip: &lt;code&gt;~/.cache/pip&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go modules: &lt;code&gt;~/go/pkg/mod/cache&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;iCloud: &lt;code&gt;~/Library/Mobile Documents&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check their size with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; &amp;lt;folder&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Step 5: Keep it clean&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I now run these commands every few weeks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm cache clean &lt;span class="nt"&gt;--force&lt;/span&gt;
docker builder prune
brew cleanup
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/Library/Caches/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps my Mac from filling up again.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Lessons learned&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Most big storage is &lt;strong&gt;hidden in caches&lt;/strong&gt;, not in Documents.&lt;/li&gt;
&lt;li&gt;Tools like Docker, npm, Homebrew, and VSCode can use &lt;strong&gt;lots of GB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Cleaning regularly can free &lt;strong&gt;20–40 GB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Terminal commands like &lt;code&gt;du -sh&lt;/code&gt; and &lt;code&gt;docker system df&lt;/code&gt; help find big files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these steps, my Mac now has plenty of space and runs better.&lt;/p&gt;

</description>
      <category>npm</category>
      <category>php</category>
      <category>node</category>
      <category>docker</category>
    </item>
    <item>
      <title>Kubernetes Service Account and RBAC Tutorial</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Thu, 16 Jan 2025 13:37:02 +0000</pubDate>
      <link>https://dev.to/haamid/kubernetes-service-account-and-rbac-tutorial-2a6d</link>
      <guid>https://dev.to/haamid/kubernetes-service-account-and-rbac-tutorial-2a6d</guid>
      <description>&lt;h1&gt;
  
  
  Kubernetes Service Account and RBAC Tutorial
&lt;/h1&gt;

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

&lt;p&gt;In this tutorial, we created a Service Account with a Role and RoleBinding for read-only access to Pods. You can find the source code in the &lt;a href="https://github.com/hamidhaghdoost/k8s-service-account-tutorial" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Service Account in Kubernetes?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Service Account&lt;/strong&gt; in Kubernetes is a special type of account that is used by processes or applications running inside &lt;strong&gt;Pods&lt;/strong&gt; to authenticate and interact with the Kubernetes API. Unlike &lt;strong&gt;User Accounts&lt;/strong&gt;, which are typically associated with human users, &lt;strong&gt;Service Accounts&lt;/strong&gt; are designed for non-human access. They are used to grant specific permissions to applications, allowing them to interact with the Kubernetes cluster in a controlled and secure way.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does a Service Account Work?
&lt;/h3&gt;

&lt;p&gt;Service accounts provide a mechanism for granting &lt;strong&gt;RBAC (Role-Based Access Control)&lt;/strong&gt; permissions to Pods and workloads. Each service account has a set of &lt;strong&gt;credentials&lt;/strong&gt; (a token) that is automatically generated by Kubernetes. This token is mounted into the container running inside a Pod, which allows the application to authenticate itself against the Kubernetes API.&lt;/p&gt;

&lt;p&gt;Through the service account, Kubernetes manages the &lt;strong&gt;access control&lt;/strong&gt; for specific resources (such as Pods, Services, ConfigMaps, etc.), based on the &lt;strong&gt;Role&lt;/strong&gt; or &lt;strong&gt;ClusterRole&lt;/strong&gt; associated with the account. These roles define what actions the service account can perform on different resources within the cluster.&lt;/p&gt;

&lt;p&gt;In essence, a &lt;strong&gt;Service Account&lt;/strong&gt; acts as an identity for the applications or workloads running inside your Kubernetes Pods. By linking it with roles and permissions, Kubernetes enables fine-grained access control, ensuring that each service only has access to the resources it needs.&lt;/p&gt;




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

&lt;p&gt;Before starting this tutorial, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Kubernetes cluster&lt;/strong&gt; (either local or on a cloud provider).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kubectl&lt;/strong&gt; installed and configured to access the cluster.&lt;/li&gt;
&lt;li&gt;Basic knowledge of &lt;strong&gt;Kubernetes Pods&lt;/strong&gt; and &lt;strong&gt;RBAC&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Create a Service Account
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Service Account&lt;/strong&gt; is an identity for processes running inside Pods. It allows Pods to authenticate and interact with the Kubernetes API.&lt;/p&gt;

&lt;p&gt;First, create a file named &lt;code&gt;service-account.yaml&lt;/code&gt; to define the Service Account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;print-read-service-account&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service-account-test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file defines a service account named &lt;code&gt;print-read-service-account&lt;/code&gt; in the &lt;code&gt;service-account-test&lt;/code&gt; namespace.&lt;/p&gt;

&lt;p&gt;To apply the Service Account to your Kubernetes cluster, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; service-account.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Create a Role with Read Access to Pods
&lt;/h2&gt;

&lt;p&gt;In Kubernetes, a &lt;strong&gt;Role&lt;/strong&gt; defines what resources can be accessed within a specific namespace and what actions can be performed. Here, we'll create a Role that grants &lt;strong&gt;read-only access&lt;/strong&gt; to &lt;strong&gt;pods&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;role.yaml&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt; 
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read-role&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service-account-test&lt;/span&gt;
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Role grants permission to &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;list&lt;/code&gt; &lt;strong&gt;pods&lt;/strong&gt; in the &lt;code&gt;service-account-test&lt;/code&gt; namespace.&lt;/p&gt;

&lt;p&gt;To apply the Role, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; role.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Create a RoleBinding to Bind the Role to the Service Account
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;RoleBinding&lt;/strong&gt; is used to bind a Role to a specific &lt;strong&gt;Service Account&lt;/strong&gt;. This allows the service account to use the permissions defined in the Role.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;role-binding.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RoleBinding&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read-role-binding&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service-account-test&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;print-read-service-account&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service-account-test&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read-role&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This RoleBinding binds the &lt;code&gt;read-role&lt;/code&gt; to the &lt;code&gt;print-read-service-account&lt;/code&gt; service account.&lt;/p&gt;

&lt;p&gt;To apply the RoleBinding, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; role-binding.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Create a Pod that Uses the Service Account
&lt;/h2&gt;

&lt;p&gt;Now, create a &lt;strong&gt;Pod&lt;/strong&gt; that uses the &lt;code&gt;print-read-service-account&lt;/code&gt; service account to access Kubernetes resources. This Pod will use the &lt;strong&gt;kubectl&lt;/strong&gt; command to list &lt;strong&gt;pods&lt;/strong&gt; and &lt;strong&gt;services&lt;/strong&gt; in the cluster.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;pod-with-service-account.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-with-service-account&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service-account-test&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;print-read-service-account&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;print-reader-container&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bitnami/kubectl:latest&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sh'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-c'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;kubectl&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;get&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pods&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;kubectl&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;get&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;services'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Pod runs a container with the &lt;strong&gt;kubectl&lt;/strong&gt; image. The container executes the command &lt;code&gt;kubectl get pods &amp;amp;&amp;amp; kubectl get services&lt;/code&gt;, which will attempt to retrieve both Pods and Services in the cluster.&lt;/p&gt;

&lt;p&gt;To apply the Pod, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; pod-with-service-account.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5: Verify the Pod Logs
&lt;/h2&gt;

&lt;p&gt;Once the Pod is created, you can check the logs of the Pod to verify that it can read &lt;strong&gt;pods&lt;/strong&gt; and &lt;strong&gt;services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs pod-with-service-account &lt;span class="nt"&gt;-n&lt;/span&gt; service-account-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Output:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NAME                       READY   STATUS    RESTARTS        AGE
pod-with-service-account   1/1     Running   6 &lt;span class="o"&gt;(&lt;/span&gt;2m48s ago&lt;span class="o"&gt;)&lt;/span&gt;   5m47s
Error from server &lt;span class="o"&gt;(&lt;/span&gt;Forbidden&lt;span class="o"&gt;)&lt;/span&gt;: services is forbidden: User &lt;span class="s2"&gt;"system:serviceaccount:service-account-test:print-read-service-account"&lt;/span&gt; cannot list resource &lt;span class="s2"&gt;"services"&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;API group &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;the namespace &lt;span class="s2"&gt;"service-account-test"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;p&gt;In the log above, the &lt;code&gt;kubectl&lt;/code&gt; command successfully lists the &lt;strong&gt;pods&lt;/strong&gt;, but it encounters an error when trying to list the &lt;strong&gt;services&lt;/strong&gt;. The error message indicates that the service account &lt;code&gt;print-read-service-account&lt;/code&gt; does not have permission to access the &lt;code&gt;services&lt;/code&gt; resource. This is because the Role only grants access to &lt;strong&gt;pods&lt;/strong&gt; and not &lt;strong&gt;services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To fix this, you need to update the Role to grant read access to both &lt;strong&gt;pods&lt;/strong&gt; and &lt;strong&gt;services&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Update the Role to Access Services
&lt;/h2&gt;

&lt;p&gt;Edit the &lt;code&gt;role.yaml&lt;/code&gt; file to include access to &lt;strong&gt;services&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt; 
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read-role&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service-account-test&lt;/span&gt;
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;services"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reapply the updated Role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; role.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when you check the Pod logs again, you should see both &lt;strong&gt;pods&lt;/strong&gt; and &lt;strong&gt;services&lt;/strong&gt; listed.&lt;/p&gt;

&lt;p&gt;By default, a Kubernetes &lt;strong&gt;Service Account&lt;/strong&gt; has access only to resources within the namespace it is created in. This means that the &lt;code&gt;print-read-service-account&lt;/code&gt; in our example can only interact with resources like Pods and Services within the &lt;code&gt;service-account-test&lt;/code&gt; namespace. If you want the service account to have access to resources in other namespaces, you need to use a &lt;strong&gt;ClusterRole&lt;/strong&gt; and &lt;strong&gt;ClusterRoleBinding&lt;/strong&gt; instead of a &lt;strong&gt;Role&lt;/strong&gt; and &lt;strong&gt;RoleBinding&lt;/strong&gt;. A &lt;strong&gt;ClusterRole&lt;/strong&gt; grants access to resources across the entire cluster, and a &lt;strong&gt;ClusterRoleBinding&lt;/strong&gt; allows you to bind the ClusterRole to a service account across multiple namespaces or cluster-wide.&lt;/p&gt;




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

&lt;p&gt;In this tutorial, you learned how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;Service Account&lt;/strong&gt; for use by a Kubernetes Pod.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;Role&lt;/strong&gt; that grants read-only access to Pods.&lt;/li&gt;
&lt;li&gt;Bind the Role to the Service Account using a &lt;strong&gt;RoleBinding&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Deploy a Pod that uses the Service Account to interact with Kubernetes resources.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By following these steps, you can control access to Kubernetes resources securely using &lt;strong&gt;RBAC&lt;/strong&gt; and &lt;strong&gt;Service Accounts&lt;/strong&gt;, ensuring that applications only have access to the resources they need.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" rel="noopener noreferrer"&gt;Kubernetes RBAC Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" rel="noopener noreferrer"&gt;Kubernetes Service Accounts Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>development</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Hashicorp Vault Agent Tutorial: Generating .env from Vault Secrets</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Thu, 02 Jan 2025 14:35:16 +0000</pubDate>
      <link>https://dev.to/haamid/hashicorp-vault-agent-tutorial-generating-env-from-vault-secrets-3e87</link>
      <guid>https://dev.to/haamid/hashicorp-vault-agent-tutorial-generating-env-from-vault-secrets-3e87</guid>
      <description>&lt;p&gt;In this tutorial, we will set up Vault Agent to generate a &lt;code&gt;.env&lt;/code&gt; file with secrets from HashiCorp Vault. We’ll use the AppRole authentication method to securely authenticate and retrieve secrets, then write them to an environment file for use in your application.&lt;/p&gt;

&lt;p&gt;You can find the complete configuration files and setup used in this tutorial in the &lt;a href="https://github.com/hamidhaghdoost/vault-agent-tutorial" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Important Note:&lt;/strong&gt; This tutorial uses Vault in development mode (&lt;code&gt;-dev&lt;/code&gt;) for simplicity. Development mode is &lt;strong&gt;not secure&lt;/strong&gt; and should only be used for testing and learning purposes. In a production environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a properly initialized and unsealed Vault server.&lt;/li&gt;
&lt;li&gt;Secure the Vault server with TLS certificates and access control.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Vault server running (in development mode for testing)&lt;/li&gt;
&lt;li&gt;Vault Agent installed and configured&lt;/li&gt;
&lt;li&gt;Basic knowledge of Vault and its authentication methods&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Start Vault Server in Development Mode
&lt;/h2&gt;

&lt;p&gt;We’ll start Vault in development mode for testing purposes. This will make Vault accessible via &lt;code&gt;127.0.0.1:8200&lt;/code&gt; with a root token.&lt;/p&gt;

&lt;p&gt;Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault server &lt;span class="nt"&gt;-dev&lt;/span&gt; &lt;span class="nt"&gt;-dev-root-token-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root &lt;span class="nt"&gt;-dev-tls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then export &lt;code&gt;VAULT_ADDR&lt;/code&gt; and &lt;code&gt;VAULT_CACERT&lt;/code&gt; from the output of previous command to give the ability to cli to have access to Vault server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'https://127.0.0.1:8200'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_CACERT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/tmp/vault-tls900287623/vault-ca.pem'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And create two dummy secrets as username and password of a database that later we want to write them in a env variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault kv put secret/dbinfo &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root &lt;span class="nv"&gt;pass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;test123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access Vault’s UI by navigating to &lt;a href="https://127.0.0.1:8200" rel="noopener noreferrer"&gt;https://127.0.0.1:8200&lt;/a&gt; and logging in with the &lt;code&gt;root&lt;/code&gt; token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Set Up the AppRole Authentication Method
&lt;/h2&gt;

&lt;p&gt;We will use AppRole for authentication. First, enable the AppRole authentication method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault auth &lt;span class="nb"&gt;enable &lt;/span&gt;approle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create a new AppRole and attach a policy that allows reading from the &lt;code&gt;secret/data/dbinfo&lt;/code&gt; path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create the Vault policy (&lt;code&gt;agent-policy.hcl&lt;/code&gt;)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="s2"&gt;"secret/data/dbinfo"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;capabilities&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"read"&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;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Write the policy&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault policy write agent-policy agent-policy.hcl
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create the AppRole and attach the policy&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault write auth/approle/role/vault-agent-role &lt;span class="nv"&gt;policies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"agent-policy"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate the &lt;code&gt;role_id&lt;/code&gt; and &lt;code&gt;secret_id&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault &lt;span class="nb"&gt;read &lt;/span&gt;auth/approle/role/vault-agent-role/role-id
vault write &lt;span class="nt"&gt;-f&lt;/span&gt; auth/approle/role/vault-agent-role/secret-id
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;role_id&lt;/code&gt; and &lt;code&gt;secret_id&lt;/code&gt; are required to authenticate via AppRole. Save these values to the files &lt;code&gt;role_id&lt;/code&gt; and &lt;code&gt;secret_id&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Configure Vault Agent
&lt;/h2&gt;

&lt;p&gt;The Vault Agent configuration file (&lt;code&gt;vault-agent.hcl&lt;/code&gt;) will authenticate with Vault using the AppRole and generate a &lt;code&gt;.env&lt;/code&gt; file with the secret values. Here’s an example configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Vault Agent configuration&lt;/span&gt;
&lt;span class="nx"&gt;vault&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://127.0.0.1:8200"&lt;/span&gt;
  &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;client_token&amp;gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;auto_auth&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="s2"&gt;"approle"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mount_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"auth/approle"&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;role_id_file_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./role_id"&lt;/span&gt;
      &lt;span class="nx"&gt;secret_id_file_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./secret_id"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;sink&lt;/span&gt; &lt;span class="s2"&gt;"file"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./vault-agent-token"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./env-template.tmpl"&lt;/span&gt;
  &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./.env"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;role_id_file_path&lt;/code&gt; and &lt;code&gt;secret_id_file_path&lt;/code&gt; point to the files containing the AppRole credentials.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;template&lt;/code&gt; block specifies the path to the &lt;code&gt;env-template.tmpl&lt;/code&gt; file and the destination for the generated &lt;code&gt;.env&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Create the Template File (&lt;code&gt;env-template.tmpl&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Create a template file (&lt;code&gt;env-template.tmpl&lt;/code&gt;) that Vault Agent will use to generate the &lt;code&gt;.env&lt;/code&gt; file. Here’s an example template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_USER={{ with secret "secret/data/dbinfo" }}{{ .Data.data.user }}{{ end }}
DB_PASS={{ with secret "secret/data/dbinfo" }}{{ .Data.data.pass }}{{ end }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This template will insert the &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;pass&lt;/code&gt; from the Vault secrets into the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Start Vault Agent
&lt;/h2&gt;

&lt;p&gt;Now, we will start the Vault Agent to authenticate and generate the &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault agent &lt;span class="nt"&gt;-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./vault-agent.hcl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vault Agent will authenticate using AppRole, retrieve the secret from &lt;code&gt;secret/data/dbinfo&lt;/code&gt;, and generate the &lt;code&gt;.env&lt;/code&gt; file at the specified location.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Check the Generated &lt;code&gt;.env&lt;/code&gt; File
&lt;/h2&gt;

&lt;p&gt;After Vault Agent runs, the &lt;code&gt;.env&lt;/code&gt; file will be populated with the secrets from Vault:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_USER=root
DB_PASS=test123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file can now be used to set environment variables for your application.&lt;/p&gt;

&lt;p&gt;Your final files should be 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;agent-policy.hcl
env-template.tmpl
role_id
secret_id
vault-agent.hcl
vault-agent.pid
vault-agent-token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this tutorial, we’ve configured Vault Agent to authenticate with Vault using AppRole, retrieve secrets, and generate a &lt;code&gt;.env&lt;/code&gt; file. This is a simple and secure way to manage sensitive configuration data in your application.&lt;/p&gt;

&lt;p&gt;I hope this tutorial helps you get Vault Agent running smoothly. Happy coding! 🚀&lt;/p&gt;

</description>
      <category>vault</category>
      <category>dotenv</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>A Simple Guide to Choosing Licenses for Your Projects</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Fri, 13 Dec 2024 08:41:14 +0000</pubDate>
      <link>https://dev.to/haamid/a-simple-guide-to-choosing-licenses-for-your-projects-fmn</link>
      <guid>https://dev.to/haamid/a-simple-guide-to-choosing-licenses-for-your-projects-fmn</guid>
      <description>&lt;p&gt;If you are confused about licenses like me, &lt;a href="https://www.gnu.org/licenses/license-recommendations.html" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; helps you decide on licenses for software, documentation, and other practical works. Here, I’ll provide a simplified (but probably not entirely accurate) version of it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;General Rule of Thumb&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you’re modifying an existing project, stick with its original license unless you have a really good reason to change it.
&lt;/li&gt;
&lt;li&gt;If you do switch licenses, make sure it’s allowed and make it clear which parts use which license.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;For Software&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;GNU GPL (General Public License)&lt;/strong&gt; for most projects to make sure users have the freedom to use, share, and modify your work.
&lt;/li&gt;
&lt;li&gt;For small programs (under 300 lines), use &lt;strong&gt;Apache License 2.0&lt;/strong&gt;—it's simpler and less restrictive.
&lt;/li&gt;
&lt;li&gt;For server software, pick &lt;strong&gt;GNU AGPL (Affero GPL)&lt;/strong&gt; to ensure users can access the source code even when running online.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;For Libraries&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;LGPL (Lesser GPL)&lt;/strong&gt; if you expect proprietary software to use your library.
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;GPL&lt;/strong&gt; for libraries with specialized or unique use cases.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;For Documentation&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;GNU Free Documentation License (GFDL)&lt;/strong&gt; for big works like manuals.
&lt;/li&gt;
&lt;li&gt;For smaller docs, use a simpler license like &lt;strong&gt;GNU all-permissive license&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;For Icons, Fonts, and Other Works&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If these are part of a software project, use the same license as the software.
&lt;/li&gt;
&lt;li&gt;If they’re standalone, go for a &lt;strong&gt;Creative Commons Attribution-ShareAlike (CC BY-SA)&lt;/strong&gt; license to keep them free and shareable.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Copyleft is a way to make sure that software (or other creative works) remains free for everyone to use, share, and modify. It works by allowing anyone to use your work, but with the condition that if they make changes and share it, they must also make those changes available under the same free terms.&lt;/p&gt;

&lt;p&gt;In simpler terms: it’s like sharing your recipe with friends, but telling them that if they make changes to it, they also have to share the updated recipe in the same way. This ensures that the work stays open and free for everyone.&lt;/p&gt;

&lt;p&gt;And that’s pretty much it! The GNU Project recommends these licenses to keep your work free and accessible. If you’re still unsure, you can always contact their licensing team. 😊&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>software</category>
      <category>gnu</category>
    </item>
    <item>
      <title>Run Gitlab CI jobs on a specific runner</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Thu, 31 Oct 2024 09:18:07 +0000</pubDate>
      <link>https://dev.to/haamid/run-gitlab-ci-jobs-on-a-specific-runner-563i</link>
      <guid>https://dev.to/haamid/run-gitlab-ci-jobs-on-a-specific-runner-563i</guid>
      <description>&lt;p&gt;I have two runners in my project. One is on Microsoft Azure for Azure deployments, and the other is on DigitalOcean for its deployments. Today, I realized that all of my jobs are being handled by the Azure runner, causing our tests to take too much time due to significant network delay when connecting to the database across data centers.&lt;/p&gt;

&lt;p&gt;Therefore, I needed to configure specific jobs to run on designated runners. Here, I’ll explain how to do that.&lt;/p&gt;

&lt;p&gt;To assign a specific GitLab Runner to a job in your GitLab CI/CD pipeline, use the &lt;code&gt;tags&lt;/code&gt; keyword in the job definition in your &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file. You’ll need to add a unique tag to the runner configuration in GitLab and then reference that tag in the job configuration. Here’s how:&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Add a Tag to the Runner
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to your project’s &lt;strong&gt;Settings &amp;gt; CI / CD&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Runners&lt;/strong&gt;, locate the runner you want to assign to your job.&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Edit&lt;/strong&gt; (pencil icon) next to the runner and add a unique tag (for example, &lt;code&gt;azure-runner&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Use the Tag in Your &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Add the same tag to your job definition in the &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "Running job on an Azure runner"&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;azure-runner&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explanation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;tags&lt;/strong&gt;: By specifying the &lt;code&gt;azure-runner&lt;/code&gt; tag, GitLab ensures this job will only be picked up by runners that have this tag.&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%2F3cxyxdn51usddhm3e5qx.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%2F3cxyxdn51usddhm3e5qx.png" alt=" " width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if you take a look at your job on GitLab, you will see that it is assigned to the specific runner you specified.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>cicd</category>
      <category>azure</category>
      <category>docker</category>
    </item>
    <item>
      <title>Install Docker and Docker Compose by single command and use it without sudo :)</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Fri, 08 Sep 2023 16:09:05 +0000</pubDate>
      <link>https://dev.to/haamid/install-docker-and-docker-compose-by-single-command-and-use-it-without-sudo--c37</link>
      <guid>https://dev.to/haamid/install-docker-and-docker-compose-by-single-command-and-use-it-without-sudo--c37</guid>
      <description>&lt;p&gt;I know it looks crazy but to be honest I am frustrated of searching "install docker ubuntu" and copy paste lots of commands every time. If it happens for you a lot, you can bookmark &lt;a href="https://gist.github.com/tuytoosh/b700f17f3ee3ad7f20d533e61de31c56" rel="noopener noreferrer"&gt;this gist&lt;/a&gt; and just copy and paste it to install docker, compose and post installation commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done  &amp;amp;&amp;amp;
sudo apt-get update &amp;amp;&amp;amp;
sudo apt-get install ca-certificates curl gnupg &amp;amp;&amp;amp;
sudo install -m 0755 -d /etc/apt/keyrings &amp;amp;&amp;amp;
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg &amp;amp;&amp;amp;
sudo chmod a+r /etc/apt/keyrings/docker.gpg &amp;amp;&amp;amp;
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release &amp;amp;&amp;amp; echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
sudo apt-get update &amp;amp;&amp;amp;
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin &amp;amp;&amp;amp;
sudo groupadd docker &amp;amp;&amp;amp; 
sudo usermod -aG docker $USER &amp;amp;&amp;amp; 
newgrp docker &amp;amp;&amp;amp; 
sudo docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A shorter way
&lt;/h3&gt;

&lt;p&gt;If you don't want to copy such a long command you can easily run this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; /bin/bash -c "$(curl -s https://gist.githubusercontent.com/tuytoosh/b700f17f3ee3ad7f20d533e61de31c56/raw)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It downloads the gist and runs the commands after getting root password.&lt;br&gt;
You can write an Ansible playbook as well to do the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Install Docker on Debian
  hosts: all
  become: true
  tasks:
    - name: Remove conflicting Docker packages
      apt:
        name: "{{ item }}"
        state: absent
        purge: true
      loop:
        - docker.io
        - docker-doc
        - docker-compose
        - podman-docker
        - containerd
        - runc
      ignore_errors: true

    - name: Update apt repository cache
      apt:
        update_cache: yes

    - name: Install prerequisite packages
      apt:
        name:
          - ca-certificates
          - curl
          - gnupg
        state: present

    - name: Create keyrings directory for Docker
      file:
        path: /etc/apt/keyrings
        state: directory
        mode: '0755'

    - name: Add Docker's official GPG key
      ansible.builtin.command:
        cmd: curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
      args:
        creates: /etc/apt/keyrings/docker.gpg

    - name: Set permissions for Docker GPG key
      file:
        path: /etc/apt/keyrings/docker.gpg
        mode: '0644'

    - name: Add Docker repository
      ansible.builtin.apt_repository:
        repo: "deb [arch={{ ansible_architecture }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian {{ ansible_lsb.codename }} stable"
        filename: docker

    - name: Update apt cache after adding Docker repo
      apt:
        update_cache: yes

    - name: Install Docker packages
      apt:
        name:
          - docker-ce
          - docker-ce-cli
          - containerd.io
          - docker-buildx-plugin
          - docker-compose-plugin
        state: present

    - name: Create Docker group if it does not exist
      group:
        name: docker
        state: present

    - name: Add user to Docker group
      user:
        name: "{{ ansible_user }}"
        groups: docker
        append: yes

    - name: Run Docker hello-world to verify installation
      command: docker run hello-world
      register: docker_test_result
      failed_when: docker_test_result.rc != 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ciao e buon week-end :)&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>ubuntu</category>
      <category>linux</category>
    </item>
    <item>
      <title>Hello world Kubernetes with Nginx on Minikube</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Fri, 18 Aug 2023 15:17:13 +0000</pubDate>
      <link>https://dev.to/haamid/hello-world-kubernetes-with-nginx-on-minikube-643</link>
      <guid>https://dev.to/haamid/hello-world-kubernetes-with-nginx-on-minikube-643</guid>
      <description>&lt;p&gt;Kubernetes gives you the ability to deploy your app in a highly available way, and it has provisioning features that you can use to avoid manual tasks.&lt;br&gt;
There are tons of tutorials about Kubernetes out there, but in this simple post, I just want to give you the simplest deployment ever in Kubernetes. You will see how to deploy nginx with Kubernetes and access it easily.&lt;br&gt;
Before deployment, make sure you have properly installed kubectl and minikube, and remove any old stuff from minikube using the &lt;code&gt;delete&lt;/code&gt; and &lt;code&gt;start&lt;/code&gt; commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube delete
minikube start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it works, so everything is fine. lets go ahead. The main part is the &lt;code&gt;deployment.yaml&lt;/code&gt; file. write it in a file and apply it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then apply 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;kubectl apply -f deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you check the deployments:&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 deployments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see sth 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;NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           29s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, there is an Nginx deployment with 2 replicas. In order to verify if it is actually working, we should check port 80 of the pods. Therefore, we need to find the IP of each pod by simply using this command:&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 pods -o wide
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it should give you sth similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                READY   STATUS     RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATES
nginx-deployment-57d84f57dc-6wk4h   1/1     Running    0          3m22s   10.244.0.10   minikube   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case the IP of Pod is &lt;code&gt;10.244.0.10&lt;/code&gt; which I should connect to the cluster and check port &lt;code&gt;80&lt;/code&gt; of that. In Minikube we can SSH to the cluster simply with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now check the &lt;code&gt;&amp;lt;IP&amp;gt;:&amp;lt;PORT&amp;gt;&lt;/code&gt; with this command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you get an output 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;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&amp;lt;style&amp;gt;
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;For online documentation and support please refer to
&amp;lt;a href="http://nginx.org/"&amp;gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;
Commercial support is available at
&amp;lt;a href="http://nginx.com/"&amp;gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you for using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means your Nginx is working properly on the specified port. So you have a cluster with two Pods, each running an Nginx service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expose Nginx to the world
&lt;/h3&gt;

&lt;p&gt;If you want to expose your service to outside to see in the browser you can use a &lt;code&gt;LoadBalancer&lt;/code&gt; service 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;apiVersion: v1
kind: Service
metadata:
  name: nginx-load-balancer
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply 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;kubectl apply -f load-balancer.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you should see an Nginx default page in your IP address.&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%2Fz2ouvqa7uqauiucft7ao.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%2Fz2ouvqa7uqauiucft7ao.png" alt=" " width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was the most basic deployment on Kubernetes, but every big thing is made up of small pieces. In the next posts, I will try to delve deeper into Kubernetes. Have a good time! :)&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>nginx</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Laravel 10 new features</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Wed, 15 Feb 2023 17:00:17 +0000</pubDate>
      <link>https://dev.to/haamid/laravel-10-new-features-2kcp</link>
      <guid>https://dev.to/haamid/laravel-10-new-features-2kcp</guid>
      <description>&lt;p&gt;Finally Laravel 10 is released. It requires PHP &amp;gt;= 8.1. Most of the features are added by the core Laravel team and not the other contributors and it seems that there is not a big changes compared previous version releases. Lets have a glance. &lt;/p&gt;

&lt;h2&gt;
  
  
  New Type Hinting Model
&lt;/h2&gt;

&lt;p&gt;Nuno Maduro, creator of &lt;a href="https://github.com/pestphp/pest" rel="noopener noreferrer"&gt;Pest&lt;/a&gt; has added new PHP style of type hinting and removed old way of dock-block in all stubs and maybe codebase. It seems that the change has not a sensible different for end-users :)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Display a listing of the resource.
*/
public function index(): Response
{
    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Features with Pennant
&lt;/h2&gt;

&lt;p&gt;Another core member of Laravel, named &lt;a href="https://github.com/timacdonald" rel="noopener noreferrer"&gt;Tim MacDonald&lt;/a&gt; has developed a new package named Pennant that makes it easy to publish specific features for specific users. consider a situation that you have added a new feature and you want to test it on a small chunk of users. the package has introduced a convenient way for that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Laravel\Pennant\Feature;
use Illuminate\Support\Lottery;

Feature::define('new-onboarding-flow', function () {
    return Lottery::odds(1, 10);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Process Interaction in a simple way
&lt;/h2&gt;

&lt;p&gt;This feature is a little bit funny. I have experience working with the commands line &lt;code&gt;exec&lt;/code&gt; which we can run a program in OS's shell with PHP like &lt;code&gt;ls -a&lt;/code&gt;. With this new feature, you can run this kind of command with a better coding interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Illuminate\Support\Facades\Process;

$result = Process::run('ls -la');

return $result-&amp;gt;output();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Profile tests
&lt;/h2&gt;

&lt;p&gt;If your tests take too much to be ended (like me:)) try this feature. It profiles your tests and reports the execution time which makes it easy to find slow tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan test --profile
&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%2Fe72gtpr9744qtjne6gw3.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%2Fe72gtpr9744qtjne6gw3.png" alt=" " width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Pest for testing
&lt;/h2&gt;

&lt;p&gt;If you prefer the Pest PHP testing format for writing your tests, Now it is built in on Laravel and you can use it easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Command CLI prompts
&lt;/h2&gt;

&lt;p&gt;This feature prompts the user to complete the command if it was not complete. For example, if you run a command 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;php artisan make:controller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It asks you the name of controller. We can accept it from &lt;a href="https://github.com/jessarcher" rel="noopener noreferrer"&gt;Jess&lt;/a&gt; :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Horizon and Telescope
&lt;/h2&gt;

&lt;p&gt;Finally if you are a fan of one of the above tools, there is a little bit face lift on them. &lt;/p&gt;

&lt;p&gt;Overall, I think the changes were not big but that is the open-source world and we have to thank the contributors for their efforts. If you want a new thing, go and write it :) Have a good time.&lt;/p&gt;

</description>
      <category>theme</category>
      <category>ui</category>
      <category>design</category>
      <category>ux</category>
    </item>
    <item>
      <title>Error types and error reporting in PHP</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Sun, 04 Dec 2022 19:41:36 +0000</pubDate>
      <link>https://dev.to/haamid/error-types-and-error-reporting-in-php-3ogp</link>
      <guid>https://dev.to/haamid/error-types-and-error-reporting-in-php-3ogp</guid>
      <description>&lt;p&gt;It is important to know about error types in PHP. By this knowledge it would be easier to find and solve errors. Basically we have 4 types of error in PHP and I will show you them with an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Notice
&lt;/h2&gt;

&lt;p&gt;PHP is not sure about whether is it an error or not!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Warning
&lt;/h2&gt;

&lt;p&gt;An error that is important and should be fixed but does not stop code execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include("external_file.php");

Warning: include(external_file.php): Failed to open stream: No such file or directory in /Users/hamid/Codes/error.php on line 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Parse error
&lt;/h2&gt;

&lt;p&gt;When the compiler is unable to parse your code correctly. For example when a &lt;code&gt;;&lt;/code&gt; is missing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if ($a == 1) {
    echo "something!"
}

Parse error: syntax error, unexpected token "}", expecting "," or ";" in /Users/hamid/Codes/error.php on line 12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Fatal error
&lt;/h2&gt;

&lt;p&gt;When you have a critical error. &lt;strong&gt;Your code execution will be halted&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$c = 1 / 0;

Fatal error: Uncaught DivisionByZeroError: Division by zero in /Users/hamid/Codes/error.php:7
Stack trace:
#0 {main}
  thrown in /Users/hamid/Codes/error.php on line 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error reporting in PHP
&lt;/h2&gt;

&lt;p&gt;You can ask PHP to show specific types of errors like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Turn off all error reporting
error_reporting(0);

// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);

// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);

// Report all errors except E_NOTICE
// This is the default value set in php.ini
error_reporting(E_ALL ^ E_NOTICE);

// Report all PHP errors (see changelog)
error_reporting(E_ALL);

// Report all PHP errors
error_reporting(-1);

// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading... &lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>webdev</category>
      <category>backend</category>
    </item>
    <item>
      <title>Mock Config in Laravel</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Sat, 03 Sep 2022 19:45:19 +0000</pubDate>
      <link>https://dev.to/haamid/mock-config-in-laravel-688</link>
      <guid>https://dev.to/haamid/mock-config-in-laravel-688</guid>
      <description>&lt;p&gt;Hi all. If you are testing your application and you need to make your config constant or change it to a specific value for testing you can mock it simply!&lt;br&gt;
&lt;code&gt;Config&lt;/code&gt; facade of Laravel has a method named &lt;code&gt;set()&lt;/code&gt; which overwrites the default value of configs 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;Config::set('name', 'Laravel');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in testing env you can do something 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;public function test_that_home_page_is_working()
{
    Config::set('name', 'Laravel');
    $this-&amp;gt;get('/')-&amp;gt;assertSee("Laravel");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generally &lt;strong&gt;Laravel facades&lt;/strong&gt; have several benefits because of their testability. You can &lt;strong&gt;&lt;a href="https://laravel.com/docs/9.x/mocking" rel="noopener noreferrer"&gt;Mock&lt;/a&gt;&lt;/strong&gt; all facades of Laravel easily. Also if you want to have deeper knowledge about testing tools you can take a look at &lt;a href="http://docs.mockery.io/en/latest/" rel="noopener noreferrer"&gt;PHP Mockery&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>testing</category>
      <category>mocking</category>
    </item>
    <item>
      <title>Bootstrap open Accordion after Ajax loaded</title>
      <dc:creator>Hamid Haghdoost</dc:creator>
      <pubDate>Sat, 04 Jun 2022 13:27:01 +0000</pubDate>
      <link>https://dev.to/haamid/bootstrap-open-accordion-after-ajax-loaded-3md2</link>
      <guid>https://dev.to/haamid/bootstrap-open-accordion-after-ajax-loaded-3md2</guid>
      <description>&lt;p&gt;&lt;a href="https://getbootstrap.com/docs/5.2/components/accordion/" rel="noopener noreferrer"&gt;Accordion&lt;/a&gt; is a nice component of Bootstrap. It uses &lt;a href="https://getbootstrap.com/docs/5.2/components/collapse/" rel="noopener noreferrer"&gt;Collapse&lt;/a&gt; feature of Bootstrap. It works properly under the hood but sometimes you need to do something different. In my case I needed to click on accordion header, then send an Ajax request and get the content of accordion and then open it. There was not a straigh-forward API or document for that and finally I find it.&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;script&amp;gt;
    let prevent = true;

    $("#collapseThree").on("show.bs.collapse", function (e) {
        if (prevent) {
            e.preventDefault();
        }
        setTimeout(function () {
            prevent = false;
            $("#collapseThree").collapse("show");
            prevent = true;
        }, 1000);
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, I've added an event on the open state of collapse and I've used a &lt;code&gt;setTimeout&lt;/code&gt; function for simulate Ajax request.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>bootstrap</category>
      <category>css</category>
      <category>ajax</category>
    </item>
  </channel>
</rss>
