<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Girish V]]></title><description><![CDATA[Girish V]]></description><link>https://alchemyblogs.dpdns.org</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1704041543908/Vlpx79jwj.jpg</url><title>Girish V</title><link>https://alchemyblogs.dpdns.org</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 09 Jun 2026 20:08:56 GMT</lastBuildDate><atom:link href="https://alchemyblogs.dpdns.org/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Personal and Corporate Quickbook for Tax and Expense Management Using OpenSource Tools]]></title><description><![CDATA[Managing bills and expenses can be challenging, especially when preparing for tax season or managing corporate finances. To streamline this process, I developed an open-source QuickBook tracker application that utilizes various open-source tools. Thi...]]></description><link>https://alchemyblogs.dpdns.org/building-a-personal-and-corporate-quickbook-for-tax-and-expense-management-using-opensource-tools</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/building-a-personal-and-corporate-quickbook-for-tax-and-expense-management-using-opensource-tools</guid><category><![CDATA[taxprep]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Expense management]]></category><category><![CDATA[notion]]></category><category><![CDATA[Google Drive]]></category><category><![CDATA[Python]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[Google API]]></category><category><![CDATA[automation]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Mon, 23 Sep 2024 02:53:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727059381409/5175b8a5-e34e-4674-9272-e6273c0585f7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Managing bills and expenses can be challenging, especially when preparing for tax season or managing corporate finances. To streamline this process, I developed an open-source QuickBook tracker application that utilizes various open-source tools. This application allows users to upload bill images, which are then parsed using a custom AI/ML model to extract essential details like the supplier name, invoice number, date, tax, net amount, and category. The extracted details are stored in Notion, while the bill images are uploaded to Google Drive, providing an organized and efficient way to track and manage bills.</p>
<h2 id="heading-key-features"><strong>Key Features</strong></h2>
<ul>
<li><p><strong>Bill Image Upload:</strong> Users can upload images of bills/expenses directly through the Flask web application.</p>
</li>
<li><p><strong>Google Drive Integration:</strong> Uploaded bill images are saved to Google Drive for easy access and backup.</p>
</li>
<li><p><strong>Notion Database:</strong> Extracted bill details are stored in a Notion database, allowing users to track and manage their bills efficiently.</p>
</li>
<li><p><strong>Secure and Scalable:</strong> The application is designed with security in mind, ensuring that user data is protected.</p>
</li>
<li><p><strong>Cost-Effective:</strong> Instead of paying for expensive third-party services, this application can be built and maintained at no cost using open-source tools and APIs.</p>
</li>
</ul>
<h2 id="heading-technology-stack"><strong>Technology Stack</strong></h2>
<ol>
<li><p><strong>Flask:</strong> A lightweight and flexible Python web framework used for building the web applications.</p>
</li>
<li><p><strong>Google Drive API:</strong> Used to upload and manage bill images in Google Drive.</p>
</li>
<li><p><strong>Notion API:</strong> Used to create and update entries in a Notion database with the extracted bill details.</p>
</li>
<li><p><strong>Mindee API:</strong> An optional tool to enhance OCR capabilities, especially for more complex bill structures.</p>
</li>
</ol>
<h2 id="heading-step-by-step-guide"><strong>Step-by-Step Guide</strong></h2>
<ol>
<li><strong>Setting Up the Flask Application:</strong></li>
</ol>
<ul>
<li><p>Create a Flask application with a simple user interface for uploading bill images.</p>
</li>
<li><p>Implement secure user authentication to protect user data.</p>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, render_template, redirect, url_for
<span class="hljs-keyword">from</span> werkzeug.utils <span class="hljs-keyword">import</span> secure_filename
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> base64
<span class="hljs-keyword">from</span> utils.gdrive_helper <span class="hljs-keyword">import</span> GoogleDriveHelper
<span class="hljs-keyword">from</span> utils.notion_service <span class="hljs-keyword">import</span> NotionDatabaseHandler
<span class="hljs-keyword">from</span> utils.reciept_service <span class="hljs-keyword">import</span> ReceiptParser

load_dotenv()
app = Flask(__name__)

credential_json = json.loads(os.getenv(<span class="hljs-string">"GOOGLE_OAUTH_SERVICE_ACCOUNT"</span>))
gdrive_service = GoogleDriveHelper(credential_json)
drive_folder_id = gdrive_service.create_folder(<span class="hljs-string">"test_notion_upload"</span>)

receipt_service = ReceiptParser(os.getenv(<span class="hljs-string">"MINDEE_API_KEY"</span>))

notion_db_id = os.getenv(<span class="hljs-string">"NOTION_DB_ID"</span>)
notion_service = NotionDatabaseHandler(
        api_key=os.getenv(<span class="hljs-string">"NOTION_KEY"</span>),
        database_id=notion_db_id
    )

<span class="hljs-meta">@app.route('/')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'index.html'</span>)

<span class="hljs-meta">@app.route('/upload', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">upload_file</span>():</span>
    <span class="hljs-keyword">if</span> <span class="hljs-string">'file'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> request.files:
        <span class="hljs-keyword">return</span> redirect(request.url)
    file = request.files[<span class="hljs-string">'file'</span>]
    <span class="hljs-keyword">if</span> file.filename == <span class="hljs-string">''</span>:
        <span class="hljs-keyword">return</span> redirect(request.url)
    <span class="hljs-keyword">if</span> file:
        filename = secure_filename(file.filename)
        file_bytes = file.read()
        file_base64 = base64.b64encode(file_bytes).decode(<span class="hljs-string">'utf-8'</span>)

        <span class="hljs-comment"># Parse the reciept </span>
        reciept_details = receipt_service.parse_reciept_from_base64(file_base64, filename)

        <span class="hljs-comment"># Upload the file to the google drive</span>
        _, drive_url = gdrive_service.upload_file_obj(
            file, filename, drive_folder_id
        )
        reciept_details[<span class="hljs-string">"Receipt"</span>] = {<span class="hljs-string">"name"</span>: filename, <span class="hljs-string">"url"</span>: drive_url}

        <span class="hljs-comment"># Create the payload from the user content</span>
        entry_payload = notion_service.create_entry_payload(reciept_details)

        <span class="hljs-comment"># Insert the entry into the database</span>
        <span class="hljs-keyword">if</span> entry_payload:
            notion_service.insert_entry(entry_payload)
        flash(<span class="hljs-string">"Image uploaded and processed successfully!"</span>, <span class="hljs-string">"success"</span>)

        <span class="hljs-comment"># Process the uploaded file here</span>
        <span class="hljs-keyword">return</span> redirect(url_for(<span class="hljs-string">'index'</span>))

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    app.run(debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>This code creates a simple web interface where users can upload bill images. The uploaded files are saved to a local directory for further processing.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:325/1*GQVNIZ0SUjIREr2uwX4DnQ.png" alt class="image--center mx-auto" /></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*yTkxPa9JM11CfFoukWCF7w.png" alt class="image--center mx-auto" /></p>
<p><strong>2. Integrating AI/ML Model:</strong></p>
<ul>
<li><p>Develop a custom AI/ML model trained to parse bill receipts and extract information such as the supplier name, invoice number, amount, tax, net amount, category, and date.</p>
</li>
<li><p>Integrate the model into the Flask application to process uploaded bill images.</p>
</li>
<li><p>Alternatively, you can use Mindee to parse the invoice bill</p>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> mindee <span class="hljs-keyword">import</span> Client, product


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ReceiptParser</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, api_key</span>):</span>
        self.mindee_client = Client(api_key=api_key)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">extract_bill_details</span>(<span class="hljs-params">self, receipt_data</span>):</span>
        output = {
            <span class="hljs-string">"Name"</span>: receipt_data.document.inference.prediction.supplier_name.value <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">"Invoice No"</span>: receipt_data.document.inference.prediction.receipt_number.value <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">"Amount"</span>: receipt_data.document.inference.prediction.total_amount.value,
            <span class="hljs-string">"Tax"</span>: receipt_data.document.inference.prediction.total_tax.value,
            <span class="hljs-string">"Net"</span>: receipt_data.document.inference.prediction.total_net.value,
            <span class="hljs-string">"Category"</span>: receipt_data.document.inference.prediction.category.value,
            <span class="hljs-string">"Date"</span>: receipt_data.document.inference.prediction.date.value,
            <span class="hljs-string">"Mode"</span>: <span class="hljs-string">"Credit Card"</span>,
        }
        print(<span class="hljs-string">f"Bill details: <span class="hljs-subst">{output}</span>"</span>)
        <span class="hljs-keyword">return</span> output

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">parse_reciept_from_base64</span>(<span class="hljs-params">self, base64_string, image_name</span>):</span>
        input_doc = self.mindee_client.source_from_b64string(base64_string, image_name)
        receipt_data = self.mindee_client.parse(product.ReceiptV5, input_doc)
        result = self.extract_bill_details(receipt_data)
        <span class="hljs-keyword">return</span> result
</code></pre>
<p>Call the <code>parse_reciept_from_base64</code> function in your upload handler to process each bill and extract the necessary information.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:518/1*9cCb9K0Xu-KPIfNmmEkxGQ.png" alt class="image--center mx-auto" /></p>
<p>3. <strong>Uploading to Google Drive:</strong></p>
<ul>
<li><p>Use the Google Drive API to upload bill images directly from the application using the OAuth credentials.</p>
</li>
<li><p>Organize images in a structured way, such as by date or category, for easy retrieval.</p>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoogleDriveHelper</span>:</span>
    SCOPES = [
        <span class="hljs-string">"https://www.googleapis.com/auth/drive.file"</span>,
        <span class="hljs-string">"https://www.googleapis.com/auth/drive"</span>,
    ]

    VALID_EXTENSIONS = [<span class="hljs-string">".pdf"</span>, <span class="hljs-string">".png"</span>, <span class="hljs-string">".jpeg"</span>, <span class="hljs-string">".jpg"</span>]

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, credentail_json</span>):</span>
        self.credentail_json_file = credentail_json
        self.connect_using_service_account()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">connect_using_service_account</span>(<span class="hljs-params">self</span>):</span>
        creds = ServiceAccountCredentials.from_json_keyfile_dict(
            self.credentail_json, self.SCOPES
        )
        self.drive_service = build(
            <span class="hljs-string">"drive"</span>, <span class="hljs-string">"v3"</span>, credentials=creds, cache_discovery=<span class="hljs-literal">False</span>
        )

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">upload_file_obj</span>(<span class="hljs-params">self, file_obj, filename, parent_folder_id=None</span>):</span>
        mime_type, _ = mimetypes.guess_type(filename)
        <span class="hljs-keyword">if</span> mime_type <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
            mime_type = <span class="hljs-string">"application/octet-stream"</span>  <span class="hljs-comment"># Default fallback MIME type</span>
        file_metadata = {
            <span class="hljs-string">"name"</span>: filename,
            <span class="hljs-string">"parents"</span>: [parent_folder_id] <span class="hljs-keyword">if</span> parent_folder_id <span class="hljs-keyword">else</span> [],
        }
        print(mime_type)

        <span class="hljs-comment"># Upload the file object using MediaIoBaseUpload</span>
        media = MediaIoBaseUpload(file_obj, mimetype=mime_type, resumable=<span class="hljs-literal">True</span>)

        <span class="hljs-comment"># Upload the file to Google Drive</span>
        drive_file = (
            self.drive_service.files()
            .create(body=file_metadata, media_body=media, fields=<span class="hljs-string">"id"</span>)
            .execute()
        )

        file_id = drive_file.get(<span class="hljs-string">"id"</span>)
        print(<span class="hljs-string">f"File uploaded successfully. File ID: <span class="hljs-subst">{file_id}</span>"</span>)
        sharablelink = self.get_sharable_link(file_id)
        <span class="hljs-keyword">return</span> drive_file.get(<span class="hljs-string">"id"</span>), sharablelink
</code></pre>
<p>Integrate this function in the Flask application to upload the processed bill images directly to Google Drive.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*sSUMu4UopeLOw6_Bviov5w.png" alt class="image--center mx-auto" /></p>
<p><strong>4. Creating Notion Database Entries:</strong></p>
<ul>
<li><p>Set up a Notion database with fields for storing bill information.</p>
</li>
<li><p>Use the Notion API to create new entries in the database for each parsed bill, allowing users to view and manage their bills within Notion.</p>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests

NOTION_TOKEN = <span class="hljs-string">'your_notion_token'</span>
NOTION_DATABASE_ID = <span class="hljs-string">'your_database_id'</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotionDatabaseHandler</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, api_key=NOTION_TOKEN, database_id=NOTION_DATABASE_ID</span>):</span>
        self.api_key = api_key
        self.database_id = database_id
        self.headers = {
            <span class="hljs-string">"Authorization"</span>: <span class="hljs-string">f"Bearer <span class="hljs-subst">{self.api_key}</span>"</span>,
            <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
            <span class="hljs-string">"Notion-Version"</span>: <span class="hljs-string">"2022-06-28"</span>,  <span class="hljs-comment"># Latest API version</span>
        }

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">insert_entry</span>(<span class="hljs-params">self, details</span>):</span>
        data = {
            <span class="hljs-string">"parent"</span>: {<span class="hljs-string">"database_id"</span>: self.database_id},
            <span class="hljs-string">"properties"</span>: {
                <span class="hljs-string">"Name"</span>: {<span class="hljs-string">"title"</span>: [{<span class="hljs-string">"text"</span>: {<span class="hljs-string">"content"</span>: details[<span class="hljs-string">'supplier_name'</span>]}}]},
                <span class="hljs-string">"Invoice Number"</span>: {<span class="hljs-string">"rich_text"</span>: [{<span class="hljs-string">"text"</span>: {<span class="hljs-string">"content"</span>: details[<span class="hljs-string">'invoice_number'</span>]}}]},
                <span class="hljs-string">"Date"</span>: {<span class="hljs-string">"date"</span>: {<span class="hljs-string">"start"</span>: details[<span class="hljs-string">'date'</span>]}},
                <span class="hljs-string">"Tax"</span>: {<span class="hljs-string">"number"</span>: details[<span class="hljs-string">'tax'</span>]},
                <span class="hljs-string">"Net Amount"</span>: {<span class="hljs-string">"number"</span>: details[<span class="hljs-string">'net_amount'</span>]},
                <span class="hljs-string">"Category"</span>: {<span class="hljs-string">"select"</span>: {<span class="hljs-string">"name"</span>: details[<span class="hljs-string">'category'</span>]}}
            }
        }
        response = requests.post(<span class="hljs-string">'https://api.notion.com/v1/pages'</span>, headers=self.headers, json=data)
        <span class="hljs-keyword">if</span> response.status_code == <span class="hljs-number">200</span>:
            print(<span class="hljs-string">'Notion entry created successfully'</span>)
        <span class="hljs-keyword">else</span>:
            print(<span class="hljs-string">f'Failed to create Notion entry: <span class="hljs-subst">{response.content}</span>'</span>)
</code></pre>
<p>This function sends a POST request to the Notion API to create a new entry with the parsed bill details.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:483/1*UVM7yG8OJXvVEzOWhJHTrw.png" alt class="image--center mx-auto" /></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*VRex0QbB5Y_a7mzDCBDu1g.png" alt class="image--center mx-auto" /></p>
<p>5. <strong>Viewing and Tracking Bills:</strong></p>
<ul>
<li>Provide a user-friendly dashboard within the Flask application where users can view and manage their bills. Use data from the Notion database to populate the dashboard, allowing for easy tracking and filtering by date, category, or amount.</li>
</ul>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*yTkxPa9JM11CfFoukWCF7w.png" alt class="image--center mx-auto" /></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*b2O3KpHsBPGNuJdw5h4k2Q.png" alt class="image--center mx-auto" /></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*SaszNv6WsYjkcMUO3RER_A.png" alt class="image--center mx-auto" /></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*SV-bKMg61HTUh75JRAPb_A.png" alt class="image--center mx-auto" /></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*8V1N5oP4IOxJG2bUAQUoeA.png" alt class="image--center mx-auto" /></p>
<p><img src="https://miro.medium.com/v2/resize:fit:518/1*9cCb9K0Xu-KPIfNmmEkxGQ.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-benefits"><strong>Benefits</strong></h2>
<ul>
<li><p><strong>Time-Saving:</strong> Automates the manual task of tracking and organizing bills, freeing up time for other tasks.</p>
</li>
<li><p><strong>Accuracy:</strong> Reduces errors by using AI/ML models to extract bill details reliably.</p>
</li>
<li><p><strong>Centralized Management:</strong> Stores all bill information in a single place, making it easy to track and manage finances.</p>
</li>
<li><p><strong>Open Source and Cost-Free:</strong> Built using open-source tools, this application eliminates the need for expensive third-party services, allowing you to manage your bills at no cost.</p>
</li>
<li><p><strong>Tax Readiness:</strong> By categorizing and organizing expenses, the application helps users stay prepared for tax season, simplifying the process of compiling deductible expenses.</p>
</li>
<li><p><strong>Customizable:</strong> Easily extend and modify the application to fit your specific needs or add new features.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This open-source bill tracker application offers a comprehensive solution for managing bills, especially for tax and expense management. By utilizing Flask, Mindee, Google Drive, and Notion, you can create a powerful tool to keep your finances organized — all at no cost. Whether you’re managing personal finances or handling corporate bills, this application simplifies the process and eliminates the need for expensive third-party services.</p>
<blockquote>
<p><em>For those interested in exploring the full code or contributing to the project, please feel free to reach out to me at</em> <strong><em>girishcodealchemy@gmail.com*</em></strong>. I’m excited to share the complete implementation and collaborate on further improvements!*</p>
</blockquote>
<hr />
<p>🚀 Stay tuned for more powerful insights into open-source tools for seamless expense and tax management. Happy organizing!!! 🌐</p>
<p>✈️ Github: <a target="_blank" href="http://github.com/GirishCodeAlchemy">github.com/GirishCodeAlchemy</a><br />✈️Linkedin:<a target="_blank" href="http://linkedin.com/in/vgirish10">linkedin.com/in/vgirish10</a></p>
]]></content:encoded></item><item><title><![CDATA[Seamless Docker Container Deployment Using Terraform]]></title><description><![CDATA[Deploying Docker containers can be a complex process, especially when managing infrastructure at scale. Terraform, an open-source infrastructure as code (IaC) tool, simplifies this process by providing a consistent workflow for provisioning and manag...]]></description><link>https://alchemyblogs.dpdns.org/seamless-docker-container-deployment-using-terraform</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/seamless-docker-container-deployment-using-terraform</guid><category><![CDATA[Docker]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[deployment]]></category><category><![CDATA[#IaC]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Thu, 25 Jul 2024 13:48:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721885642580/9e29350f-a106-4b6a-b9e8-57198e36a190.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<p>Deploying Docker containers can be a complex process, especially when managing infrastructure at scale. Terraform, an open-source infrastructure as code (IaC) tool, simplifies this process by providing a consistent workflow for provisioning and managing infrastructure across various cloud providers. In this blog, we'll explore how to deploy Docker containers using Terraform, a powerful combination that brings automation, consistency, and scalability to your infrastructure management.</p>
<h2 id="heading-use-case">Use Case</h2>
<p>Imagine you are responsible for deploying a microservices-based application that consists of multiple Docker containers. Each service has its own dependencies, scaling requirements, and network configurations. Managing these services manually can quickly become unmanageable. By leveraging Terraform, you can automate the deployment process, ensure consistency across environments, and easily scale services as needed.</p>
<ol>
<li><p><strong>Microservices Deployment:</strong> Automate the deployment of a microservices-based application consisting of multiple Docker containers.</p>
</li>
<li><p><strong>Dependency Management:</strong> Handle each service's dependencies, ensuring that all necessary components are properly configured and available.</p>
</li>
<li><p><strong>Scaling Requirements:</strong> Easily scale services up or down based on demand without manual intervention.</p>
</li>
<li><p><strong>Network Configurations:</strong> Define and manage network configurations for seamless communication between services.</p>
</li>
<li><p><strong>Environment Consistency:</strong> Ensure consistency across development, staging, and production environments by using infrastructure as code.</p>
</li>
<li><p><strong>Simplified Management:</strong> Reduce the complexity of managing multiple services manually by leveraging Terraform for automated deployments.</p>
</li>
<li><p><strong>Infrastructure Reproducibility:</strong> Define infrastructure as code to easily reproduce environments for testing, staging, and production.</p>
</li>
<li><p><strong>Streamlined Deployment Process:</strong> Simplify and standardize the deployment process, allowing developers to focus on building and improving applications.</p>
</li>
</ol>
<h2 id="heading-requirements">Requirements</h2>
<p>Before we dive into the setup, ensure you have the following prerequisites:</p>
<ol>
<li><p><a target="_blank" href="https://www.terraform.io/downloads.html"><strong>Terraform</strong></a><strong>:</strong> Install Terraform on your local machine.</p>
</li>
<li><p><a target="_blank" href="https://www.docker.com/get-started"><strong>Docker</strong></a><strong>:</strong> Install Docker on your local machine.</p>
</li>
<li><p><strong>Docker Hub Account:</strong> Create a Docker Hub account to store your Docker images.</p>
</li>
<li><p><strong>Docker Images:</strong> Build and push your Docker images to Docker Hub.</p>
</li>
</ol>
<h2 id="heading-steps-to-set-up-docker-deployment-using-terraform">Steps to Set Up Docker Deployment Using Terraform</h2>
<h3 id="heading-1-install-terraform-and-docker">1. Install Terraform and Docker</h3>
<p>Ensure both Terraform and Docker are installed on your machine. Verify the installations by running the following commands:</p>
<pre><code class="lang-bash">terraform -v
docker -v
</code></pre>
<h3 id="heading-2-create-a-docker-compose-file">2. Create a Docker Compose File</h3>
<p>Create a docker-compose.yml file that defines your services. This file will be used to describe your application's services, networks, and volumes.</p>
<pre><code class="lang-bash">version: <span class="hljs-string">'3'</span>
services:
  web:
    image: girishcodealchemy/alchemy-nginx:v5
    ports:
      - <span class="hljs-string">"80:80"</span>
   db:
    image: postgres:latest
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:
</code></pre>
<h3 id="heading-3-write-terraform-configuration">3. Write Terraform Configuration</h3>
<p>Create a directory for your Terraform files and navigate into it:</p>
<pre><code class="lang-bash">mkdir terraform-docker
<span class="hljs-built_in">cd</span> terraform-docker
</code></pre>
<p>Create a <code>main.tf</code> file and add the following configuration to define your Docker provider and resources:</p>
<pre><code class="lang-bash">terraform {
  required_providers {
    docker = {
      <span class="hljs-built_in">source</span>  = <span class="hljs-string">"kreuzwerker/docker"</span>
      version = <span class="hljs-string">"~&gt; 3.0.2"</span>
    }
  }

  required_version = <span class="hljs-string">"~&gt; 1.5"</span>
}

provider <span class="hljs-string">"docker"</span> {
  host = <span class="hljs-string">"unix:///var/run/docker.sock"</span>
}

resource <span class="hljs-string">"docker_network"</span> <span class="hljs-string">"my_network"</span> {
  name = <span class="hljs-string">"my_network"</span>
}

resource <span class="hljs-string">"docker_volume"</span> <span class="hljs-string">"db_data"</span> {
  name = <span class="hljs-string">"db_data"</span>
}

resource <span class="hljs-string">"docker_container"</span> <span class="hljs-string">"web"</span> {
  name  = <span class="hljs-string">"web"</span>
  image = <span class="hljs-string">"girishcodealchemy/alchemy-nginx:v5"</span>
  ports {
    internal = 80
    external = 80
  }
  networks_advanced {
    name = docker_network.my_network.name
  }
}

resource <span class="hljs-string">"docker_container"</span> <span class="hljs-string">"db"</span> {
  name  = <span class="hljs-string">"db"</span>
  image = <span class="hljs-string">"postgres:latest"</span>
  env = [
    <span class="hljs-string">"POSTGRES_USER=postgres"</span>,
    <span class="hljs-string">"POSTGRES_PASSWORD=password"</span>,
    <span class="hljs-string">"POSTGRES_DB=mydb"</span>
  ]

  volumes {
    volume_name    = docker_volume.db_data.name
    container_path = <span class="hljs-string">"/var/lib/postgresql/data"</span>
  }
  networks_advanced {
    name = docker_network.my_network.name
  }
}
</code></pre>
<h3 id="heading-4-initialize-terraform">4. Initialize Terraform</h3>
<p>Run the following command to initialize the Terraform configuration. This command downloads the Docker provider and prepares your workspace.</p>
<pre><code class="lang-bash">terraform init
</code></pre>
<h3 id="heading-5-perform-the-terraform-plan">5. Perform the Terraform plan</h3>
<p>Run the following command to create an execution plan:</p>
<pre><code class="lang-bash">terraform plan
</code></pre>
<p>Terraform will display a plan of the changes it will make. Review the plan carefully.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721883269561/2b4105b3-d70e-44cb-94ac-5e82c9d84796.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-6-apply-the-terraform-configuration">6. Apply the Terraform Configuration</h3>
<p>Run the following command to apply the configuration and deploy your Docker containers:</p>
<pre><code class="lang-bash">terraform apply
</code></pre>
<p>Terraform will display a plan of the changes it will make. Review the plan and type <code>yes</code> to proceed with the deployment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721883399914/8ca26f0f-e264-4d31-a16e-7bc848de7048.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-7-verify-the-deployment">7. Verify the Deployment</h3>
<p>After the deployment is complete, verify that the containers are running by using the Docker CLI:</p>
<pre><code class="lang-bash">docker ps
</code></pre>
<p>You should see your web, and db containers running.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721883455837/b865cd86-0d97-4cb1-94b0-78e31aba91ef.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-8-destroy-the-docker-containers">8. Destroy the Docker containers</h3>
<p>To clean up the infrastructure, run the destroy command:</p>
<pre><code class="lang-plaintext">terraform destroy
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721883751391/cdb04f14-be3b-4f6c-a413-51fa3a07cfa2.png" alt /></p>
<h2 id="heading-exploring-the-full-code-on-github">Exploring the Full Code on GitHub</h2>
<p>To view the complete code for deploying Docker containers using Terraform, visit the <a target="_blank" href="https://github.com/GirishCodeAlchemy/alchemy-docker/blob/main/terraform/main.tf">GitHub repository</a>. This repository contains all the necessary files and detailed instructions to help you get started with automating your Docker deployments using Terraform.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Using Terraform to deploy Docker containers brings automation and consistency to your infrastructure management. This approach allows you to define your infrastructure as code, making it easy to reproduce and scale your deployments across different environments. By following the steps outlined in this blog, you can streamline your deployment process and focus on building and improving your application.</p>
<hr />
<p>🚀 Stay tuned for more empowering insights into the world of Docker and Terraform automation. Happy deploying!<strong>! 🌐</strong></p>
<p>✈️ <strong>Github</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>github.com/GirishCodeAlchemy</strong><br /><strong>✈️</strong></a><strong>Linkedin:</strong><a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>linkedin.com/in/vgirish10</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Streamlining Cloud Web Deployment with GithubAction & Terraform Cloud 🚀🚀]]></title><description><![CDATA[In today's fast-paced development landscape, automation is key to streamlining processes and ensuring the reliability and efficiency of deployments. Automating web deployment on the cloud is essential for modern software development workflows, and in...]]></description><link>https://alchemyblogs.dpdns.org/streamlining-cloud-web-deployment-with-githubaction-terraform-cloud</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/streamlining-cloud-web-deployment-with-githubaction-terraform-cloud</guid><category><![CDATA[terraformCloud]]></category><category><![CDATA[Devops]]></category><category><![CDATA[githubaction]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Python]]></category><category><![CDATA[terratest]]></category><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Sat, 17 Feb 2024 02:59:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1708138012747/b5529daa-03aa-4a9c-ad7d-2a01c8b11612.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In today's fast-paced development landscape, automation is key to streamlining processes and ensuring the reliability and efficiency of deployments. Automating web deployment on the cloud is essential for modern software development workflows, and in this guide, we'll delve into a detailed overview of automating web deployment on the cloud using Docker, Terraform, and Kubernetes.</p>
<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>This guide focuses on a multi-phase approach to automate web deployment on the cloud. It covers setting up a basic web application deployment pipeline to serve static files using popular DevOps tools. The primary aim is to automate the process from code changes to deployment, ensuring a seamless and reliable deployment pipeline using GithubAction and Terraform Cloud.</p>
<h2 id="heading-tools-used"><strong>Tools Used</strong></h2>
<p>Before diving into the deployment process, let's outline the key tools utilized in this automation setup:</p>
<ol>
<li><p><strong>Docker</strong>: A containerization platform used for building and managing Docker images.</p>
</li>
<li><p><strong>Bash Scripting</strong>: Utilized for scripting tasks and automation within the deployment process.</p>
</li>
<li><p><strong>Python</strong>: A programming language used for scripting and automation tasks, such as interacting with APIs and manipulating YAML files.</p>
</li>
<li><p><strong>Git</strong>: A version control system used for managing code changes, branches, and pull requests.</p>
</li>
<li><p><strong>Terraform</strong>: An Infrastructure-as-Code (IaC) tool used to provision and manage cloud resources.</p>
</li>
<li><p><strong>Kubernetes</strong>: A container orchestration platform used to deploy, scale, and manage containerized applications.</p>
</li>
<li><p><strong>Terratest</strong>: A Go library for testing infrastructure code, ensuring the reliability of Terraform configurations.</p>
</li>
<li><p><strong>GitHub Actions</strong>: A CI/CD platform integrated with GitHub repositories to automate workflows and tasks.</p>
</li>
<li><p><strong>Terraform Cloud</strong>: A cloud-based service for collaborative Terraform workflows, including execution and management of Terraform plans.</p>
</li>
</ol>
<h2 id="heading-workflow-overview"><strong>Workflow Overview</strong></h2>
<p><img src="https://github.com/GirishCodeAlchemy/TuroAutomateCloudWebDeploy/assets/143807663/acf8f64e-d7f4-487e-a6ca-f027f78c147f" alt="turo-cloud-assignment" /></p>
<p>The automation process is divided into three phases:</p>
<h3 id="heading-phase-1-build-and-push-docker-imagehttpsgithubcomgirishcodealchemyturoautomatecloudwebdeployactionsworkflowsdocker-buildyaml"><strong>Phase 1:</strong> <a target="_blank" href="https://github.com/GirishCodeAlchemy/TuroAutomateCloudWebDeploy/actions/workflows/docker-build.yaml"><strong>Build and Push Docker Image</strong></a></h3>
<p>This phase focuses on automating the process of building and pushing Docker images. Here's a breakdown of the workflow:</p>
<ol>
<li><p><strong>Automatic Trigger</strong>: The workflow is triggered automatically upon detecting changes in the Docker folder.</p>
</li>
<li><p><strong>Image Tag Versioning</strong>: By default, the image tag version is set to <code>DOCKER_TAG=0.${</code><a target="_blank" href="http://github.run"><code>github.run</code></a><code>_number}.${github.event.number}-dev</code>. This ensures that each build has a unique version identifier.</p>
</li>
<li><p><strong>Custom Image Tag</strong>: Users have the option to provide their own image tag. They can do this by navigating to the GitHub Actions workflow and modifying the image tag parameter.</p>
</li>
<li><p><strong>Workflow Execution</strong>: The workflow involves building the Docker image and pushing it to the Docker registry.</p>
</li>
</ol>
<ul>
<li><p>The workflow starts with the setup of the environment.</p>
</li>
<li><p>Phase 1 involves building the Docker image and pushing it to the Docker registry.</p>
</li>
<li><p>Once completed, Phase 2 will commence, which involves updating the Terraform code.</p>
</li>
</ul>
<p>This phase streamlines the process of Docker image management, ensuring consistency and reliability in the deployment pipeline.</p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/09f7c3d3-11e7-47c2-8b9d-a96ac60967c6" alt="Build the version tag" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/3b239254-edcb-4957-9c63-78dcb5c1d330" alt="githubaction-build" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/e73f7631-56d0-4331-9bab-4f6992ffc1d1" alt="phase1" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/40fc37a3-6ebd-4e04-be38-834974b51fde" alt="dockerhub" /></p>
<h3 id="heading-phase-2-update-image-tag-and-create-prhttpsgithubcomgirishcodealchemyturoautomatecloudwebdeployactionsworkflowsdeploy-imageyaml"><strong>Phase 2:</strong> <a target="_blank" href="https://github.com/GirishCodeAlchemy/TuroAutomateCloudWebDeploy/actions/workflows/deploy-image.yaml"><strong>Update Image Tag and Create PR</strong></a></h3>
<p>In this phase, the image tag is updated, and a pull request is created automatically. Here's how it works:</p>
<ol>
<li><p><strong>Continuous Integration</strong>: This phase integrates the updated image tag into the deployment pipeline, ensuring smooth and continuous deployment.</p>
</li>
<li><p><strong>Image Tag Update</strong>: The image tag is updated as part of this phase to reflect the changes made to the Docker image. This ensures that the latest version of the image is used for deployment.</p>
</li>
<li><p><strong>Terraform Plan Generation</strong>: The Terraform plan is generated to assess the impact of the changes made to the infrastructure. This step provides insight into the modifications that will be applied during the deployment process.</p>
</li>
<li><p><strong>Pull Request Creation</strong>: Automatically creates a pull request with proposed infrastructure changes.</p>
<ul>
<li><p>Once the image tag is updated and the Terraform plan is generated, a pull request is created automatically.</p>
</li>
<li><p>The pull request includes the proposed changes to the infrastructure, allowing for review and validation before deployment.</p>
</li>
</ul>
</li>
<li><p><strong>Workflow Execution</strong>:</p>
<ul>
<li><p>The workflow starts with the setup of the environment.</p>
</li>
<li><p>Phase 2 involves updating the image tag, and generating the Terraform plan on the creation of the pull request.</p>
</li>
<li><p>Upon completion, Phase 3 will begin, which involves reviewing the Terraform plan and applying the changes.</p>
</li>
</ul>
</li>
</ol>
<p>This phase ensures that changes to the Docker image and infrastructure are properly evaluated and integrated into the deployment pipeline, maintaining the reliability and stability of the application.</p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/34039b99-23c3-451c-a749-9a9ec80a0032" alt="Continuous Integration" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/7c674ec7-a8a4-4b92-a65d-85947f2d8d11" alt="pr created" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/d76e5807-fb89-47d8-bc5b-357f756b8c17" alt="Terratest" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/68826bee-31d1-49b8-944e-bba1e58a5f7c" alt="terraplan" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/28c06727-3123-42b3-8560-1d4544ff087a" alt="Merge" /></p>
<h3 id="heading-phase-3-deploy-the-changeshttpsappterraformioappaws-app-hostingworkspacesturoautomatecloudwebdeployruns"><strong>Phase 3:</strong> <a target="_blank" href="https://app.terraform.io/app/aws-app-hosting/workspaces/TuroAutomateCloudWebDeploy/runs"><strong>Deploy the Changes</strong></a></h3>
<p>The final phase focuses on deploying the changes to the infrastructure and application:</p>
<ol>
<li><p><strong>Review and Approval</strong>: Before deployment, the changes proposed in the Terraform plan are reviewed and approved. This step ensures that any modifications to the infrastructure meet the necessary requirements and standards.</p>
</li>
<li><p><strong>Deployment Process</strong>: Applies Terraform configuration changes to the target environment.</p>
<ul>
<li><p>Once the changes are reviewed and approved, the deployment process is initiated.</p>
</li>
<li><p>The Terraform configuration is applied to the target environment, implementing the proposed changes to the infrastructure.</p>
</li>
</ul>
</li>
<li><p><strong>UI Access</strong>: Provides access to the deployed application via a UI link.</p>
<ul>
<li><p>After successful deployment, users can access the deployed application via the provided UI link.</p>
</li>
<li><p>The link directs users to the application interface, where they can interact with the updated features and functionalities.</p>
</li>
</ul>
</li>
<li><p><strong>Workflow Integration</strong>:</p>
<ul>
<li><p>Phase 3 is seamlessly integrated into the deployment workflow, following the completion of Phase 2.</p>
</li>
<li><p>The deployment process ensures that changes are effectively applied to the infrastructure, maintaining the availability and performance of the application.</p>
</li>
</ul>
</li>
</ol>
<p>This phase completes the deployment cycle, ensuring that changes to the infrastructure and application are successfully deployed and accessible to users. It emphasizes the importance of thorough review and approval processes to maintain the reliability and stability of the deployed environment.</p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/8f39469a-cadf-44d1-a3bc-1b95f9629efb" alt="image" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/173e9ac2-958e-4d8f-947c-4f48c00625a7" alt="image" /></p>
<p><img src="https://github.com/GirishCodeAlchemy/TuroAutomateCloudWebDeploy/assets/143807663/da35b2b5-0e24-48f5-9e78-f56dc1a090b4" alt="image" /></p>
<h3 id="heading-access-the-uihttpsgirishcodealchemytest-subaccount-1-v02test-subaccount-1rrmu"><a target="_blank" href="https://girishcodealchemy.test-subaccount-1-v02.test-subaccount-1.rr.mu/">Access the UI</a></h3>
<p><img src="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy/assets/143807663/938745d9-2bad-449f-ab6b-b6830df3200a" alt="image" /></p>
<h3 id="heading-explore-the-full-code"><strong>Explore the Full Code</strong></h3>
<p>Curious to dive deeper into the automation setup? You can explore the full codebase and configuration files on the GitHub repository. Feel free to browse through the code, experiment with different configurations, and adapt the automation workflow to suit your specific deployment needs.</p>
<p><a target="_blank" href="https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy">https://github.com/GirishCodeAlchemy/AutomateCloudWebDeploy</a></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Automating web deployment on the cloud streamlines the deployment process, ensuring consistency, reliability, and efficiency. By leveraging Docker, Terraform, Kubernetes, and other DevOps tools, teams can create a robust deployment pipeline that accelerates software delivery and enhances overall productivity.</p>
<p>This comprehensive automation setup emphasizes the importance of continuous integration, infrastructure as code, and thorough review processes in maintaining the reliability and stability of deployed applications on the cloud. With automation, teams can focus more on innovation and less on manual deployment tasks, driving business growth and success in today's competitive landscape.</p>
<p>. . . . .</p>
<p>🚀 Stay tuned for more empowering insights into the world of automated deployment with GithubAction &amp; Terrafrom Cloud. Happy automating your cloud journey!⛴️  </p>
<p>✈️ <strong>Github</strong>: <a target="_blank" href="http://github.com/GirishCodeAlchemy"><strong>github.com/GirishCodeAlchemy</strong></a><br /><strong>✈️Linkedin:</strong><a target="_blank" href="http://linkedin.com/in/vgirish10"><strong>linkedin.com/in/vgirish10</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[GitHub Action Runtime Adhoc Commands on PR]]></title><description><![CDATA[GitHub Actions provides a powerful automation platform that allows you to build, test, and deploy your code directly from your GitHub repository. One of the exciting features of GitHub Actions is the ability to run custom scripts and commands during ...]]></description><link>https://alchemyblogs.dpdns.org/github-action-runtime-adhoc-commands-on-pr</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/github-action-runtime-adhoc-commands-on-pr</guid><category><![CDATA[PR-commands]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[GitHub Actions]]></category><category><![CDATA[automation]]></category><category><![CDATA[Devops articles]]></category><category><![CDATA[DevOps Automation]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Fri, 02 Feb 2024 17:26:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706891225144/f0773a29-6968-4ebb-a110-245974c1ac32.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>GitHub Actions provides a powerful automation platform that allows you to build, test, and deploy your code directly from your GitHub repository. One of the exciting features of GitHub Actions is the ability to run custom scripts and commands during the workflow.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706852361425/c86acb8d-d80a-4c65-b11e-4eb24031d917.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-overview"><strong>Overview</strong></h2>
<p>In modern software development workflows, efficient collaboration and automation play a crucial role. The "GithubAction Runtime Adhoc PR Commands" is a GitHub Action designed to streamline and automate specific tasks on pull requests, enhancing the overall development process.</p>
<p>The primary purpose of this GitHub Action is to enable the execution of ad-hoc commands dynamically in response to user comments on pull requests. Ad-hoc commands refer to custom, user-defined instructions that can be triggered to perform specific actions. These commands can be particularly useful for tasks such as rebasing, auto squashing, or any other custom workflow steps that developers may need during the pull request review process.</p>
<h2 id="heading-problem-statement"><strong>Problem Statement</strong></h2>
<p>Imagine a scenario where you want to execute specific commands on a pull request dynamically. GitHub Actions offer a great way to automate workflows, but sometimes you need more flexibility. Maybe you want to trigger certain tasks only when a specific comment is added to a PR. This is where ad-hoc commands come into play.</p>
<h3 id="heading-key-features"><strong>Key Features</strong></h3>
<ol>
<li><p><strong>Automation of Custom Commands:</strong> The GitHub Action automates the execution of custom commands specified in pull request comments. This eliminates the need for manual intervention, making the development process more efficient.</p>
</li>
<li><p><strong>Dynamic Response to User Interactions:</strong> The Action responds dynamically to user comments, allowing developers to trigger specific tasks based on their needs. This flexibility is valuable in scenarios where different actions may be required for different pull requests.</p>
</li>
<li><p><strong>Enhanced Workflow Flexibility:</strong> By incorporating this GitHub Action into your workflow, you gain a high degree of flexibility. Developers can interact with the pull request by simply adding specific commands in their comments, and the automation takes care of the rest.</p>
</li>
<li><p><strong>Easy Integration with GitHub Actions:</strong> The Action seamlessly integrates with GitHub Actions, utilizing the power of workflows to orchestrate the execution of ad-hoc commands. This integration ensures a smooth and cohesive experience within the GitHub ecosystem.</p>
</li>
</ol>
<h3 id="heading-use-cases"><strong>Use Cases</strong></h3>
<ul>
<li><p><strong>Rebasing:</strong> Developers can trigger a rebase operation on their pull requests by adding the <code>/rebase</code> command in a comment. This is particularly useful for keeping the codebase up-to-date with the latest changes from the main branch.</p>
</li>
<li><p><strong>Autosquashing:</strong> The <code>/autosquash</code> command allows developers to automate the process of squashing commits in their pull requests, creating a cleaner commit history.</p>
</li>
<li><p><strong>Custom Workflow Steps:</strong> Beyond rebase and autosquash, developers can define and execute any custom workflow steps by incorporating specific commands tailored to their project requirements.</p>
</li>
</ul>
<h2 id="heading-usage">Usage:</h2>
<ol>
<li><p>Add below action to your workflow YAML</p>
</li>
<li><p>Specify your custom commands on the PR comments</p>
</li>
<li><p>watch the magic happen as your PRs get supercharged</p>
</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">PR</span> <span class="hljs-string">Adhoc</span> <span class="hljs-string">commands</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">issue_comment:</span>
    <span class="hljs-attr">types:</span> [<span class="hljs-string">created</span>]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">PR-Adhoc-Commands</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">if:</span> <span class="hljs-string">&gt;-
      github.event.issue.pull_request != '' &amp;&amp;
      (
        contains(github.event.comment.body, '/rebase') ||
        contains(github.event.comment.body, '/autosquash') ||
        contains(github.event.comment.body, '/rebase-autosquash')
      )
</span>    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">the</span> <span class="hljs-string">latest</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">token:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.GITHUB_TOKEN</span> <span class="hljs-string">}}</span>
          <span class="hljs-attr">fetch-depth:</span> <span class="hljs-number">0</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Running</span> <span class="hljs-string">Adhoc</span> <span class="hljs-string">commands</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">GirishCodeAlchemy/githubaction-runtime-adhoc-pr-commands@v1.0</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">GITHUB_TOKEN:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.GITHUB_TOKEN</span> <span class="hljs-string">}}</span>
</code></pre>
<h2 id="heading-command-usage">Command Usage :</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706853031882/38277f8f-d3b1-414e-a10f-de4e4b697391.gif" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706891565040/81e587bb-b57a-4c15-b749-312e993340a6.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-solution-overview"><strong>Solution Overview</strong></h2>
<p>To address this challenge, we'll create a GitHub Action that responds to comments on a pull request and executes custom commands. The key components of the solution include:</p>
<ol>
<li><p><strong>GitHub Action Workflow:</strong> Define a workflow that triggers on pull request comments.</p>
</li>
<li><p><strong>Custom Action Script:</strong> Write a script that interprets the comment content and executes the desired commands.</p>
</li>
<li><p><strong>GitHub API Integration:</strong> Use the GitHub API to fetch information about the pull request and perform necessary actions.</p>
</li>
</ol>
<p>Let's break down the implementation step by step.</p>
<h2 id="heading-implementation"><strong>Implementation</strong></h2>
<h3 id="heading-1-github-action-workflow"><strong>1. GitHub Action Workflow</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Adhoc</span> <span class="hljs-string">Commands</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">issue_comment:</span>
    <span class="hljs-attr">types:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">created</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">adhoc_commands:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">code</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Adhoc</span> <span class="hljs-string">Commands</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">GirishCodeAlchemy/githubaction-runtime-adhoc-pr-commands@v1.0</span>
      <span class="hljs-attr">env:</span>
          <span class="hljs-attr">GITHUB_TOKEN:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.GITHUB_TOKEN</span> <span class="hljs-string">}}</span>
</code></pre>
<p>This workflow triggers on new comments (<code>issue_comment</code> event) and uses a custom action (which we'll create next) to run the ad-hoc commands.</p>
<h3 id="heading-2-custom-action-script"><strong>2. Custom Action Script</strong></h3>
<pre><code class="lang-bash"><span class="hljs-comment"># alchemy.py</span>

import subprocess

def execute_adhoc_commands(comment_body):
    <span class="hljs-comment"># Logic to parse and execute commands</span>
    <span class="hljs-comment"># Example: Execute "echo Hello World" if the comment contains "/run-command"</span>
    <span class="hljs-keyword">if</span> <span class="hljs-string">"/run-command"</span> <span class="hljs-keyword">in</span> comment_body:
        subprocess.run([<span class="hljs-string">"echo"</span>, <span class="hljs-string">"Hello World"</span>])

<span class="hljs-comment"># Entry point</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    comment_body = input(<span class="hljs-string">"Enter the comment body: "</span>)
    execute_adhoc_commands(comment_body)
</code></pre>
<p>In this script, we define a function <code>execute_adhoc_commands</code> that interprets the comment content and executes specific commands. Customize this logic according to your requirements.</p>
<h3 id="heading-3-github-api-integration"><strong>3. GitHub API Integration</strong></h3>
<p>Extend the script to fetch additional information about the pull request using the GitHub API. For example, you can retrieve the PR number, author, or any other relevant details.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># alchemy.py</span>

import subprocess
import os
import requests

def get_pr_info():
    github_token = os.getenv(<span class="hljs-string">"GITHUB_TOKEN"</span>)
    pr_number = os.getenv(<span class="hljs-string">"PR_NUMBER"</span>)
    repo = os.getenv(<span class="hljs-string">"GITHUB_REPOSITORY"</span>)

    headers = {
        <span class="hljs-string">"Authorization"</span>: f<span class="hljs-string">"Bearer {github_token}"</span>,
        <span class="hljs-string">"Accept"</span>: <span class="hljs-string">"application/vnd.github.v3+json"</span>
    }

    response = requests.get(
        f<span class="hljs-string">"https://api.github.com/repos/{repo}/pulls/{pr_number}"</span>,
        headers=headers
    )

    <span class="hljs-built_in">return</span> response.json()

def execute_adhoc_commands(comment_body):
    pr_info = get_pr_info()
    pr_author = pr_info[<span class="hljs-string">"user"</span>][<span class="hljs-string">"login"</span>]
    pr_number = pr_info[<span class="hljs-string">"number"</span>]

    <span class="hljs-comment"># Logic to parse and execute commands</span>
    <span class="hljs-comment"># Example: Execute "echo Hello World" if the comment contains "/run-command"</span>
    <span class="hljs-keyword">if</span> <span class="hljs-string">"/run-command"</span> <span class="hljs-keyword">in</span> comment_body:
        subprocess.run([<span class="hljs-string">"echo"</span>, f<span class="hljs-string">"Hello World from PR {pr_number} by {pr_author}"</span>])

<span class="hljs-comment"># Entry point</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    comment_body = input(<span class="hljs-string">"Enter the comment body: "</span>)
    execute_adhoc_commands(comment_body)
</code></pre>
<p>Here, we've added a <code>get_pr_info</code> function to fetch PR information. Update the logic in <code>execute_adhoc_commands</code> to utilize this information as needed.</p>
<h3 id="heading-github-marketplace">Github Marketplace:</h3>
<p>The action is now available on the public GitHub Actions Marketplace: <a target="_blank" href="https://github.com/marketplace/actions/pr-runtime-adhoc-commands">PR Runtime Adhoc commands</a></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>With this GitHub Action setup, you have a flexible way to execute custom commands dynamically based on comments in your pull requests. Whether you need to trigger specific tests, deploy to staging, or perform any other task, this solution provides the extensibility you need.</p>
<p>🚀 Stay tuned for more empowering insights into the world of GitHub Actions and PR runtime adhoc commands. Happy automating!<strong>! 🌐</strong></p>
<p>✈️ <strong>Github</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>github.com/GirishCodeAlchemy</strong><br /><strong>✈️</strong></a><strong>Linkedin:</strong><a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>linkedin.com/in/vgirish10</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Streamlining AWS SSO in Complex Multi-Account Environments]]></title><description><![CDATA[Introduction
In today's dynamic landscape of cloud infrastructure, managing access and authentication across multiple AWS accounts can be a challenging task. As organizations scale their presence on the AWS cloud, the need for a robust Single Sign-On...]]></description><link>https://alchemyblogs.dpdns.org/streamlining-aws-sso-in-complex-multi-account-environments</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/streamlining-aws-sso-in-complex-multi-account-environments</guid><category><![CDATA[AWS-sso-automate]]></category><category><![CDATA[AWS]]></category><category><![CDATA[SSO]]></category><category><![CDATA[Terraform]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Sun, 21 Jan 2024 22:04:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705815230240/7749ff96-af15-4e6c-8e33-83ae0d00e844.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>In today's dynamic landscape of cloud infrastructure, managing access and authentication across multiple AWS accounts can be a challenging task. As organizations scale their presence on the AWS cloud, the need for a robust Single Sign-On (SSO) solution becomes increasingly evident. This blog aims to delve into the details of AWS SSO automation, offering insights into efficiently orchestrating user access in complex multi-account environments. We will delve into the challenges of manual SSO creation and present a comprehensive guide on transitioning to an automated approach, providing a roadmap for enhancing security, scalability, and overall operational efficiency.</p>
<h3 id="heading-challenges-of-manual-sso-creation"><strong>Challenges of Manual SSO Creation:</strong></h3>
<ol>
<li><p><strong>Tedious User Access Configuration:</strong></p>
<ul>
<li>Manually configuring individual user access across multiple AWS accounts is a time-consuming and labor-intensive task.</li>
</ul>
</li>
<li><p><strong>Potential for Human Errors:</strong></p>
<ul>
<li>The manual nature of SSO creation introduces the risk of human errors in permission assignments, leading to security vulnerabilities and compliance concerns.</li>
</ul>
</li>
<li><p><strong>Inefficiencies in Permission Management:</strong></p>
<ul>
<li>Managing permissions manually can result in inefficiencies, as each user and group may have unique configurations that must be meticulously handled.</li>
</ul>
</li>
<li><p><strong>Operational Overhead:</strong></p>
<ul>
<li>The manual approach adds operational overhead, requiring significant time and effort to ensure accurate and consistent SSO configurations across accounts.</li>
</ul>
</li>
<li><p><strong>Limitations in Scalability:</strong></p>
<ul>
<li>As organizations expand their AWS footprint, the limitations of manual SSO creation become more apparent, hindering scalability and adaptability to evolving infrastructure needs.</li>
</ul>
</li>
<li><p><strong>Security Concerns:</strong></p>
<ul>
<li>Manual processes increase the risk of security vulnerabilities, as errors in permission assignments may lead to unauthorized access and potential data breaches.</li>
</ul>
</li>
<li><p><strong>Complexity with Growing AWS Presence:</strong></p>
<ul>
<li>The challenges amplify as the AWS presence grows, making manual SSO creation increasingly complex and prone to inconsistencies.</li>
</ul>
</li>
</ol>
<h3 id="heading-the-road-to-automation"><strong>The Road to Automation:</strong></h3>
<p>Automating AWS SSO processes not only addresses the challenges posed by manual configurations but also brings forth a range of benefits. A well-implemented automation strategy enhances security by enforcing consistent access policies and reduces the risk of human errors in permission assignments. Scalability is significantly improved, allowing organizations to seamlessly adapt to the evolving demands of their cloud infrastructure. Additionally, the time and effort saved through automation can be redirected towards more strategic initiatives, fostering innovation and agility.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705873187782/fe086946-9299-4dbb-a315-4395eb7a03f4.gif" alt class="image--center mx-auto" /></p>
<p><strong>Key Components of AWS SSO Automation:</strong></p>
<ol>
<li><p><strong>Terraform Infrastructure as Code (IaC):</strong> Leveraging Terraform, an IaC tool, facilitates the codification of AWS SSO configurations. This not only streamlines the provisioning of SSO resources but also ensures version-controlled, repeatable, and auditable infrastructure changes.</p>
</li>
<li><p><strong>AWS SSO Terraform Module:</strong> Introducing the <a target="_blank" href="https://registry.terraform.io/modules/GirishCodeAlchemy/sso-module/aws/latest">GirishCodeAlchemy AWS SSO Terraform Module</a>, now available on the Terraform Registry. Designed to simplify the orchestration of AWS SSO resources, this module empowers your environment with the flexibility to manage multiple hierarchies seamlessly. Easily provision and configure AWS SSO components, including identity store, users, groups, and permissions, using this modular and user-friendly solution.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705813567584/f1ddb30b-663e-4357-a94c-8f270ccc6bb5.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before diving into the automation process, ensure you have the following prerequisites:</p>
<ul>
<li><p>Identity Store configured</p>
</li>
<li><p>Relevant AWS accounts and permission sets defined</p>
</li>
</ul>
<h3 id="heading-terraform-setup">Terraform Setup</h3>
<p>We'll use Terraform for this automation. Ensure you have Terraform installed, and set up your project directory.</p>
<p><strong>Terraform Module Usage:</strong></p>
<p>Simplify your AWS SSO implementation with the <a target="_blank" href="https://registry.terraform.io/modules/GirishCodeAlchemy/sso-module/aws/latest"><strong>GirishCodeAlchemy/sso-module/aws</strong></a> Terraform Module. Use the provided example configuration to get started:</p>
<pre><code class="lang-bash">data <span class="hljs-string">"aws_ssoadmin_instances"</span> <span class="hljs-string">"ssoadmin"</span> {
  <span class="hljs-comment"># Retrieve information about existing SSO instances, if needed.</span>
}

module <span class="hljs-string">"sso"</span> {
  <span class="hljs-built_in">source</span>  = <span class="hljs-string">"GirishCodeAlchemy/sso-module/aws"</span>
  version = <span class="hljs-string">"1.0.0"</span>

  identity_store_ids           = data.aws_ssoadmin_instances.ssoadmin.identity_store_ids
  ssoadmin_instance_arns       = data.aws_ssoadmin_instances.ssoadmin.arns
  sso_user_configmap           = var.sso_user_configmap
  sso_groups_configmap         = var.sso_groups_configmap
  sso_permissionsets_configmap = var.sso_permissionsets_configmap
  sso_account_configmap        = var.sso_account_configmap
}
</code></pre>
<p><strong>Variables Configuration Examples:</strong><br />The GirishCodeAlchemy AWS SSO Terraform Module includes a set of variables for configuring users, groups, permission sets, and accounts. Here are some examples to guide you through the configuration process:</p>
<ul>
<li><p><code>identity_store_ids</code></p>
<pre><code class="lang-bash">  identity_store_ids = [<span class="hljs-string">"d-dssdaa"</span>] <span class="hljs-comment"># data.aws_ssoadmin_instances.ssoadmin.identity_store_id</span>
  ssoadmin_instance_arns = [<span class="hljs-string">"arn:aws:sso:::instance/ssoins-xxxxxxxxxx"</span>] <span class="hljs-comment"># data.aws_ssoadmin_instances.ssoadmin.arns</span>
</code></pre>
</li>
<li><p><code>sso_user_configmap</code></p>
<pre><code class="lang-bash">  sso_user_configmap = {
    girish1 = {
      display_name = <span class="hljs-string">"Girish V"</span>
      user_name    = <span class="hljs-string">"girish1"</span>
      given_name   = <span class="hljs-string">"Girish"</span>
      family_name  = <span class="hljs-string">"V"</span>
      email        = <span class="hljs-string">"girish1@example.com"</span>
    },
    girish2 = {
      display_name = <span class="hljs-string">"Girish V"</span>
      user_name    = <span class="hljs-string">"girish2"</span>
      given_name   = <span class="hljs-string">"Girish"</span>
      family_name  = <span class="hljs-string">"V"</span>
      email        = <span class="hljs-string">"girish2@example.com"</span>
    }
  }
</code></pre>
</li>
<li><p><code>sso_groups_configmap</code></p>
<pre><code class="lang-bash">  sso_groups_configmap = {
    <span class="hljs-string">"L1-devops-group"</span> = {
      display_name = <span class="hljs-string">"L1-devops-group"</span>
      description  = <span class="hljs-string">"This is AWS L1 Devops Group"</span>
      users        = [<span class="hljs-string">"girish1"</span>, <span class="hljs-string">"girish2"</span>]
    },
    <span class="hljs-string">"L1-Admin-group"</span> = {
      display_name = <span class="hljs-string">"L1-Admin-group"</span>
      description  = <span class="hljs-string">"This is AWS L1 Admin Group"</span>
      users        = [<span class="hljs-string">"girish1"</span>]
    }
  }
</code></pre>
</li>
<li><p><code>sso_permissionsets_configmap</code></p>
<pre><code class="lang-bash">  sso_permissionsets_configmap = {
    <span class="hljs-string">"SSM-Admin-permissionset"</span> = {
      name                = <span class="hljs-string">"SSM-Admin-permissionset"</span>
      description         = <span class="hljs-string">"Sample Admin permissionset"</span>
      managed_policy_arns = [<span class="hljs-string">"arn:aws:iam::aws:policy/AmazonEC2FullAccess"</span>, <span class="hljs-string">"arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"</span>]
      inline_policy       = &lt;&lt;-EOF
      {
          <span class="hljs-string">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
          <span class="hljs-string">"Statement"</span>: [
              {
              <span class="hljs-string">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
              <span class="hljs-string">"Action"</span>: [
                  <span class="hljs-string">"lambda:*"</span>,
              ],
              <span class="hljs-string">"Resource"</span>: <span class="hljs-string">"*"</span>
              }
          ]
      }
      EOF
    },
    <span class="hljs-string">"SSM-testing-permissionset"</span> = {
      name                = <span class="hljs-string">"SSM-testing-permissionset"</span>
      description         = <span class="hljs-string">"Sample testing permissionset"</span>
      managed_policy_arns = [<span class="hljs-string">"arn:aws:iam::aws:policy/AmazonEC2FullAccess"</span>]
      inline_policy       = &lt;&lt;-EOF
      {
          <span class="hljs-string">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
          <span class="hljs-string">"Statement"</span>: [
              {
              <span class="hljs-string">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
              <span class="hljs-string">"Action"</span>: [
                  <span class="hljs-string">"s3:ListAllMyBuckets"</span>,
                  <span class="hljs-string">"s3:GetBucketLocation"</span>
              ],
              <span class="hljs-string">"Resource"</span>: <span class="hljs-string">"arn:aws:s3:::*"</span>
              }
          ]
      }
      EOF
    }
  }
</code></pre>
</li>
<li><p><code>sso_account_configmap</code></p>
<pre><code class="lang-bash">  sso_account_configmap = {
    <span class="hljs-string">"1xxxxxxxx"</span> = {
      users = {
        girishcodealchemy = { username = <span class="hljs-string">"girishcodealchemy"</span>, permissionset = [<span class="hljs-string">"SSM-testing-permissionset"</span>, <span class="hljs-string">"SSM-Admin-permissionset"</span>] }
      }
      groups = {
        L1devopsgroup = { groupname = <span class="hljs-string">"L1-devops-group"</span>, permissionset = [<span class="hljs-string">"SSM-testing-permissionset"</span>, <span class="hljs-string">"SSM-Admin-permissionset"</span>] }
      }
    },
    <span class="hljs-string">"2xxxxxxxx"</span> = {
      users = {
        girishcodealchemy = { username = <span class="hljs-string">"girishcodealchemy"</span>, permissionset = [<span class="hljs-string">"SSM-testing-permissionset"</span>] }
      }
      groups = {
        L1devopsgroup = { groupname = <span class="hljs-string">"L1-devops-group"</span>, permissionset = [<span class="hljs-string">"SSM-testing-permissionset"</span>] },
        L1AdminGroup  = { groupname = <span class="hljs-string">"L1-Admin-group"</span>, permissionset = [<span class="hljs-string">"SSM-Admin-permissionset"</span>] }
      }
    }
  }
</code></pre>
</li>
</ul>
<p><strong>Terraform plan and Deploy</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705809788747/cc999e44-b7f3-4c04-a5a9-7fd486359f84.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705809506909/164fc15e-2c79-40da-bf25-5645d7f3eb9b.png" alt class="image--center mx-auto" /></p>
<p>Users Created</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705812012372/199bc6fd-b58e-45e1-91de-a2c23be304be.png" alt class="image--center mx-auto" /></p>
<p>Groups and Members Created</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705812092741/29e9f538-d17e-4794-8966-e7e5f890ca2c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705812122234/68bdd1fc-10f0-44fb-bbcf-5a0279e96bbb.png" alt class="image--center mx-auto" /></p>
<p>Permission Sets Created</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705812174294/2ef165c6-1a7b-485b-b054-49d33ab2aca1.png" alt class="image--center mx-auto" /></p>
<p>Mapped Users , Groups &amp; Permission sets to the Accounts</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705812363890/3de32f2e-ff50-41a2-b96f-cd2d1bf35a24.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705812449439/8214b219-e1a3-431b-9b00-84c34d57899d.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-implementation-resources"><strong>Implementation Resources:</strong></h2>
<p><strong>A Guide for Creating Resources from Scratch</strong></p>
<p>Setting up AWS SSO automation from scratch involves creating necessary resources using Terraform. This guide outlines the steps to implement your own AWS SSO solution.</p>
<ol>
<li><h4 id="heading-aws-identity-store-user-configuration"><strong>AWS Identity Store User Configuration:</strong></h4>
</li>
</ol>
<p>Automate the creation and configuration of AWS Identity Store users using the <code>aws_identitystore_user</code> resource. This resource creates a user in the AWS Identity Store. The user’s display name, username, given name, family name, and email are all configurable.</p>
<ul>
<li>Define user configurations in the <a class="post-section-overview" href="#sso_user_configmap">sso_user_configmap</a> variable. The example code snippet illustrates the Terraform implementation:</li>
</ul>
<pre><code class="lang-bash">resource <span class="hljs-string">"aws_identitystore_user"</span> <span class="hljs-string">"aws_user"</span> {
  for_each          = var.sso_user_configmap
  identity_store_id = element(var.identity_store_ids, 0)

  display_name = each.value.display_name
  user_name    = each.value.user_name

  name {
    given_name  = each.value.given_name
    family_name = each.value.family_name
  }

  emails {
    primary = <span class="hljs-literal">true</span>
    value   = each.value.email
  }

  lifecycle {
    ignore_changes = [
      name,
      emails,
    ]
  }
}
</code></pre>
<ol>
<li><h4 id="heading-aws-identity-store-group-configuration"><strong>AWS Identity Store Group Configuration:</strong></h4>
</li>
</ol>
<p>Start by defining AWS Identity Store groups and their memberships. Use the <code>aws_identitystore_group</code> and <code>aws_identitystore_group_membership</code> resources to create the necessary group structures.</p>
<ul>
<li>Define group and member configurations in the <a class="post-section-overview" href="#sso_groups_configmap">sso_groups_configmap</a> variable. The example code snippet showcases the Terraform implementation:</li>
</ul>
<pre><code class="lang-bash">resource <span class="hljs-string">"aws_identitystore_group"</span> <span class="hljs-string">"aws_group"</span> {
  for_each          = var.sso_groups_configmap
  identity_store_id = element(var.identity_store_ids, 0)
  display_name      = each.value.display_name
  description       = each.value.description
}

resource <span class="hljs-string">"aws_identitystore_group_membership"</span> <span class="hljs-string">"example"</span> {
  for_each          = { <span class="hljs-keyword">for</span> identity <span class="hljs-keyword">in</span> local.flattened_groups : <span class="hljs-string">"<span class="hljs-variable">${identity.group_key}</span>-<span class="hljs-variable">${identity.user_key}</span>"</span> =&gt; identity }
  identity_store_id = element(var.identity_store_ids, 0)
  group_id          = aws_identitystore_group.aws_group[each.value.group_key].group_id
  member_id         = aws_identitystore_user.aws_user[each.value.user_key].user_id
}
</code></pre>
<ol>
<li><h4 id="heading-aws-sso-admin-permission-sets"><strong>AWS SSO Admin Permission Sets:</strong></h4>
</li>
</ol>
<p>Define AWS SSO permission sets that align with your organization's access policies. Use <code>aws_ssoadmin_permission_set</code> <code>aws_ssoadmin_permission_set_inline_policy</code> and <code>aws_ssoadmin_managed_policy_attachment</code> resources.</p>
<ul>
<li>Define Permission Set , Inline policy and managed_policy in the <a class="post-section-overview" href="#sso_permissionsets_configmap">sso_permissionsets_configmap</a> variable.</li>
</ul>
<pre><code class="lang-bash">// Terraform code <span class="hljs-keyword">for</span> AWS SSO Admin Permission Set
resource <span class="hljs-string">"aws_ssoadmin_permission_set"</span> <span class="hljs-string">"permissionset"</span> {
  for_each     = var.sso_permissionsets_configmap
  name         = each.value.name
  description  = each.value.description
  instance_arn = tolist(var.ssoadmin_instance_arns)[0]
}

resource <span class="hljs-string">"aws_ssoadmin_permission_set_inline_policy"</span> <span class="hljs-string">"inline_policy"</span> {
  for_each           = var.sso_permissionsets_configmap
  inline_policy      = each.value.inline_policy
  instance_arn       = tolist(var.ssoadmin_instance_arns)[0]
  permission_set_arn = aws_ssoadmin_permission_set.permissionset[each.key].arn
}

resource <span class="hljs-string">"aws_ssoadmin_managed_policy_attachment"</span> <span class="hljs-string">"managed_policy_attachment"</span> {
  for_each           = { <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> local.flattened_managed_policy_attachments : <span class="hljs-string">"<span class="hljs-variable">${i.permission_set_name}</span>-<span class="hljs-variable">${i.managed_policy_arn}</span>"</span> =&gt; i }
  instance_arn       = tolist(var.ssoadmin_instance_arns)[0]
  managed_policy_arn = each.value.managed_policy_arn
  permission_set_arn = aws_ssoadmin_permission_set.permissionset[each.value.permission_set_name].arn

  depends_on         = [aws_ssoadmin_account_assignment.sso_account_user, aws_ssoadmin_account_assignment.sso_account_group, ]
}
</code></pre>
<blockquote>
<p><mark>[!NOTE]</mark> Adding an explicit dependency on the account assignment resource will allow the managed policy attachment to be safely destroyed prior to the removal of the account assignment.</p>
</blockquote>
<ol>
<li><h4 id="heading-aws-sso-admin-account-assignment"><strong>AWS SSO Admin Account Assignment:</strong></h4>
</li>
</ol>
<p>Automate the assignment of AWS SSO permission sets to groups or users across multiple accounts using <code>aws_ssoadmin_account_assignment</code>.</p>
<ul>
<li>Define Users, Groups, list of permission sets mapped in the <a class="post-section-overview" href="#sso_account_configmap">sso_account_configmap</a> variable.</li>
</ul>
<pre><code class="lang-bash">// Terraform code <span class="hljs-keyword">for</span> AWS SSO Admin Account Assignment
resource <span class="hljs-string">"aws_ssoadmin_account_assignment"</span> <span class="hljs-string">"sso_account_user"</span> {
  for_each = { <span class="hljs-keyword">for</span> config <span class="hljs-keyword">in</span> local.flatten_user_configurations : <span class="hljs-string">"<span class="hljs-variable">${config.account}</span>.<span class="hljs-variable">${config.username}</span>.<span class="hljs-variable">${config.permissionset}</span>"</span> =&gt; config }

  instance_arn       = tolist(var.ssoadmin_instance_arns)[0]
  target_id          = each.value.account
  target_type        = <span class="hljs-string">"AWS_ACCOUNT"</span>
  principal_id       = data.aws_identitystore_user.aws_user[<span class="hljs-string">"<span class="hljs-variable">${each.value.account}</span>.<span class="hljs-variable">${each.value.username}</span>"</span>].user_id
  principal_type     = <span class="hljs-string">"USER"</span>
  permission_set_arn = data.aws_ssoadmin_permission_set.aws_user_permissionset[each.key].arn
}

resource <span class="hljs-string">"aws_ssoadmin_account_assignment"</span> <span class="hljs-string">"sso_account_group"</span> {
  for_each = { <span class="hljs-keyword">for</span> config <span class="hljs-keyword">in</span> local.flatten_group_configurations : <span class="hljs-string">"<span class="hljs-variable">${config.account}</span>.<span class="hljs-variable">${config.groupname}</span>.<span class="hljs-variable">${config.permissionset}</span>"</span> =&gt; config }

  instance_arn       = tolist(var.ssoadmin_instance_arns)[0]
  target_id          = each.value.account
  target_type        = <span class="hljs-string">"AWS_ACCOUNT"</span>
  principal_id       = data.aws_identitystore_group.aws_group[<span class="hljs-string">"<span class="hljs-variable">${each.value.account}</span>.<span class="hljs-variable">${each.value.groupname}</span>"</span>].group_id
  principal_type     = <span class="hljs-string">"GROUP"</span>
  permission_set_arn = data.aws_ssoadmin_permission_set.aws_group_permissionset[each.key].arn
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Automating AWS SSO configurations for complex multi-account environments brings efficiency and consistency to access management. This blog post provided a basic guide using Terraform. Tailor these configurations to fit your organization's specific requirements and enjoy a streamlined AWS SSO experience.</p>
<p><strong>🚀 Stay tuned for more empowering insights into the world of cloud infrastructure management. Happy SSO automating! 🌐</strong></p>
<p>✈️ <strong>Github</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>github.com/GirishCodeAlchemy</strong><br /><strong>✈️</strong></a> <strong>Linkedin:</strong> <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>linkedin.com/in/vgirish10</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Setting Up Jupyter Notebook Kernels for Golang and Node.js]]></title><description><![CDATA[Introduction:
Jupyter Notebook is a powerful tool for interactive computing that supports various programming languages. While Python is the default language, you can extend its capabilities by adding kernels for other languages such as Node.js and G...]]></description><link>https://alchemyblogs.dpdns.org/setting-up-jupyter-notebook-kernels-for-golang-and-nodejs</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/setting-up-jupyter-notebook-kernels-for-golang-and-nodejs</guid><category><![CDATA[Jupyter Notebook ]]></category><category><![CDATA[golang]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[jupyterhub]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Mon, 15 Jan 2024 05:33:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705295590931/5d1714e3-31a4-44c0-9e4e-dcd19f5774d2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction:</h2>
<p>Jupyter Notebook is a powerful tool for interactive computing that supports various programming languages. While Python is the default language, you can extend its capabilities by adding kernels for other languages such as Node.js and Golang. This blog post will guide you through the process of setting up Jupyter Notebook kernels for both Golang and Node.js.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites:</strong></h3>
<p>Before we start, make sure you have the following installed:</p>
<ol>
<li><p>Jupyter Notebook: Install Jupyter Notebook on your machine by following the instructions on the official website (<a target="_blank" href="https://nodejs.org/">https://jupyter.org/install</a>).</p>
</li>
<li><p>Golang: Install Golang from the official website (<a target="_blank" href="https://nodejs.org/">https://golang.org/dl/</a>).</p>
</li>
<li><p>Node.js: Install Node.js from the official website (<a target="_blank" href="https://nodejs.org/">https://nodejs.org/</a>).</p>
</li>
</ol>
<h3 id="heading-setting-up-jupyter-kernel-for-golang"><strong><mark>Setting Up Jupyter Kernel for Golang:</mark></strong></h3>
<ol>
<li><p><strong>Install Gophernotes:</strong></p>
<p> Gophernotes is a Go kernel for Jupyter Notebooks. Install it using:</p>
<pre><code class="lang-bash"> go get github.com/gopherdata/gophernotes
</code></pre>
</li>
<li><p><strong>Configure Jupyter to Use Gophernotes:</strong></p>
<p> Configure Jupyter to recognize Gophernotes as a kernel:</p>
<pre><code class="lang-bash"> mkdir -p ~/.<span class="hljs-built_in">local</span>/share/jupyter/kernels/gophernotes
 cp $(go env GOPATH)/pkg/mod/github.com/gopherdata/gophernotes@v0.7.5/kernel/* ~/.<span class="hljs-built_in">local</span>/share/jupyter/kernels/gophernotes
 <span class="hljs-built_in">cd</span> ~/.<span class="hljs-built_in">local</span>/share/jupyter/kernels/gophernotes
 chmod +w ./kernel.json <span class="hljs-comment"># in case copied kernel.json has no write permission</span>
 $ sed <span class="hljs-string">"s|gophernotes|<span class="hljs-subst">$(go env GOPATH)</span>/bin/gophernotes|"</span> &lt; kernel.json.in &gt; kernel.json
</code></pre>
<p> Ensure that the paths in the <code>kernel.json</code> file point to the correct Gophernotes installation.</p>
</li>
<li><p><strong>Launch Jupyter Notebook:</strong></p>
<p> Start Jupyter Notebook:</p>
<pre><code class="lang-bash"> jupyter notebook
</code></pre>
<p> Create a new notebook and choose the Gophernotes kernel from the "Kernel" menu.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705293661145/492e2050-0f6f-4293-a840-43c70f83c21c.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705296512609/725d814a-e421-474d-b70e-ef1916949f31.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-setting-up-jupyter-kernel-for-nodejs"><strong><mark>Setting Up Jupyter Kernel for Node.js:</mark></strong></h3>
<ol>
<li><p><strong>Install ijavascript:</strong></p>
<p> Open your terminal and install the <code>ijavascript</code> kernel using the following command:</p>
<pre><code class="lang-bash"> npm install -g ijavascript
</code></pre>
</li>
<li><p><strong>Install the Jupyter Kernel:</strong></p>
<p> Register the ijavascript kernel with Jupyter Notebook:</p>
<pre><code class="lang-bash"> ijsinstall
</code></pre>
<p> This command will create a kernel specification for ijavascript.</p>
</li>
<li><p><strong>Launch Jupyter Notebook:</strong></p>
<p> Start Jupyter Notebook using the following command:</p>
<pre><code class="lang-bash"> jupyter notebook
</code></pre>
<p> In the Jupyter Notebook interface, create a new notebook and select the ijavascript kernel from the "Kernel" menu.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705294149098/73b4feb9-d061-48d7-b4fc-550679bc5042.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705294176348/7a150675-ffc9-4764-98cd-fbc70e1a5279.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-conclusion"><strong>Conclusion:</strong></h3>
<p>Congratulations! You have successfully set up Jupyter Notebook kernels for Golang and Node.js. Now you can leverage the power of Jupyter for interactive development in these languages. Feel free to explore and experiment with your code in a collaborative and interactive environment.</p>
<p><strong>🚀 Stay tuned for more insightful content as we explore the diverse realms of programming. Happy coding and notebook-ing!🚀</strong></p>
<p>✈️ <strong>Github</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>github.com/GirishCodeAlchemy</strong></a><br /><strong>✈️ Linkedin:</strong> <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>linkedin.com/in/vgirish10</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[DevContainers: Streamlining Your Development Environment]]></title><description><![CDATA[In the ever-evolving landscape of software development, maintaining a consistent and reproducible development environment is crucial. DevContainers offers a solution by containerizing your development environment, providing a standardized setup for y...]]></description><link>https://alchemyblogs.dpdns.org/devcontainers-streamlining-your-development-environment</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/devcontainers-streamlining-your-development-environment</guid><category><![CDATA[devcontainers]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[development]]></category><category><![CDATA[dev environment]]></category><category><![CDATA[#Dev Effectiveness]]></category><category><![CDATA[Docker]]></category><category><![CDATA[vscode]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Sun, 31 Dec 2023 06:57:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1703797592245/4a848906-b9a6-420a-a2f5-df8bf21625d3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the ever-evolving landscape of software development, maintaining a consistent and reproducible development environment is crucial. DevContainers offers a solution by containerizing your development environment, providing a standardized setup for your projects. In this blog post, we'll explore what DevContainers are, how to set them up, and the benefits they bring to the development process.</p>
<h1 id="heading-what-are-devcontainers"><strong>What are DevContainers?</strong></h1>
<p><strong>DevContainers</strong> are a way to define and share development environments using containers. These containers encapsulate all the dependencies, tools, and configurations needed to run your application. By leveraging Docker under the hood, DevContainers ensures that everyone on your team has the same development environment, reducing "<strong><mark>It works on my machine</mark></strong>" issues.</p>
<h2 id="heading-setting-up-devcontainers"><strong>Setting Up DevContainers</strong></h2>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>Before diving into DevContainers, ensure you have the following installed:</p>
<ul>
<li><p>Docker</p>
</li>
<li><p>Visual Studio Code</p>
</li>
</ul>
<h3 id="heading-installation"><strong>Installation</strong></h3>
<ol>
<li><p>Install the <code>Dev Containers / Remote containers</code> extension for Visual Studio Code.</p>
</li>
<li><p>Open your project in Visual Studio Code.</p>
</li>
<li><p>Click on the <code>green/blue</code> icon in the bottom-left corner of the window, and select <code>Dev Containers: Add Development Container Configuration Files.</code></p>
</li>
</ol>
<p>This will create a <code>.devcontainer</code> folder with the necessary configuration files.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704001302903/41acf728-0cb8-41c3-866e-c5160c99720d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704001378247/1bb4d627-977f-4950-88d7-8169e24bf5f0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704005523095/f75840a6-d29d-41a8-9cde-49a982b2bc5f.png" alt /></p>
<h2 id="heading-key-features-and-benefits"><strong>Key Features and Benefits</strong></h2>
<h3 id="heading-1-isolation"><strong>1. Isolation</strong></h3>
<p>DevContainers provides a fully isolated environment for your project. Dependencies and configurations are encapsulated within the container, preventing conflicts with your local setup.</p>
<h3 id="heading-2-consistency"><strong>2. Consistency</strong></h3>
<p>Every team member, regardless of their local setup, gets the same development environment. This consistency minimizes compatibility issues and accelerates onboarding for new developers.</p>
<h3 id="heading-3-portability"><strong>3. Portability</strong></h3>
<p>DevContainers can be easily shared and replicated. Collaborators, contributors, or CI/CD pipelines can use the same container configuration, ensuring a uniform environment across different machines.</p>
<h2 id="heading-working-with-devcontainers"><strong>Working with DevContainers</strong></h2>
<h3 id="heading-configuring-devcontainers"><strong>Configuring DevContainers</strong></h3>
<p>The <code>.devcontainer</code> folder contains a <code>devcontainer.json</code> file where you can specify the container image, extensions, and settings. Customize this file to tailor the development environment to your project's needs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704001663073/d9397935-4cca-4e33-a2c3-0044676829a8.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-developing-inside-containers"><strong>Developing Inside Containers</strong></h3>
<ol>
<li><p>Open your project in Visual Studio Code.</p>
</li>
<li><p>Click on the <code>green/blue</code> icon in the bottom-left corner.</p>
</li>
<li><p>Select <code>Dev-Containers: Reopen in Container.</code></p>
</li>
</ol>
<p>Your project will now be running inside the DevContainer, with access to all the tools and dependencies defined in the configuration.</p>
<h2 id="heading-use-cases-and-scenarios"><strong>Use Cases and Scenarios</strong></h2>
<h3 id="heading-1-multi-language-projects"><strong>1. Multi-language Projects</strong></h3>
<p>DevContainers are ideal for projects that use multiple programming languages. Each language can have its own container, avoiding conflicts between language-specific dependencies.</p>
<h3 id="heading-2-team-collaboration"><strong>2. Team Collaboration</strong></h3>
<p>With DevContainers, everyone on the team gets a consistent development environment. This minimizes friction caused by differences in operating systems or individual configurations.</p>
<h3 id="heading-3-open-source-contributions"><strong>3. Open Source Contributions</strong></h3>
<p>For open-source projects, DevContainers simplify the onboarding process for contributors. They can start contributing without worrying about setting up dependencies locally.</p>
<h2 id="heading-troubleshooting-and-tips"><strong>Troubleshooting and Tips</strong></h2>
<p>While DevContainers generally provide a seamless experience, here are a few tips for troubleshooting:</p>
<ul>
<li><p>Ensure Docker is running.</p>
</li>
<li><p>Check for any errors in the Visual Studio Code output panel.</p>
</li>
<li><p>If facing issues with extensions, make sure they are compatible with the DevContainer environment.</p>
</li>
</ul>
<h2 id="heading-devcontainers-template-reference"><strong>DevContainers Template Reference</strong></h2>
<p>For your convenience, I have created a DevContainers template that you can use as a starting point for your projects. This template includes a well-configured <code>devcontainer.json</code> file and example settings to kickstart your containerized development.</p>
<p><strong>Github</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy/it-works-on-my-machine.git">https://github.com/GirishCodeAlchemy/it-works-on-my-machine.git</a></p>
<p>Feel free to clone or fork this repository and tailor it to your project requirements. We encourage contributions and improvements from the community to make this template even more versatile and useful.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>DevContainers offers a practical solution for creating consistent, isolated, and portable development environments. By adopting DevContainers, teams can streamline their workflows, enhance collaboration, and simplify the onboarding process for new members. Start containerizing your development environments today and enjoy a more reliable and efficient development experience.</p>
<h2 id="heading-additional-resources"><strong>Additional Resources</strong></h2>
<ul>
<li><p><a target="_blank" href="https://code.visualstudio.com/docs/devcontainers/containers">DevContainers Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://docs.docker.com/">Docker Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers">Visual Studio Code Remote Development</a></p>
</li>
</ul>
<h2 id="heading-call-to-action"><strong>Call to Action</strong></h2>
<p>Have you tried DevContainers in your projects? Share your experiences, tips, and tricks in the comments below. Let's build a community of developers leveraging DevContainers for a better development experience!</p>
<p><strong>🚀 Stay tuned for more updates as we continue to push the boundaries of what's possible in the world of development and containerization. Happy exploring! 🚀</strong></p>
<p>✈️ <strong>Github</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>https://github.com/GirishCodeAlchemy</strong>  
</a>✈️ <strong>Linkedin</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy"><strong>https://www.linkedin.com/in/vgirish10/</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[News Sentiment Analysis with ETL Pipeline using Kafka, Hadoop and Spark]]></title><description><![CDATA[Introduction
In today's fast-paced world, keeping track of news sentiments is crucial for various applications, ranging from financial market predictions to understanding public opinion. In this blog post, we will explore a comprehensive project that...]]></description><link>https://alchemyblogs.dpdns.org/news-sentiment-analysis-with-etl-pipeline-using-kafka-hadoop-and-spark</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/news-sentiment-analysis-with-etl-pipeline-using-kafka-hadoop-and-spark</guid><category><![CDATA[Newsapi]]></category><category><![CDATA[kafka]]></category><category><![CDATA[hadoop]]></category><category><![CDATA[spark]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Python]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Sentiment analysis]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Sat, 23 Dec 2023 00:08:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1703290027221/da064993-bf87-43fc-85e1-f121d3dfe882.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>In today's fast-paced world, keeping track of news sentiments is crucial for various applications, ranging from financial market predictions to understanding public opinion. In this blog post, we will explore a comprehensive project that combines the power of Kafka, Hadoop, Spark, and machine learning to perform sentiment analysis on news articles.</p>
<h2 id="heading-project-overview"><strong>Project Overview</strong></h2>
<h3 id="heading-objective"><strong>Objective</strong></h3>
<p>Our project goes beyond traditional sentiment analysis by creating an end-to-end pipeline that seamlessly integrates real-time data streaming, distributed storage, and advanced analytics. The goal is to provide users with a comprehensive view of the sentiments expressed in news articles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703269310074/b0332d00-8841-4772-920d-e6edb37e3924.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-technologies-used"><strong>Technologies Used</strong></h3>
<ol>
<li><p><strong>Kafka:</strong> This robust event streaming platform ensures the seamless flow of news data, making it instantly available for analysis.</p>
</li>
<li><p><strong>Hadoop:</strong> The cornerstone of our project, Hadoop's distributed file system guarantees the scalability needed to handle vast amounts of news data efficiently.</p>
</li>
<li><p><strong>Spark:</strong> With its lightning-fast data processing capabilities, Spark transforms raw news data into a format suitable for sentiment analysis, all in near real-time.</p>
</li>
<li><p><strong>Machine Learning:</strong> Our sentiment analysis model, trained on diverse datasets, showcases the capabilities of cutting-edge machine learning algorithms.</p>
</li>
</ol>
<h2 id="heading-project-components"><strong>Project Components</strong></h2>
<h3 id="heading-1-kafka-setup"><strong>1. Kafka Setup</strong></h3>
<p>Our project kicks off with the implementation of Kafka, acting as a robust and distributed event streaming platform. This ensures that news data is ingested and made available for analysis in real-time.</p>
<h3 id="heading-2-hadoop-integration"><strong>2. Hadoop Integration</strong></h3>
<p>Hadoop seamlessly integrates into our architecture, providing the reliability and scalability needed to handle the vast volumes of data generated by an ever-evolving news landscape.</p>
<h3 id="heading-3-apache-spark-for-etl"><strong>3. Apache Spark for ETL</strong></h3>
<p>Spark takes center stage for Extract, Transform, Load (ETL) processes. It efficiently cleanses and pre-processes news data, ensuring that only relevant information is passed through for sentiment analysis.</p>
<h3 id="heading-4-machine-learning-model"><strong>4. Machine Learning Model</strong></h3>
<p>Our machine learning model, an exemplar of innovation, is trained to discern sentiments within news articles accurately. Its ability to adapt to varying tones and contexts sets it apart in the field of sentiment analysis.</p>
<h3 id="heading-5-results-and-visualization"><strong>5. Results and Visualization</strong></h3>
<p>The project's culmination involves presenting the sentiment analysis results through visually compelling visualizations. Stakeholders can seamlessly grasp nuanced sentiment trends, making informed decisions based on the data-driven insights provided.</p>
<h2 id="heading-impressive-highlights"><strong>Impressive Highlights</strong></h2>
<h3 id="heading-real-time-processing"><strong>Real-time Processing</strong></h3>
<p>One of the project's standout features is its real-time data processing capabilities. The seamless flow of news data through Kafka, coupled with Spark's speed, ensures that our sentiment analysis is always up-to-date and reflective of the latest trends.</p>
<h3 id="heading-scalability"><strong>Scalability</strong></h3>
<p>Our project is designed with scalability in mind. Hadoop's distributed file system allows the storage and management of large datasets, ensuring that the pipeline can handle increasing volumes of news articles without compromising performance.</p>
<h3 id="heading-predictive-analytics"><strong>Predictive Analytics</strong></h3>
<p>The machine learning model is not just a sentiment analyzer; it's a predictive analytics tool. Its ability to adapt to emerging sentiment patterns positions our project as a proactive solution for staying ahead of the news curve.</p>
<h3 id="heading-user-friendly-visualization"><strong>User-friendly Visualization</strong></h3>
<p>We believe in making data accessible. Our visualizations are not just informative but also user-friendly, allowing stakeholders, regardless of technical background, to grasp sentiment trends effortlessly.</p>
<h2 id="heading-running-the-project"><strong>Running the Project</strong></h2>
<p>For those eager to replicate or extend this project, detailed steps are provided to guide you through the process. From setting up Kafka to training your machine learning model, we ensure that our innovation is accessible to all.</p>
<p><a target="_blank" href="https://github.com/GirishCodeAlchemy/News-sentiment-ML-ETL-pipeline">https://github.com/GirishCodeAlchemy/News-sentiment-ML-ETL-pipeline</a></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This project stands as a testament to the incredible possibilities that emerge when cutting-edge technologies unite. By combining Kafka, Hadoop, Spark, and machine learning, we've created a sentiment analysis pipeline that not only impresses with its technical prowess but also empowers users with actionable insights derived from the complex world of news sentiments.</p>
<p>Stay tuned for more updates as we continue to push the boundaries of what's possible in the realm of sentiment analysis. Happy exploring!</p>
<p>✈️ <strong>Github</strong>: <a target="_blank" href="https://github.com/GirishCodeAlchemy">https://github.com/GirishCodeAlchemy</a><br />✈️ <strong>Linkedin</strong>: <a target="_blank" href="https://www.linkedin.com/in/vgirish10/">https://www.linkedin.com/in/vgirish10/</a></p>
]]></content:encoded></item><item><title><![CDATA[Simplify Disk Space Analysis with TopNDiskAnalyzer]]></title><description><![CDATA[Introduction
Managing and understanding file sizes within a directory is a common task for developers, sysadmins, sre, and users. To simplify this process, I've created a tool called TopNDiskAnalyzer. This tool allows users to analyze and retrieve th...]]></description><link>https://alchemyblogs.dpdns.org/simplify-disk-space-analysis-with-topndiskanalyzer</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/simplify-disk-space-analysis-with-topndiskanalyzer</guid><category><![CDATA[diskusage]]></category><category><![CDATA[disk space]]></category><category><![CDATA[SRE]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[system]]></category><category><![CDATA[sysadmin]]></category><category><![CDATA[Linux]]></category><category><![CDATA[macOS]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Sun, 10 Dec 2023 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1702188694374/91de805c-9173-47c7-b501-b099d7d05350.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>Managing and understanding file sizes within a directory is a common task for developers, sysadmins, sre, and users. To simplify this process, I've created a tool called TopNDiskAnalyzer. This tool allows users to analyze and retrieve the top N files and folders based on their sizes within a specified directory.</p>
<h2 id="heading-features"><strong>Features</strong></h2>
<ol>
<li><strong>Concurrent Processing</strong></li>
</ol>
<p>TopNDiskAnalyzer leverages concurrent processing to efficiently analyze files and folders concurrently. This is achieved by utilizing goroutines in Go, ensuring optimal performance, especially when dealing with large directory structures.</p>
<ol>
<li><strong>Dynamic Top N</strong></li>
</ol>
<p>One notable feature of TopNDiskAnalyzer is its ability to dynamically set the 'N' value for the top files and folders. Users can provide the desired count using the <code>--top</code> command-line argument. If not specified, the default value is 10.</p>
<ol>
<li><strong>Informative Output</strong></li>
</ol>
<p>The tool produces insightful output, displaying the top files and folders along with their sizes in a human-readable format. The sizes are presented in KB, MB, GB, etc., making it easy for users to comprehend.</p>
<h2 id="heading-getting-started"><strong>Getting Started</strong></h2>
<h3 id="heading-installation"><strong>Installation</strong></h3>
<h4 id="heading-download-binary">Download Binary</h4>
<p>You can download the precompiled binary for your operating system from the <a target="_blank" href="https://github.com/GirishCodeAlchemy/TopNDiskAnalyzer/releases">releases page</a>.</p>
<h5 id="heading-linux"><strong>Linux:</strong></h5>
<pre><code class="lang-bash"><span class="hljs-comment"># 64-bit</span>
wget https://github.com/GirishCodeAlchemy/TopNDiskAnalyzer/releases/download/v1.0.0/tdf-linux-amd64 -O tdf
chmod +x tdf
sudo mv tdf /usr/<span class="hljs-built_in">local</span>/bin/

<span class="hljs-comment"># 32-bit</span>
wget https://github.com/GirishCodeAlchemy/TopNDiskAnalyzer/releases/download/v1.0.0/tdf-linux-386 -O tdf
chmod +x tdf
sudo mv tdf /usr/<span class="hljs-built_in">local</span>/bin/
</code></pre>
<h5 id="heading-macos"><strong>macOS:</strong></h5>
<pre><code class="lang-bash"><span class="hljs-comment"># 64-bit</span>
wget https://github.com/GirishCodeAlchemy/TopNDiskAnalyzer/releases/download/v1.0.0/tdf-darwin-amd64 -O tdf
chmod +x tdf
sudo mv tdf /usr/<span class="hljs-built_in">local</span>/bin/
</code></pre>
<h5 id="heading-windows"><strong>Windows:</strong></h5>
<p>Download the <a target="_blank" href="https://github.com/GirishCodeAlchemy/TopNDiskAnalyzer/releases/download/v1.0.0/tdf.exe">tdf.exe</a> from the <a target="_blank" href="https://github.com/GirishCodeAlchemy/TopNDiskAnalyzer/releases">releases page</a>.</p>
<h4 id="heading-build-from-source">Build from Source</h4>
<p>If you prefer to build from a source, make sure you have Go installed. Clone the repository and run the following commands:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/GirishCodeAlchemy/TopNDiskAnalyzer.git
<span class="hljs-built_in">cd</span> TopNDiskAnalyzer
go build -o tdf main.go
sudo mv tdf /usr/<span class="hljs-built_in">local</span>/bin/
</code></pre>
<p>This will provide users with clear instructions on how to download and install your TopNDiskAnalyzer tool on various operating systems.</p>
<h3 id="heading-usage"><strong>Usage</strong></h3>
<p>Once installed, you can use the tool by running the following command:</p>
<pre><code class="lang-bash">tdf [options] [directory_path]
</code></pre>
<p>Options</p>
<ul>
<li><p><code>--dir</code>: Specifies the directory path. Defaults to the current directory.</p>
</li>
<li><p><code>--top</code>: Specifies the number of top items to display. Defaults to 10.</p>
</li>
<li><p><code>--help</code>: Displays helpful information about the program and its options.</p>
</li>
</ul>
<p>The command recursively analyzes the specified directory, calculating the sizes of files and folders, and then displays the top items based on their sizes in descending order.</p>
<h2 id="heading-examples"><strong>Examples</strong></h2>
<pre><code class="lang-bash"><span class="hljs-comment"># Analyze the current directory, display top 10 items</span>
tdf

<span class="hljs-comment"># Analyze a specific directory, display top 15 items</span>
tdf --top 15 /path/to/directory 

<span class="hljs-comment"># Analyze a specific directory (using positional argument), display top 10 items</span>
tdf /path/to/directory

<span class="hljs-comment"># Help</span>
tdf --<span class="hljs-built_in">help</span>
</code></pre>
<h2 id="heading-screenshots"><strong>Screenshots</strong></h2>
<p>Here are some screenshots illustrating the usage of TopNDiskAnalyzer:</p>
<ol>
<li><p><strong>Help Command</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702179450706/e1babe21-94c8-45ca-b3a8-fe3f800e328f.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Relative Path</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702179480681/40f569ba-21b7-478b-b43b-323b19d4586e.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Absolute Path</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702179509200/4a63980a-f99b-4fa1-8d9a-47ea309dcc88.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Top Option</strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702179543290/184b4b9a-49ba-4e7f-b73c-9ffad852aada.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>TopNDiskAnalyzer provides a straightforward solution for users who need quick insights into the largest files and folders within a directory. Its concurrent processing, dynamic top N feature, and informative output make it a valuable tool for various use cases.</p>
<p>To get started, check out the <a target="_blank" href="https://github.com/GirishCodeAlchemy/TopNFileAnalyzer">GitHub repository</a> and feel free to contribute or provide feedback.</p>
<h2 id="heading-thank-you-for-reading">🙏Thank you for reading...</h2>
<p>✈️ <strong>Linkedin</strong>: <a target="_blank" href="https://www.linkedin.com/in/vgirish10/">https://www.linkedin.com/in/vgirish10/</a></p>
]]></content:encoded></item><item><title><![CDATA[Web Page Capture Tool: A Go-Based Solution for Screenshots and PDFs]]></title><description><![CDATA[In the realm of web development and automation, capturing screenshots or generating PDFs of web pages is a common need. Whether for documentation, testing, or monitoring, having a tool that simplifies this process can be invaluable. In this blog post...]]></description><link>https://alchemyblogs.dpdns.org/web-page-capture-tool-a-go-based-solution-for-screenshots-and-pdfs</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/web-page-capture-tool-a-go-based-solution-for-screenshots-and-pdfs</guid><category><![CDATA[webtopdf]]></category><category><![CDATA[webtoimage]]></category><category><![CDATA[pdfdocument]]></category><category><![CDATA[Webscreenshot]]></category><category><![CDATA[pdf]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Thu, 07 Dec 2023 16:19:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1701965714883/da5ae68f-fd64-4b9c-9209-6e2f1f9a5af2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the realm of web development and automation, capturing screenshots or generating PDFs of web pages is a common need. Whether for documentation, testing, or monitoring, having a tool that simplifies this process can be invaluable. In this blog post, we introduce a lightweight solution built with Go that leverages headless Chrome for capturing screenshots and generating PDFs.</p>
<p>Let's explore the benefits of this tool in two specific use cases:</p>
<h2 id="heading-1-storing-job-descriptions-for-applied-companies"><strong>1. Storing Job Descriptions for Applied Companies</strong></h2>
<p>One practical application of the Web Page Capture Tool is in the realm of job hunting. When applying to various companies, job seekers often come across interesting job descriptions and company information on their websites. The tool allows you to capture these web pages and store them as images or PDFs, providing a convenient way to:</p>
<ul>
<li><p><strong>Document Job Opportunities:</strong> Capture and store job descriptions along with relevant details from company websites.</p>
</li>
<li><p><strong>Offline Reference:</strong> Have a local repository of job descriptions for applied companies, allowing you to refer to them even when offline.</p>
</li>
<li><p><strong>Organized Archive:</strong> Create an organized archive of job opportunities, making it easier to review and compare roles from different companies.</p>
</li>
</ul>
<h2 id="heading-2-creating-document-versions-of-web-pages"><strong>2. Creating Document Versions of Web Pages</strong></h2>
<p>The Web Page Capture Tool is not limited to capturing job descriptions; it can be a versatile solution for creating document versions of any web page. Consider the following benefits:</p>
<ul>
<li><p><strong>Web Page Archiving:</strong> Capture web pages for archival purposes, preserving the content as it appears at a specific point in time.</p>
</li>
<li><p><strong>Documentation of Online Content:</strong> Easily document online articles, tutorials, or any other web-based content by generating PDFs.</p>
</li>
<li><p><strong>Offline Reading:</strong> Create offline versions of web pages for later reading or reference.</p>
</li>
<li><p><strong>Versioning of Online Resources:</strong> Capture different versions of web pages over time, useful for tracking changes or maintaining a historical record.</p>
</li>
</ul>
<h2 id="heading-overview"><strong>Overview</strong></h2>
<p>The Web Page Capture Tool is a Go-based command-line utility designed to interact with headless Chrome and capture web pages in two formats: screenshots (images) and PDFs. The tool is simple to use, allowing users to specify a URL, the desired output format (image or PDF), and an optional filename. If no filename is provided, the tool defaults to a predefined name.</p>
<h2 id="heading-getting-started"><strong>Getting Started</strong></h2>
<p>To get started with the Web Page Capture Tool, you can download the pre-built binary from the <a target="_blank" href="https://github.com/GirishCodeAlchemy/WebPageCapture.git">GitHub repository</a></p>
<ol>
<li><p>Download the latest binary from the <a target="_blank" href="https://github.com/GirishCodeAlchemy/WebPageCapture/releases/download/v1.0.0/web-capture-tool">Releases</a></p>
<pre><code class="lang-bash"> wget https://github.com/GirishCodeAlchemy/WebPageCapture/releases/download/v1.0.0/web-capture-tool
</code></pre>
</li>
<li><p>Once downloaded, make the binary executable:</p>
<pre><code class="lang-bash"> chmod +x web-capture-tool
</code></pre>
</li>
<li><p>Move the binary to a directory in your system's PATH, so you can run it from any location:</p>
<pre><code class="lang-bash"> sudo mv web-capture-tool /usr/<span class="hljs-built_in">local</span>/bin/
</code></pre>
</li>
</ol>
<h2 id="heading-usage"><strong>Usage</strong></h2>
<h3 id="heading-help-and-usage"><strong>Help and Usage:</strong></h3>
<p>For detailed information about the available flags and options, you can use the following command:</p>
<pre><code class="lang-bash">web-capture-tool --<span class="hljs-built_in">help</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703907046188/c532eda8-388e-43b9-8546-d582edd655b6.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-capture-screenshot"><strong>Capture Screenshot:</strong></h3>
<p>To capture a screenshot of a web page, run the following command:</p>
<pre><code class="lang-bash">./web-capture-tool &lt;URL&gt; image [filename]
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">./web-capture-tool https://example.com image output.jpg
</code></pre>
<h3 id="heading-generate-pdf"><strong>Generate PDF:</strong></h3>
<p>To generate a PDF of a web page, use the following command:</p>
<pre><code class="lang-bash">./web-capture-tool &lt;URL&gt; pdf [filename]
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">./web-capture-tool https://example.com pdf output.pdf
</code></pre>
<h2 id="heading-customization-and-extension"><strong>Customization and Extension</strong></h2>
<p>The tool is intentionally kept minimal to serve as a foundation that can be extended based on specific requirements. Users familiar with Go can explore the code and customize the tool to suit their needs. Additionally, integrating it into existing automation pipelines or scripts is straightforward.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>The Web Page Capture Tool provides a quick and efficient way to capture web pages in both image and PDF formats. Its simplicity makes it suitable for various use cases, and the underlying Go and Chrome integration offers flexibility and reliability. Whether you need to document web pages, perform visual testing, job hunting, and content documentation, or automate PDF generation, this tool can be a valuable addition to your toolkit.</p>
<p>Feel free to explore, modify, and adapt the Web Page Capture Tool based on your specific needs. Whether you're building a repository of job opportunities or archiving online content, this tool can enhance your web capture workflows. Give it a try, and let us know how it fits into your use cases!</p>
<p>Give it a try, and let us know how it fits into your web capture workflows!</p>
<h2 id="heading-thank-you-for-reading">🙏Thank you for reading...</h2>
<p>✈️ <strong>Linkedin</strong>: <a target="_blank" href="https://www.linkedin.com/in/vgirish10/">https://www.linkedin.com/in/vgirish10/</a></p>
]]></content:encoded></item><item><title><![CDATA[Kubernetes Troubleshooting Simplified: A Beginner's Guide]]></title><description><![CDATA[What is Docker? What is a container? Why are they important?
Docker is like a magic box for software. It holds everything an app needs to run, like the app itself, tools, and libraries. It's like a lunchbox for your software.
Software is often a mix ...]]></description><link>https://alchemyblogs.dpdns.org/kubernetes-troubleshooting-simplified-a-beginners-guide</link><guid isPermaLink="true">https://alchemyblogs.dpdns.org/kubernetes-troubleshooting-simplified-a-beginners-guide</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Kubernetes-troubleshooting]]></category><dc:creator><![CDATA[Girish V]]></dc:creator><pubDate>Tue, 24 Oct 2023 03:54:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/9cXMJHaViTM/upload/2d662bbde3eb290adf0f5e26430708af.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<p><strong>What is Docker? What is a container? Why are they important?</strong></p>
<p>Docker is like a magic box for software. It holds everything an app needs to run, like the app itself, tools, and libraries. It's like a lunchbox for your software.</p>
<p>Software is often a mix of different parts, like web servers, databases, and other tools. When people build software, they sometimes face problems, like making sure it works on different computers.</p>
<p>Docker containers help with this. They keep everything together, so the software runs the same everywhere. It's like a lunchbox that keeps your food fresh.</p>
<p>So, Docker makes it easier for developers to create, share, and run their software. It's a helpful tool for building and managing software.</p>
<h1 id="heading-docker">Docker</h1>
<p>Docker is a suite of platform-as-a-service products that utilize OS-level virtualization to distribute software within self-contained units called containers. These containers share the underlying operating system kernel but are isolated from one another. Each container includes its own software, libraries, and configuration files.</p>
<ul>
<li><p>Docker is known for its swift(Fast) startup times.</p>
</li>
<li><p>In Docker, an 'image' serves as a preconfigured template.</p>
</li>
<li><p>Containers, in contrast, represent active instances of these images. They run in isolation, maintaining their own environments and sets of processes</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698114491370/c788c2c2-9f5b-4c4a-b059-158c347d8d9e.png" alt /></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698115838246/2af86e5d-7e2e-4b06-8d1e-346f620298a4.png" alt class="image--center mx-auto" /></p>
<p><strong>What is Orchestration? Why Do We Need Container Orchestration?</strong></p>
<ul>
<li>Orchestration in system administration involves the automated configuration, coordination, and management of computer systems and software. Numerous tools are available for automating server configuration and management.</li>
</ul>
<p>In container orchestration, the focus is on monitoring application load and performance while ensuring the swift deployment of new containers in case of failures.</p>
<p>Container orchestration automates various aspects of coordinating and managing containers, primarily concentrating on the lifecycle of containers and their dynamic environments.</p>
<p>Container orchestration serves to automate the following tasks at scale:</p>
<ul>
<li><p>Configuring and scheduling containers</p>
</li>
<li><p>Provisioning and deploying containers</p>
</li>
<li><p>Managing container availability</p>
</li>
<li><p>Configuring applications based on the containers they run in</p>
</li>
<li><p>Scaling containers to evenly distribute application workloads across infrastructure</p>
</li>
<li><p>Allocating resources among containers</p>
</li>
<li><p>Handling load balancing, traffic routing, and service discovery for containers</p>
</li>
<li><p>Monitoring the health of containers</p>
</li>
<li><p>Ensuring secure interactions between containers</p>
</li>
</ul>
<p>Container orchestration comprises a set of tools and scripts that aid in hosting and managing containers.</p>
<p>There are multiple container orchestration options available today, including Docker Swarm, Kubernetes, Mesos (Apache), and cloud solutions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698116273909/843db7d2-9682-4d54-b752-bbba693ea9b4.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-kubernetes"><strong>Kubernetes</strong></h1>
<p>Kubernetes is an open-source container orchestration system that automates application deployment, scaling, and management.</p>
<ul>
<li>Kubernetes is like a smart manager for your apps. It helps them deploy, grow, and stay organized. To talk to Kubernetes, you use a tool called <code>kubectl</code> which is a command line interface</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698116523965/c174512a-af4b-4809-8e3d-b85a6a9770b1.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>ETCD: Your Kubernetes Memory</strong></p>
<p> Think of etcd as Kubernetes' memory. It stores information about the nodes in a simple key-value format, such as which containers are on which node and when they were loaded. All this data is kept in a special place called etcd.</p>
</li>
<li><p><strong>Kube-scheduler: The Smart Deployer</strong></p>
<p> Kube-scheduler is like a smart organizer. It finds the perfect node to put your container based on its needs, how much space is available on worker nodes, and any other rules you've set.</p>
</li>
<li><p><strong>Controller Manager: The Node Manager</strong></p>
<p> The controller manager is in charge of handling new nodes joining the cluster and dealing with situations where nodes go missing. It's like the person who welcomes new members to a club.</p>
</li>
<li><p><strong>Kube-api server: The Commander</strong></p>
<p> The kube-api server is the commander of the Kubernetes army. It manages everything that happens within the cluster and provides an interface for people outside the cluster to make things happen.</p>
</li>
<li><p><strong>Kubelet: The Watchful Guard</strong></p>
<p> Kubelet is like a guardian for each node in the cluster. It takes orders from the kube-api server and makes sure everything runs smoothly. The kube-api server also keeps an eye on kubelet to know what's happening with nodes and containers.</p>
</li>
<li><p><strong>Kube-proxy: The Traffic Cop</strong></p>
<p> Kube-proxy makes sure the traffic rules are set on worker nodes so containers can talk to each other.</p>
</li>
<li><p><strong>Kubernetes Runtime Environment: Where the Magic Happens</strong></p>
</li>
<li><p><strong>Kubectl: Your Command Center</strong></p>
<p> Kubectl is like a remote control for your Kubernetes cluster. It's how you give orders and get things done. You can tell kubectl what to do with simple commands.</p>
</li>
<li><p><strong>Pods: Where Your Apps Live</strong></p>
<p> A pod is like a cozy home for your apps. It's the smallest thing Kubernetes can manage, and it's where your containers live. Think of a pod as a special place where different parts of your app can talk to each other. But be careful – if a pod's home (the node) goes away, the pod disappears too. It's not built to survive the destruction of its home.</p>
</li>
</ol>
<h3 id="heading-kubernetes-deployment-script"><strong>Kubernetes Deployment Script</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">your-app-deployment</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">your-app</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">your-app</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">your-app-container</span>
          <span class="hljs-attr">image:</span> <span class="hljs-string">your-app-image:latest</span>
          <span class="hljs-attr">ports:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>
          <span class="hljs-attr">env:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">ENV_VARIABLE_NAME</span>
              <span class="hljs-attr">value:</span> <span class="hljs-string">"your-environment-value"</span>
          <span class="hljs-attr">resources:</span>
            <span class="hljs-attr">requests:</span>
              <span class="hljs-attr">memory:</span> <span class="hljs-string">"64Mi"</span>
              <span class="hljs-attr">cpu:</span> <span class="hljs-string">"250m"</span>
            <span class="hljs-attr">limits:</span>
              <span class="hljs-attr">memory:</span> <span class="hljs-string">"128Mi"</span>
              <span class="hljs-attr">cpu:</span> <span class="hljs-string">"500m"</span>
          <span class="hljs-attr">affinity:</span>
            <span class="hljs-attr">nodeAffinity:</span>
              <span class="hljs-attr">requiredDuringSchedulingIgnoredDuringExecution:</span>
                <span class="hljs-attr">nodeSelectorTerms:</span>
                  <span class="hljs-bullet">-</span> <span class="hljs-attr">matchExpressions:</span>
                    <span class="hljs-bullet">-</span> <span class="hljs-attr">key:</span> <span class="hljs-string">node-label-key</span>
                      <span class="hljs-attr">operator:</span> <span class="hljs-string">In</span>
                      <span class="hljs-attr">values:</span>
                        <span class="hljs-bullet">-</span> <span class="hljs-string">node-label-value</span>
</code></pre>
<ul>
<li><p><code>apiVersion</code> specifies the Kubernetes API version for deployments.</p>
</li>
<li><p><code>kind</code> specifies that this is a deployment.</p>
</li>
<li><p><code>metadata</code> includes information like the name of your deployment.</p>
</li>
<li><p><code>spec</code> defines the desired state for your deployment. You can adjust the number of replicas, the container image, and the container port to fit your application's requirements.</p>
</li>
<li><p><code>env</code> allows you to specify environment variables for your container.</p>
</li>
<li><p><code>resources</code> define resource requests and limits for memory and CPU.</p>
</li>
<li><p><code>affinity</code> enables you to set node affinity based on node labels.</p>
</li>
</ul>
<p>Make sure to replace <code>your-app-deployment</code>, <code>your-app</code>, <code>your-app-container</code>, and <code>your-app-image:latest</code> with the appropriate values for your application. This script will create a deployment with three replica pods.</p>
<p>You can save this script in a YAML file, and then apply it to your Kubernetes cluster using the <code>kubectl apply -f your-script.yaml</code> command. This will deploy your application on Kubernetes.</p>
<p><img src="https://github.com/rootsongjc/kubernetes-handbook/blob/master/images/deployment-cheatsheet.png?raw=true" alt="deployment-cheatsheet.png" /></p>
<h3 id="heading-service"><strong>Service</strong></h3>
<p>In Kubernetes, a service is a bit like a group of pods. It's a way to organize and access these pods.</p>
<p>There are three main types of services:</p>
<ol>
<li><p><strong>NodePort</strong>: This service type lets you access your pods from outside the cluster. It's like opening a door on each node so that external traffic can reach your pods.</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">my-nodeport-service</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span>
   <span class="hljs-attr">ports:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>
       <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">my-app</span>
</code></pre>
</li>
<li><p><strong>ClusterIP</strong>: These services make your pods accessible only from within the cluster. It's like an internal phone system that lets pods talk to each other.</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">my-clusterip-service</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">type:</span> <span class="hljs-string">ClusterIP</span>
   <span class="hljs-attr">ports:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>
       <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">my-app</span>
</code></pre>
</li>
<li><p><strong>LoadBalancer</strong>: This type sets up a load balancer that can distribute external traffic to your pods. It's like having a receptionist who directs calls to the right person.</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">my-loadbalancer-service</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">type:</span> <span class="hljs-string">LoadBalancer</span>
   <span class="hljs-attr">ports:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>
       <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">my-app</span>
</code></pre>
</li>
</ol>
<p>Services help manage how your pods are reached and used, making it easier to run your applications.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698117362418/b4ec381f-e1a6-4d13-a490-a3596bc3ffea.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698117416261/e307045a-7e96-4934-a218-06895a1491de.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698117445250/f89519e5-62c7-4e22-954e-904a55309fc3.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-kubernetes-cheet-sheet">Kubernetes Cheet Sheet</h1>
<p><img src="https://github.com/rootsongjc/kubernetes-handbook/blob/master/images/kubernetes-kubectl-cheatsheet.png?raw=true" alt="kubernetes-kubectl-cheatsheet.png" /></p>
<h1 id="heading-kubernetes-trouble-shoot">Kubernetes Trouble Shoot</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698117682585/0140fea1-1a05-4936-8562-4ab0f3463352.png" alt class="image--center mx-auto" /></p>
<p><img src="https://github.com/rootsongjc/kubernetes-handbook/blob/master/images/zero-downtime-kubernetes-upgrade-tips.jpg?raw=true" alt="zero-downtime-kubernetes-upgrade-tips.jpg" /></p>
<h2 id="heading-resources"><strong>📚Resources</strong></h2>
<p>1) <a target="_blank" href="https://github.com/rootsongjc/kubernetes-handbook/tree/master">rootsongjc/kubernetes-handbook/</a></p>
<p>2) <a target="_blank" href="https://kubernetes.io/docs/home/">https://kubernetes.io/docs/home/</a></p>
<p>3) <a target="_blank" href="https://learnk8s.io/troubleshooting-deployments">https://learnk8s.io/troubleshooting-deployments</a></p>
<h2 id="heading-thank-you-for-reading">🙏Thank you for reading...</h2>
<p>✈️ <strong>Linkedin</strong>: <a target="_blank" href="https://www.linkedin.com/in/vgirish10/">https://www.linkedin.com/in/vgirish10/</a></p>
]]></content:encoded></item></channel></rss>