<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Azeez Lukman</title>
    <description>The latest articles on DEV Community by Azeez Lukman (@robogeek95).</description>
    <link>https://dev.to/robogeek95</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F112474%2F4510b417-0e82-415f-9717-aa6df69b79b6.jpg</url>
      <title>DEV Community: Azeez Lukman</title>
      <link>https://dev.to/robogeek95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robogeek95"/>
    <language>en</language>
    <item>
      <title>Leveraging Deployment Inputs in VMware Orchestrator (VRO) for Enhanced Workflow Customization</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Sat, 07 Oct 2023 01:05:46 +0000</pubDate>
      <link>https://dev.to/robogeek95/leveraging-deployment-inputs-in-vmware-orchestrator-vro-for-enhanced-workflow-customization-54b8</link>
      <guid>https://dev.to/robogeek95/leveraging-deployment-inputs-in-vmware-orchestrator-vro-for-enhanced-workflow-customization-54b8</guid>
      <description>&lt;p&gt;VMware Orchestrator (VRO) is a powerful tool that offers a wide array of functionalities for managing and orchestrating deployments. One crucial aspect of these deployments is the ability to customize them according to specific requirements. VRO allows users to declare deployment inputs, which can be subsequently employed to tailor the deployment process to meet specific needs.&lt;/p&gt;

&lt;p&gt;In this article, we'll delve into the intricacies of obtaining deployment inputs in VRO and how to effectively utilize them to enhance the customization of your workflows. We'll explore a scenario where these inputs are invaluable, such as allowing users to specify security groups or instance profiles during the deployment process. We will also discuss the role of a VMware vRealize Automation (vRA) endpoint in accessing deployment events, which serve as a repository for these essential inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding Deployment Inputs in VRO&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before we dive into the technical details, let's first grasp the concept of deployment inputs in VRO. Deployment inputs are essentially parameters or variables that allow users to influence the behaviour of their deployments. These inputs can range from simple values, like specifying the number of instances, to more complex configurations, such as security group associations or instance profile assignments. They provide a way to fine-tune deployments without the need for manual intervention at every step.&lt;/p&gt;

&lt;p&gt;Imagine a scenario where you are orchestrating the deployment of virtual machines within a cloud environment. You might want to allow users to define the security groups and instance profiles that should be associated with these virtual machines. This is where deployment inputs come into play. Users can provide these inputs via an input form or an API call, allowing for a high degree of customization.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Accessing Deployment Events via vRA Endpoint&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To effectively harness deployment inputs, VRO relies on a connection to VMware's vRealize Automation (vRA). vRA serves as a comprehensive cloud automation platform that can be integrated with VRO to extend its capabilities. It's through this integration that VRO gains access to deployment events, which are pivotal for obtaining the deployment inputs.&lt;/p&gt;

&lt;p&gt;Deployment events are essentially records or logs of what transpires during a deployment process. They contain a wealth of information, including the deployment inputs provided by users. These events are invaluable for troubleshooting, auditing, and most importantly, for customizing workflows.&lt;/p&gt;

&lt;p&gt;To access these deployment events, you need to make a request to the endpoint below:&lt;/p&gt;

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

/deployment/api/deployments/&lt;span class="s2"&gt;" + deploymentId + "&lt;/span&gt;/events&lt;span class="s2"&gt;"


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

&lt;/div&gt;

&lt;p&gt;Remember to replace &lt;code&gt;deploymentId&lt;/code&gt; with the id of your deployment. This endpoint can query and retrieve deployment events, making the deployment inputs available for further processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating a Custom Action to Manipulate Deployment Inputs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's move to the practical implementation of obtaining and utilizing deployment inputs. The first step is to create a custom action within VRO. This action will be designed to interact with the vRA endpoint and retrieve the deployment inputs associated with a specific deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create New Action
&lt;/h3&gt;

&lt;p&gt;Create an action by navigating to Orchestrator and on the actions page you can find a button to create a new action at the top of the page, use the screenshots below for reference:&lt;/p&gt;

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

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

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

&lt;p&gt;You can name it “getDeploymentInputs” and select a module to store it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Declare Inputs
&lt;/h3&gt;

&lt;p&gt;Now, it’s time to build out the action. This action should take the deployment ID as input. With the deployment ID, it can query the vRA endpoint to fetch the corresponding deployment events. &lt;/p&gt;

&lt;p&gt;Find Inputs and create a new one, specify &lt;code&gt;deploymentId&lt;/code&gt; as the name, as for the type, the returned events are typically represented as an array of events, which includes the deployment inputs, this can be represented as &lt;code&gt;Properties&lt;/code&gt;, enter &lt;code&gt;Properties&lt;/code&gt; for the type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write Custom Script
&lt;/h3&gt;

&lt;p&gt;Declare a path as the endpoint specified earlier, and the action should be &lt;code&gt;GET&lt;/code&gt;:&lt;/p&gt;

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

var action &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
var path &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/deployment/api/deployments/"&lt;/span&gt; + deploymentId + &lt;span class="s2"&gt;"/events"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then, add the script below:&lt;/p&gt;

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

deploymentEventsResponse &lt;span class="o"&gt;=&lt;/span&gt; System.getModule&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"com.vra.rest"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;.vraRestCall&lt;span class="o"&gt;(&lt;/span&gt;action, path, null, null&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
var deploymentInputs &lt;span class="o"&gt;=&lt;/span&gt; deploymentEventsResponse[&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;0][&lt;span class="s1"&gt;'inputs'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

System.log&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"deploymentInputs: "&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
System.log&lt;span class="o"&gt;(&lt;/span&gt;deploymentInputs&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return &lt;/span&gt;deploymentInputs&lt;span class="p"&gt;;&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;This script sends a request to retrieve the deployment events. Let's break down its components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Making the API Call&lt;/strong&gt;: The &lt;code&gt;vraRestCall&lt;/code&gt; method is used to make an HTTP GET request to the API path. This function is part of the "com.vra.rest" module, which must have been properly configured in your VRO environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Processing the Response&lt;/strong&gt;: We store the response from the API call in the &lt;code&gt;deploymentEventsResponse&lt;/code&gt; variable. This response typically contains all the deployment events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessing Deployment Inputs&lt;/strong&gt;: The script extracts the &lt;code&gt;inputs&lt;/code&gt; array from the content of the first event in the response. This is where the deployment inputs are stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging and Returning the Inputs&lt;/strong&gt;: You can then log the retrieved deployment inputs using &lt;code&gt;System.log&lt;/code&gt; for debugging and visibility. Finally, it returns the deployment inputs for further use in your workflow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Save your action and you should be all good 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Integrating the Custom Action into Workflows&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With the custom action in place, you can seamlessly integrate it into your VRO workflows. For instance, in the scenario mentioned earlier, where users specify security groups and instance profiles, you can use the custom action within the deployment workflow. This ensures that the desired customization occurs as part of the deployment process.&lt;/p&gt;

&lt;p&gt;The flexibility of this approach allows for a wide range of use cases. You can use deployment inputs to automate various aspects of your cloud infrastructure, from network configurations to application installations, all while providing users with the ability to tailor these deployments to their specific needs.&lt;/p&gt;

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

&lt;p&gt;In conclusion, VRO provides a robust framework for orchestrating and automating deployments, and the ability to leverage deployment inputs adds an extra layer of customization and flexibility to this process. By establishing a connection with vRA, accessing deployment events, and creating custom actions to manipulate deployment inputs, you can tailor your workflows to meet your organization's unique requirements. This not only streamlines your cloud management but also empowers your users to actively participate in the customization of their deployments. The synergy between VRO and vRA, in combination with custom actions, enables you to unlock the full potential of cloud orchestration and automation.&lt;/p&gt;

&lt;p&gt;My name is Azeez Lukman, and I'm passionate about simplifying complex technical processes and sharing insights into the world of software engineering and cloud automation. Find me everywhere &lt;a class="mentioned-user" href="https://dev.to/robogeek95"&gt;@robogeek95&lt;/a&gt; for more articles like this.&lt;/p&gt;

</description>
      <category>vra</category>
      <category>devops</category>
      <category>cloud</category>
      <category>automation</category>
    </item>
    <item>
      <title>Comprehensive Guide to Infrastructure Continuous Integration and Continuous Deployment with Terraform and GitLab CI/CD</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Thu, 21 Sep 2023 08:25:29 +0000</pubDate>
      <link>https://dev.to/robogeek95/comprehensive-guide-to-infrastructure-continuous-integration-and-continuous-deployment-with-terraform-and-gitlab-cicd-4b5m</link>
      <guid>https://dev.to/robogeek95/comprehensive-guide-to-infrastructure-continuous-integration-and-continuous-deployment-with-terraform-and-gitlab-cicd-4b5m</guid>
      <description>&lt;p&gt;The practice of Infrastructure as Code (IAC) has witnessed an exponential surge in popularity in recent years. DevOps engineers, in particular, have found IAC to be a transformative approach, enabling them to automate infrastructure provisioning and management, resulting in more efficient and scalable processes. &lt;/p&gt;

&lt;p&gt;In this comprehensive guide, we will delve into the world of Infrastructure Continuous Integration (CI) and Continuous Deployment (CD) with GitLab, tailored for advanced DevOps professionals aiming to optimize their workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Getting to Know Terraform&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before we embark on our journey into CI/CD with GitLab, it's crucial to have a solid understanding of Terraform. Terraform, developed by HashiCorp, is a powerful open-source Infrastructure as a Code tool. It empowers users to define their infrastructure as code, offering a clear and repeatable method for provisioning and managing resources across diverse cloud providers and on-premises environments. Some key advantages of Terraform include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Declarative Configuration&lt;/strong&gt;: Terraform employs a declarative syntax, allowing you to describe the desired end state of your infrastructure, while Terraform determines the steps to achieve it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Cloud Support&lt;/strong&gt;: Terraform boasts compatibility with a multitude of cloud providers, facilitating the implementation of a multi-cloud strategy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control&lt;/strong&gt;: Terraform configurations are stored in version control repositories, fostering collaboration and change tracking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Overview of GitLab CI/CD&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;GitLab encompasses a comprehensive DevOps platform with robust CI/CD capabilities. It empowers DevOps engineers to automate processes such as code testing, building, and deployment, including Terraform configurations. The fundamental components of GitLab CI/CD include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runners&lt;/strong&gt;: GitLab Runners serve as agents responsible for executing CI/CD jobs. They are adaptable and can be installed on various platforms, ensuring that your pipelines can run tasks across diverse environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipelines&lt;/strong&gt;: Pipelines define the complete process of code building, testing, and deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobs&lt;/strong&gt;: Each job within a pipeline represents an individual task, such as executing tests or applying Terraform configurations. We will also explore how to use GitLab's artifact feature to store files and data generated by a job, which is invaluable for transferring data between jobs or stages within a pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Setting Up GitLab for Terraform&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To kickstart your GitLab CI/CD journey for Terraform, the initial step is to create a GitLab project or repository to host your Terraform code. Properly structuring your Terraform project within a Git repository is important for effective version control and collaboration. Consider organizing your repository with directories dedicated to different environments (e.g., development, staging, production) and adopt Git branching strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating CI/CD Pipelines for Terraform&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;GitLab CI/CD pipelines are defined using a &lt;strong&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/strong&gt; file situated within your repository. This YAML file outlines the stages, jobs, and dependencies for your CI/CD process. For Terraform, your CI/CD pipeline may encompass stages such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linting&lt;/strong&gt;: The process of examining Terraform code for syntax and style-related issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt;: Ensuring that Terraform configurations are both valid and safe to apply.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planning and Applying&lt;/strong&gt;: Creating an execution plan and implementing changes to the infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: Running infrastructure tests to validate that the changes meet the specified requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  *&lt;strong&gt;&lt;em&gt;Create the Pipeline File&lt;/em&gt;&lt;/strong&gt;*
&lt;/h3&gt;

&lt;p&gt;Start by creating a file named &lt;strong&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt; in&lt;/strong&gt; your GitHub project. This YAML file will define your CI/CD pipeline configuration. The file should be created in the root directory to ensure that GitLab can automatically detect and use it to set up and run your CI/CD pipeline for that project. If you place it in a subdirectory, GitLab will not recognize it as the configuration file for the project's pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;touch&lt;/span&gt; &lt;span class="o"&gt;****&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gitlab&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;&lt;span class="o"&gt;****&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Define Stages and Jobs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Inside your &lt;strong&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/strong&gt; file, define the stages and jobs for your Terraform CI/CD pipeline. Here's an example configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;plan&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apply&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;TF_VAR_AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;AWS_ACCESS_KEY_ID&amp;gt;"&lt;/span&gt;
  &lt;span class="na"&gt;TF_VAR_AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;AWS_SECRET_ACCESS_KEY&amp;gt;"&lt;/span&gt;

&lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;plan&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;terraform init&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;terraform plan -out=terraform.tfplan&lt;/span&gt;

&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apply&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;terraform apply -auto-approve terraform.tfplan&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt; &lt;span class="c1"&gt;# You can adjust the branch where you want to apply changes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have two stages: &lt;strong&gt;&lt;code&gt;plan&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt;. The &lt;strong&gt;&lt;code&gt;plan&lt;/code&gt;&lt;/strong&gt; stage initializes Terraform and creates a plan file, while the &lt;strong&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt; stage applies the changes using the generated plan file. We also set two variables, &lt;code&gt;TF_VAR_AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;TF_VAR_AWS_SECRET_ACCESS_KEY&lt;/code&gt;, which allow you to specify your AWS credentials, remember to replace them with your actual values. More information on securing the use of these credentials will be provided later in this article.&lt;/p&gt;

&lt;p&gt;ok… let’s break things down a little more&lt;/p&gt;

&lt;p&gt;In GitLab CI/CD, a pipeline is divided into stages, and each stage contains one or more jobs. Stages represent different phases of your CI/CD process, and jobs within each stage define specific tasks to be executed. In the example above, we've defined two stages: &lt;strong&gt;&lt;code&gt;plan&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt;. Here's what each stage represents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Plan Stage&lt;/strong&gt;: This is the first stage in our CI/CD pipeline. In this stage, we typically perform tasks related to Terraform planning. Planning involves checking the current state of your infrastructure, comparing it to your Terraform code, and generating an execution plan that describes what changes will be made when you apply your Terraform configuration.&lt;/p&gt;

&lt;p&gt;Within this stage, a job named &lt;strong&gt;plan&lt;/strong&gt; is defined. This job belongs to the &lt;strong&gt;plan&lt;/strong&gt; stage and contains the terraform commands to init and plan the terraform configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Apply Stage&lt;/strong&gt;: The second stage in our pipeline is the &lt;strong&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt; stage. This is where we actually apply the changes to our infrastructure based on the execution plan generated in the previous stage. Applying Terraform changes may involve creating, updating, or deleting resources in your cloud infrastructure.&lt;/p&gt;

&lt;p&gt;The job within this stage &lt;strong&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt; stage specifies the script that defines the commands to be executed as part of the job. Here's what the command does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;terraform apply -auto-approve terraform.tfplan&lt;/code&gt;&lt;/strong&gt;: Applies the Terraform changes using the execution plan generated in the previous stage. The &lt;strong&gt;&lt;code&gt;auto-approve&lt;/code&gt;&lt;/strong&gt; flag automatically approves and applies the changes without requiring manual confirmation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;only&lt;/code&gt;&lt;/strong&gt;: This section specifies the branch where this job should be executed. In this example, the &lt;strong&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt; job will only run when changes are pushed to the &lt;strong&gt;&lt;code&gt;main&lt;/code&gt;&lt;/strong&gt; branch. You can adjust this branch name to match your specific deployment strategy.&lt;/li&gt;
&lt;/ul&gt;


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

&lt;h3&gt;
  
  
  Trigger the pipeline run
&lt;/h3&gt;

&lt;p&gt;The most common and fundamental way to trigger a GitLab CI/CD pipeline is by pushing code changes to your GitLab repository. GitLab is designed to automatically detect changes in your codebase and initiate the CI/CD pipeline accordingly. This seamless integration ensures that your pipeline runs whenever there are new commits or merged branches in your repository. You can also manually trigger a pipeline via the GitLab UI.&lt;/p&gt;

&lt;p&gt;Save your &lt;strong&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/strong&gt; file and commit it to your GitLab repository. Push the changes to trigger your first CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;Once you've pushed your changes, visit your GitLab repository's CI/CD section to monitor the progress of your pipeline. GitLab will automatically detect the &lt;strong&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/strong&gt; file and start executing the defined stages and jobs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Review Pipeline Output&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As the pipeline runs, you can review the output of each job and check for any errors or issues. If everything is successful, your Terraform changes will be applied to the specified environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coffee break…
&lt;/h2&gt;

&lt;p&gt;You made it this far Congratulations on your first successful pipeline deployment.&lt;/p&gt;

&lt;p&gt;Grab some coffee before we continue to reviewing some more concepts you can put in place to ensure you are securely deploying these changes into your environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Manual Approvals&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the previous example, you may have noticed that the pipeline run deployed changes directly into the environment. However, this is usually not desired in production environments.&lt;/p&gt;

&lt;p&gt;Manual approvals in GitLab CI/CD are a critical feature that allows you to introduce a human validation step into your automated pipeline. This validation ensures that certain stages or jobs in your CI/CD process won't proceed without manual confirmation, typically by authorized team members. This concept helps maintain control, security, and accuracy in your deployment process, particularly when deploying to production environments or making significant changes to your infrastructure.&lt;/p&gt;

&lt;p&gt;To make a job dependent on manual approval, you include the &lt;strong&gt;&lt;code&gt;when: manual&lt;/code&gt;&lt;/strong&gt; attribute in the job definition. This attribute tells GitLab that the job should not automatically start but should wait for manual intervention. &lt;/p&gt;

&lt;p&gt;Update the apply stage in your configuration to reflect the attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt;
  &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;approve&lt;/span&gt; &lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfplan&lt;/span&gt;
  &lt;span class="nx"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;master&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;adjust&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;branch&lt;/span&gt; &lt;span class="nx"&gt;where&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt;
  &lt;span class="nx"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;manual&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How does the manual approval work?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Manual Trigger&lt;/strong&gt;: When the pipeline reaches a job that has &lt;strong&gt;&lt;code&gt;when: manual&lt;/code&gt;&lt;/strong&gt;, GitLab will display a "Play" button next to that job in the pipeline view. Only users with appropriate permissions can click this button to manually trigger the job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization&lt;/strong&gt;: GitLab ensures that only authorized users, such as team leads or administrators, can approve and trigger manual jobs. Access control and permissions are managed through GitLab's role-based access control system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual Intervention&lt;/strong&gt;: When a team member clicks the "Play" button to trigger a manual job, they may be prompted to provide additional information or confirm the action. This step adds a layer of accountability and documentation to the process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job Execution&lt;/strong&gt;: Once the manual job is triggered, it proceeds as usual, executing the defined script or commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subsequent Jobs&lt;/strong&gt;: After the manual job has been executed and approved, the pipeline continues with any subsequent jobs that are not set to &lt;strong&gt;&lt;code&gt;when: manual&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Securely Storing Secrets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To manage sensitive information like API keys and credentials, utilize GitLab's built-in secret management. Store these secrets as CI/CD environment variables to keep them secure.&lt;/p&gt;

&lt;p&gt;Securing secrets in GitLab CI/CD is a critical practice for several important reasons. It is not just a best practice; it's a fundamental aspect of maintaining the security, compliance, and reliability of your automation processes. By implementing robust secret management practices, you reduce the risk of data breaches, protect sensitive information, and enhance the overall security posture of your projects.&lt;/p&gt;

&lt;p&gt;GitLab provides a robust mechanism for managing and securely accessing secrets. Let's explore this concept step by step:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Access Project Settings&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to your GitLab account.&lt;/li&gt;
&lt;li&gt;Navigate to the project where you want to store secrets.&lt;/li&gt;
&lt;li&gt;Click on "Settings" in the project's sidebar.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Configure CI/CD Variables&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the project's "Settings" page, click on "CI/CD" in the left sidebar.&lt;/li&gt;
&lt;li&gt;Scroll down to the "Secret variables" section and click "Expand."&lt;/li&gt;
&lt;li&gt;Here, you can add and manage secret variables specific to your project. These variables are securely encrypted and can be accessed by CI/CD jobs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Add Secret Variables&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click on the "Add variable" button.&lt;/li&gt;
&lt;li&gt;Fill in the variable details:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key&lt;/strong&gt;: This is the name of the secret variable, e.g., &lt;strong&gt;&lt;code&gt;API_KEY&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value&lt;/strong&gt;: Enter the actual secret value, such as an API key or password.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add secret variables for both &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; these would be available in the environment variables of your pipeline run and are automatically passed to the terraform.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Protect Secret Variables&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;GitLab provides an option to protect secret variables. When a variable is protected, it cannot be accessed by unprotected branches or tags. This is useful for ensuring that sensitive secrets are only available in authorized environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Accessing Secret Variables in CI/CD Jobs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now you can securely utilize the secret variables in your pipeline. Update the variables section of your YAML file as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;TF_VAR_AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;TF_VAR_AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These variables are used to pass the AWS access key and secret access key to the Terraform commands. They are denoted by the &lt;code&gt;$&lt;/code&gt; symbol.&lt;/p&gt;

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

&lt;p&gt;The implementation of Infrastructure Continuous Integration and Continuous Deployment with GitLab for Terraform equips DevOps engineers with the means to streamline their workflows, ensure infrastructure reliability, and expedite the delivery of new features and updates. By embracing IAC principles and leveraging GitLab's CI/CD capabilities, you are well-prepared to meet the demands of modern infrastructure management.&lt;/p&gt;

&lt;p&gt;Begin by establishing your GitLab project, defining CI/CD pipelines, and integrating Terraform. As you gain experience, delve into advanced concepts to further enhance your journey in infrastructure automation. The synergy between GitLab and Terraform provides a formidable toolkit for achieving excellence in Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://docs.gitlab.com/ee/ci/"&gt;GitLab CI/CD Documentation&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://learn.hashicorp.com/tutorials/terraform/infrastructure-as-code?in=terraform/getting-started"&gt;Terraform Documentation&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://gitlab.com/gitlab-examples/terraform"&gt;GitLab Terraform Example Projects&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>terraform</category>
      <category>cicd</category>
      <category>gitlab</category>
      <category>advanced</category>
    </item>
    <item>
      <title>A Comprehensive Guide on Migrating OCI Terraform State from Local to Remote Storage</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Thu, 14 Sep 2023 23:39:12 +0000</pubDate>
      <link>https://dev.to/robogeek95/a-comprehensive-guide-on-migrating-oci-terraform-state-from-local-to-remote-storage-1nj0</link>
      <guid>https://dev.to/robogeek95/a-comprehensive-guide-on-migrating-oci-terraform-state-from-local-to-remote-storage-1nj0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Infrastructure as Code (IaC) has revolutionized how organizations manage their cloud resources. Terraform, a popular IaC tool, enables developers and operations teams to define and provision infrastructure using declarative configuration files. When working with Oracle Cloud Infrastructure (OCI) and Terraform, managing the state file is a crucial aspect of your infrastructure workflow.&lt;/p&gt;

&lt;p&gt;In this guide, we will explore the process of migrating your Terraform state from a local file system to an OCI Object Storage bucket. This migration enhances the security and scalability of your state management and allows for better collaboration among team members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Migrate Terraform State to an Object Storage?
&lt;/h2&gt;

&lt;p&gt;To begin with, it is important to thoroughly understand the differences between storing your Terraform state on a local file system versus on OCI Object Storage. While a local file system may seem convenient at first, it can lead to potential data loss, security breaches, and difficulty in scaling your infrastructure. Object Storage, on the other hand, offers a highly secure and scalable solution to store your Terraform state, ensuring that your data is always accessible and protected. &lt;/p&gt;

&lt;p&gt;Migrating Terraform state from your local file system to an Object Storage generally offers several compelling benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security&lt;/strong&gt;: Storing your state in OCI Object Storage ensures that it's stored in a secure and redundant manner. You can take advantage of OCI's robust security features, including encryption and IAM (Identity and Access Management) policies, to control access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Collaboration&lt;/strong&gt;: Object Storage enables seamless collaboration among team members by providing a centralized location for storing and sharing Terraform state. Multiple team members can access and modify the state file without the risk of conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability and Reliability&lt;/strong&gt;: OCI Object Storage is designed to scale automatically to accommodate your growing infrastructure. It offers high availability and durability, ensuring your Terraform state is always accessible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning and Auditing&lt;/strong&gt;: Object Storage can be configured to enable versioning, allowing you to track changes to your Terraform state over time. This feature is invaluable for auditing and troubleshooting.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Before you begin the migration process, ensure you have the following prerequisites in place:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;OCI Account&lt;/strong&gt;: You should have an active OCI account with the necessary permissions to create and manage Object Storage buckets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Installed&lt;/strong&gt;: Ensure that Terraform is installed on your local machine. You can download it from the official Terraform website (&lt;a href="https://www.terraform.io/downloads.html"&gt;https://www.terraform.io/downloads.html&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCI CLI&lt;/strong&gt;: Install the Oracle Cloud Infrastructure Command Line Interface (OCI CLI) and configure it with the necessary credentials. You can follow the official documentation for installation instructions (&lt;a href="https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm"&gt;https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prepare for the Migration Process
&lt;/h2&gt;

&lt;p&gt;The migration process involves creating an Object Storage bucket, updating the Terraform configuration to specify the new backend configuration for storing the state in OCI Object Storage, initializing Terraform with the new backend configuration and migrating the existing local Terraform state to OCI Object Storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an Object Storage Bucket
&lt;/h3&gt;

&lt;p&gt;The first step is to identify your namespace. In OCI, a namespace is a unique identifier that is used to create a unique name for each object in Object Storage. The namespace is automatically generated when you sign up for an OCI account and cannot be changed. &lt;/p&gt;

&lt;p&gt;Retrieve your OCI Object Storage namespace using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;namespace &lt;span class="o"&gt;=&lt;/span&gt; oci os ns get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a  string that represents your namespace and set it as an environment variable in your CLI for easy reference in subsequent commands.&lt;/p&gt;

&lt;p&gt;Next, create an Object Storage bucket in your OCI console, ensuring you choose a unique and meaningful name for your bucket. You can also create the bucket using the OCI CLI with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oci os bucket create &lt;span class="nt"&gt;--name&lt;/span&gt; &amp;lt;bucket-name&amp;gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; &lt;span class="nv"&gt;$namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;"bucket-name"&lt;/code&gt; with the actual bucket name and the namespace would be the one set from the previous command.&lt;/p&gt;

&lt;p&gt;Use the following commands to migrate your existing local Terraform state to OCI Object Storage, including the additional commands for setting up authentication:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Create a Customer Secret Key&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The customer secret key is a key generated for your user in OCI that you can use for authentication when interacting with OCI Object Storage. It consists of an access key ID and secret access key that you can use to authenticate and connect with your Object Storage bucket.&lt;/p&gt;

&lt;p&gt;First export your email address as a variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your_email&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command exports your console email address as a variable in the Command Line Interface (CLI) environment. It sets the variable &lt;strong&gt;&lt;code&gt;email&lt;/code&gt;&lt;/strong&gt; to your email address.&lt;/p&gt;

&lt;p&gt;Verify the Exported Email:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the OCI CLI command to Query Your User Data from OCI IAM service to retrieve user data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oci iam user list &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"data[?&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;=='&lt;/span&gt;&lt;span class="nv"&gt;$USERNAME&lt;/span&gt;&lt;span class="s2"&gt;']"&lt;/span&gt;.&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,id:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;-query&lt;/code&gt;&lt;/strong&gt; parameter filters the data to find a user with a name matching the value in the &lt;code&gt;$USERNAME&lt;/code&gt; variable and the resulting table includes the user's name and OCI User ID (OCIUID).&lt;/p&gt;

&lt;p&gt;Export the Returned OCIUID as a Variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OCIUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;YOUR_OCIUID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command exports your OCI User ID (OCIUID) as a variable in the CLI environment. Replace the provided value with the OCIUID obtained from the previous command.&lt;/p&gt;

&lt;p&gt;Finally, we can now create a customer secret key for your user using the OCI CLI. Create a customer secret key using the command below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oci iam customer-secret-key create &lt;span class="nt"&gt;--user-id&lt;/span&gt; &lt;span class="nv"&gt;$OCIUID&lt;/span&gt; &lt;span class="nt"&gt;--display-name&lt;/span&gt; &lt;span class="s1"&gt;'key-tf-test'&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"data"&lt;/span&gt;.&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"AWS_ACCESS_KEY_ID:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,AWS_SECRET_ACCESS_KEY:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;key&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a customer secret key for your user and display it in a tabular format. The &lt;strong&gt;&lt;code&gt;-user-id&lt;/code&gt;&lt;/strong&gt; parameter specifies your OCI User ID, and the &lt;strong&gt;&lt;code&gt;-display-name&lt;/code&gt;&lt;/strong&gt; parameter sets a name for the secret key. The &lt;strong&gt;&lt;code&gt;-query&lt;/code&gt;&lt;/strong&gt; parameter extracts the &lt;strong&gt;&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;&lt;/strong&gt; fields from the command's output and formats the output as a table.&lt;/p&gt;

&lt;p&gt;Note down the result, we are going to use this for authentication when interacting with OCI blob storage.&lt;/p&gt;

&lt;p&gt;Now, export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;YOUR_AWS_ACCESS_KEY_ID&amp;gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;YOUR_AWS_SECRET_ACCESS_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands export the &lt;strong&gt;&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;&lt;/strong&gt; obtained from the previous OCI CLI command as environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update Terraform Configuration
&lt;/h2&gt;

&lt;p&gt;In order to establish the connection between your Terraform workspace and the remote state stored in Object Storage, Terraform needs to be aware of the new backend configuration, which directs it to use OCI Object Storage for storing and managing the state of your infrastructure.&lt;/p&gt;

&lt;p&gt;Inside your Terraform configuration file that defines the provider, typically a provider.tf file, you would locate or add a &lt;strong&gt;&lt;code&gt;terraform&lt;/code&gt;&lt;/strong&gt; block. This block is used to configure various aspects of Terraform's behaviour, including the backend configuration for storing the state. Here's a basic example of how you can configure the block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" {
    bucket         = "bucket-name"
    key            = "terraform.tfstate"
    region         = "your-region"
        endpoint       = "https://&amp;lt;bucket-name&amp;gt;.compat.objectstorage.&amp;lt;region&amp;gt;.oraclecloud.com"

    skip_region_validation      = true
    skip_credentials_validation = true
    skip_metadata_api_check     = true
    force_path_style            = true
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down what each of these settings means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;backend&lt;/code&gt;&lt;/strong&gt;: Specifies the backend type. In this case, we are using &lt;strong&gt;&lt;code&gt;"s3"&lt;/code&gt;&lt;/strong&gt; because OCI Object Storage is S3-compatible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bucket&lt;/code&gt;&lt;/strong&gt;: The name of the OCI Object Storage bucket where your Terraform state will be stored. Replace &lt;strong&gt;&lt;code&gt;"-bucket-name"&lt;/code&gt;&lt;/strong&gt; with the actual name of the bucket you created earlier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;key&lt;/code&gt;&lt;/strong&gt;: The name of the state file within the bucket. It's typically named &lt;strong&gt;&lt;code&gt;"terraform.tfstate"&lt;/code&gt;&lt;/strong&gt; but can be customized if needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;region&lt;/code&gt;&lt;/strong&gt;: The OCI region where your Object Storage bucket is located. Replace &lt;strong&gt;&lt;code&gt;"your-region"&lt;/code&gt;&lt;/strong&gt; with the appropriate region identifier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;skip_region_validation&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;skip_credentials_validation&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;skip_metadata_api_check&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;code&gt;force_path_style&lt;/code&gt;&lt;/strong&gt;: These settings control various validation and behaviour options for the backend configuration. Here's what each setting does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;skip_region_validation&lt;/code&gt;&lt;/strong&gt;: Skips validation of the region name, which is useful when using custom endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;skip_credentials_validation&lt;/code&gt;&lt;/strong&gt;: Skips validation of credentials. Be cautious when using this option, as it can potentially lead to authentication issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;skip_metadata_api_check&lt;/code&gt;&lt;/strong&gt;: Skips checking the metadata API for credentials. This can be useful when running Terraform in environments where the metadata API is not available, such as some development environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;force_path_style&lt;/code&gt;&lt;/strong&gt;: Forces the use of path-style URLs when interacting with the Object Storage service. This is commonly used when working with S3-compatible storage services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migrate Existing State
&lt;/h2&gt;

&lt;p&gt;Now that the configuration has been completed, we can proceed to migrate the state data. This process involves transferring the data from the current system to the new one in a secure and efficient manner. It is important to ensure that all data is accurately transferred and that there are no discrepancies or errors during the migration process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialize Terraform
&lt;/h3&gt;

&lt;p&gt;Start by running the following command to initialize Terraform with the new backend configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
Initializing modules...

Initializing the backend...
Do you want to copy existing state to the new backend?
  Pre-existing state was found &lt;span class="k"&gt;while &lt;/span&gt;migrating the previous &lt;span class="s2"&gt;"local"&lt;/span&gt; backend to the
  newly configured &lt;span class="s2"&gt;"s3"&lt;/span&gt; backend. No existing state was found &lt;span class="k"&gt;in &lt;/span&gt;the newly
  configured &lt;span class="s2"&gt;"s3"&lt;/span&gt; backend. Do you want to copy this state to the new &lt;span class="s2"&gt;"s3"&lt;/span&gt;
  backend? Enter &lt;span class="s2"&gt;"yes"&lt;/span&gt; to copy and &lt;span class="s2"&gt;"no"&lt;/span&gt; to start with an empty state.

  Enter a value:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will prompt you to migrate your state. Confirm the migration by entering “yes” to proceed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Successfully&lt;/span&gt; &lt;span class="nx"&gt;configured&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;automatically&lt;/span&gt;
&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="nx"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Initializing&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Reusing&lt;/span&gt; &lt;span class="nx"&gt;previous&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;hashicorp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;oci&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;dependency&lt;/span&gt; &lt;span class="nx"&gt;lock&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Using&lt;/span&gt; &lt;span class="nx"&gt;previously&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;installed&lt;/span&gt; &lt;span class="nx"&gt;hashicorp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;oci&lt;/span&gt; &lt;span class="nx"&gt;v5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;

&lt;span class="err"&gt;╷&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Additional&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="nx"&gt;information&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; 
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;remote&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt; &lt;span class="nx"&gt;returned&lt;/span&gt; &lt;span class="nx"&gt;warnings&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;hashicorp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;oci&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;For&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="mf"&gt;0.13&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;greater&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="nx"&gt;has&lt;/span&gt; &lt;span class="nx"&gt;moved&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;oracle&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;oci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Please&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;required_providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="err"&gt;╵&lt;/span&gt;

&lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="nx"&gt;has&lt;/span&gt; &lt;span class="nx"&gt;been&lt;/span&gt; &lt;span class="nx"&gt;successfully&lt;/span&gt; &lt;span class="nx"&gt;initialized&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

&lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;may&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="nx"&gt;begin&lt;/span&gt; &lt;span class="nx"&gt;working&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;Terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Try&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;terraform plan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt;
&lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;required&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;
&lt;span class="nx"&gt;should&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="nx"&gt;work&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;ever&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt; &lt;span class="nx"&gt;modules&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;Terraform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;rerun&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;reinitialize&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;working&lt;/span&gt; &lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt;
&lt;span class="nx"&gt;commands&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;detect&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;remind&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;so&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;necessary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Using the -migrate-state option in terraform init command can perform automatic migration of the state. This is useful if you already a different backend configured for your state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify and Test
&lt;/h3&gt;

&lt;p&gt;After the migration, you can verify that the state is now stored in OCI Object Storage by running &lt;code&gt;terraform state list&lt;/code&gt; or finding the object in the blob storage in the console. Remember to Test your infrastructure deployments to ensure that everything is functioning as expected.&lt;/p&gt;

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

&lt;p&gt;Migrating your Terraform state from a local file system to OCI Object Storage is a strategic move that enhances security, collaboration, scalability, and reliability in your infrastructure management process. By following the steps outlined in this guide, you can seamlessly transition to a more robust state management solution and take full advantage of Oracle Cloud Infrastructure's capabilities. Happy Terraforming!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>oci</category>
      <category>advanced</category>
    </item>
    <item>
      <title>VRA API Authentication: Ensuring Secure Access and Understanding Authentication Methods</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Mon, 11 Sep 2023 00:52:00 +0000</pubDate>
      <link>https://dev.to/robogeek95/vra-api-authentication-ensuring-secure-access-and-understanding-authentication-methods-2ach</link>
      <guid>https://dev.to/robogeek95/vra-api-authentication-ensuring-secure-access-and-understanding-authentication-methods-2ach</guid>
      <description>&lt;p&gt;Using APIs is an effective way to programmatically access vRealize Automation (vRA). However, secure access to your API is essential when managing and automating your infrastructure. This article explores VRA API authentication using API tokens, a secure and efficient way to programmatically access vRA resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding vRealize Automation
&lt;/h2&gt;

&lt;p&gt;VMware vRealize Automation is a robust cloud management platform that empowers orga nizations to automate and orchestrate the provisioning and management of various cloud resources, including virtual machines and containers. This platform aids businesses in delivering IT services rapidly, efficiently, and securely. A key feature of vRealize Automation is its robust API infrastructure, which enables developers to seamlessly integrate vRA into their applications and workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Concepts of VRA API Authentication
&lt;/h2&gt;

&lt;p&gt;Before delving into the authentication methods, it's essential to establish some fundamental concepts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Authentication&lt;/strong&gt;: Authentication is the process of confirming the identity of a user or application. It typically involves the use of credentials such as usernames and passwords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Authorization&lt;/strong&gt;: After successful authentication, authorization determines what actions a user or application is allowed to perform within the VRA environment. It defines access permissions and rights.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Tokens&lt;/strong&gt;: Tokens serve as proof of authentication in API requests. Once a user or application is authenticated, they receive a token that must be included in subsequent API requests to prove their identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  VRA API Authentication Methods
&lt;/h2&gt;

&lt;p&gt;vRealize Automation provides various authentication methods to cater to diverse use cases and security requirements. The choice of method depends on your specific needs and existing infrastructure. Here are some of the most commonly used VRA API authentication methods:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Basic Authentication&lt;/strong&gt;: This is the simplest form of authentication, involving a username and password. While easy to implement, it is generally considered less secure, as credentials are transmitted in plain text. It's recommended to use this method over secure channels like HTTPS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. API Tokens&lt;/strong&gt;: API tokens are a more secure alternative to basic authentication. Users generate tokens with limited access rights and use them to authenticate API requests. Tokens can be revoked or refreshed as needed, enhancing security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. OAuth 2.0&lt;/strong&gt;: OAuth 2.0 is a widely adopted authentication framework that provides a standardized way to grant limited access to resources without exposing credentials. VRA supports OAuth 2.0, making it a robust choice for integration with third-party applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. SSO Integration&lt;/strong&gt;: VRA can be integrated with Single Sign-On (SSO) systems like VMware Identity Manager or external identity providers. This streamlines authentication processes and centralizes user management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using API Tokens for Authentication
&lt;/h3&gt;

&lt;p&gt;Now, let's focus on API tokens, a secure and versatile authentication method. But why should you choose API tokens for authentication in the first place?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Security&lt;/strong&gt;: API tokens are typically long, randomly generated strings that are difficult to guess. They do not contain sensitive information like passwords, making them more secure for authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Scalability&lt;/strong&gt;: API tokens can be easily generated and revoked as needed. This makes them ideal for managing access to your vRA resources, especially in dynamic environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Expiration&lt;/strong&gt;: Tokens can have expiration dates, reducing the risk of unauthorized access if a token is leaked or compromised.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Granular Access Control&lt;/strong&gt;: With API tokens, you can control the level of access granted to a user. For example, you can create tokens with read-only access or restrict access to specific resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Obtain an API Token for Authentication
&lt;/h3&gt;

&lt;p&gt;To interact with the vRA API using API tokens, follow these steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Export Variables&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Start by exporting the values on the command line, including the vRA hostname, your username, and password. This makes it easier to reference these values in the other steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service_url='https://&amp;lt;vRA_HOST&amp;gt;'
username='&amp;lt;your_username&amp;gt;'
password='&amp;lt;your_password&amp;gt;'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Request an API Token&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;VRA API authentication uses an API token to authenticate the user or client and request an access token. The API token is obtained through an initial authentication process where credentials are provided, and it does not grant access to resources directly. Instead, it is used to acquire an access token, which determines the scope of access. The API token may have a longer lifetime than the access token but is still limited and used to request access tokens periodically.&lt;/p&gt;

&lt;p&gt;Make a request to the Identity Service API to obtain the API token. The token will be attached to your request headers for authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api_token=`curl -X POST \
 "$service_url/csp/gateway/am/api/login?access_token" \
 -H 'Content-Type: application/json' \
 -d '{
 "username": "'"$username"'",
 "password": "'"$password"'"
}' | jq -r .refresh_token`

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Retrieve the Access Token&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that you have the API token, make another request to get and assign the access token. The access token is the JSON web token that grants access to specific vRA resources and defines the scope of actions the client can perform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;access_token=`curl -X POST \
 "$service_url/iaas/api/login" \
 -H 'Content-Type: application/json' \
 -s \
 -d '{
 "refreshToken": "'"$api_token"'"
}' | jq -r .token`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing Your Access
&lt;/h3&gt;

&lt;p&gt;To ensure that you have successfully authenticated and can interact with the VRA API, you can perform actions like listing all cloud accounts or workflows. Here's an example using the access token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X GET $url/iaas/api/cloud-accounts?apiVersion=$api_version -H 'Content-Type: application/json' -H "Authorization: Bearer $access_token" | jq "."

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

&lt;/div&gt;



&lt;p&gt;Similarly, you can list workflows or perform other actions based on your requirements.&lt;/p&gt;

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

&lt;p&gt;vRA API authentication is a critical component of securing your infrastructure management and automation tasks. By understanding the available authentication methods and choosing the right one for your needs, such as API tokens for enhanced security and control, you can ensure the integrity and security of your vRealize Automation environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rerefences
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dokumen.tips/download/link/vrealize-automation-api-programming-guide-vrealize-to-make-api-service-calls.html"&gt;https://dokumen.tips/download/link/vrealize-automation-api-programming-guide-vrealize-to-make-api-service-calls.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vra</category>
      <category>api</category>
      <category>cli</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Back to the blogosphere (Sharing My Journey in the World of Software Engineering)</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Thu, 07 Sep 2023 02:43:43 +0000</pubDate>
      <link>https://dev.to/robogeek95/back-to-the-blogosphere-sharing-my-journey-in-the-world-of-software-engineering-53oe</link>
      <guid>https://dev.to/robogeek95/back-to-the-blogosphere-sharing-my-journey-in-the-world-of-software-engineering-53oe</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Greetings, dear readers! It's been a while since I last shared my thoughts, learnings, and discoveries with you all. Life has taken me on a whirlwind journey filled with professional commitments, career growth, and personal responsibilities. As I sit down to reconnect with you through this blog post, I can't help but feel an exhilarating rush of excitement. I'm back, and I'm more pumped than ever to dive into the world of software engineering and DevOps, sharing insightful articles that offer solutions and fresh perspectives.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Intermission
&lt;/h2&gt;

&lt;p&gt;You might be wondering why I seemingly vanished from the blogging scene. Well, life happened. New projects, challenging assignments, and career milestones demanded my attention. Balancing these commitments alongside my personal life often left me with little time to put pen to paper, or rather, fingers to keyboard. But let me assure you, during this period, my passion for learning and growing in the tech world never wavered. If anything, it grew stronger with each experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Journey
&lt;/h2&gt;

&lt;p&gt;During my time away, I delved into uncharted territories of the software engineering and DevOps landscape. I embraced new tools, languages, and methodologies, and I tackled complex challenges that pushed the boundaries of my knowledge. There were moments of frustration and triumph, but each step further fueled my desire to share these experiences with you. The journey was a testament to the fact that learning never stops, even when our lives get busier.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Return
&lt;/h2&gt;

&lt;p&gt;And now, here I am, back in the blogosphere, ready to pick up where we left off. The excitement of sharing my learnings, the joy of discovering innovative solutions, and the sense of community we've built together beckoned me back. With a renewed sense of purpose and a commitment to delivering value, I am eager to embark on this next chapter of our journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Expect
&lt;/h2&gt;

&lt;p&gt;In the coming weeks and months, expect a variety of articles that delve into the heart of software engineering and DevOps. I'll be sharing insights into the latest trends, demystifying complex concepts, and providing practical solutions to the challenges we encounter in our everyday tech lives. From coding tips that streamline your workflow to DevOps strategies that enhance collaboration and efficiency, we'll cover it all.&lt;/p&gt;

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

&lt;p&gt;The tech community we've built is a source of inspiration aiding contributions and learning together and I am genuinely thrilled to be a part of it.&lt;/p&gt;

&lt;p&gt;Thank you for joining me on this journey. Let's dive back into the world of software engineering and DevOps with vigour, curiosity, and a commitment to continuous growth. Stay tuned for the upcoming articles – I promise they'll be worth the wait.&lt;/p&gt;

&lt;p&gt;I'm Azeez Lukman, a software engineer with a deep passion for unravelling the complexities of code and systems. You can always reach out to me at &lt;strong&gt;&lt;a href="https:///"&gt;@robogeek95&lt;/a&gt;&lt;/strong&gt; to connect, share your thoughts, or simply geek out about all things tech.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>bloging</category>
      <category>tech</category>
      <category>devops</category>
    </item>
    <item>
      <title>Creating a Chrooted Environment</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Tue, 27 Sep 2022 10:01:49 +0000</pubDate>
      <link>https://dev.to/robogeek95/creating-a-chrooted-environment-1gkd</link>
      <guid>https://dev.to/robogeek95/creating-a-chrooted-environment-1gkd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Every process in Linux has a base working directory called the root directory. The root directory designated by the slash sign is where every other directory in your system begins. Although you cannot go above this directory, you can change it.&lt;/p&gt;

&lt;p&gt;The chroot command changes the root directory for any currently running process as well as its child processes. This article will walk you through the process of creating a chrooted environment, adding access to Linux commands, along with including shared libraries for these commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is chroot
&lt;/h2&gt;

&lt;p&gt;So what does it mean to change the root directory? According to the official Debian documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A &lt;/em&gt;&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Chroot"&gt;chroot&lt;/a&gt;&lt;/em&gt;&lt;em&gt; is an operation that changes the apparent root directory for the current running process and their children.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hmm, maybe that isn’t clear enough still… When you change the root directory, commands run from the new environment are locked down to that environment, they are not able to access any files or even commands outside of that directory. When you use the chroot command, you get this completely isolated environment also referred to as a chroot jail.&lt;/p&gt;

&lt;p&gt;The “*chroot” command can be very useful in situations when you need t*o create a test environment, or you need to recover the system or password, or even when you need to reinstall the bootloader. There are several other reasons you might want to create a chrooted environment and it’s completely safe to try it out for the sake of learning something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup jailed root environment
&lt;/h2&gt;

&lt;p&gt;Let’s walk through the process of creating a chrooted environment, and create a new user for that environment.&lt;/p&gt;

&lt;p&gt;Performing a chroot requires that you are a super user. So you need to first become the root user by running the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;sudo&lt;/span&gt; &lt;span class="nx"&gt;su&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the directory we would chroot to within the /home directory named &lt;code&gt;/home/bailey&lt;/code&gt;. Although you can chroot into any directory.&lt;/p&gt;

&lt;p&gt;Create a directory for &lt;em&gt;bailey&lt;/em&gt; with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /home/bailey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a new user
&lt;/h3&gt;

&lt;p&gt;Create a new user for your environment named bailey.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;useradd bailey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provision commands to run
&lt;/h3&gt;

&lt;p&gt;When we chroot into a directory, we are in a completely isolated environment, you need to provide everything you need afresh including the files and commands so we are limited to the commands and files within this chroot jail directory, in order to enable us to run some commands in a jailed directory we need to make them available there either by installing the commands to that directory or by moving them.&lt;/p&gt;

&lt;p&gt;Start by creating the bin and lib64 directories in /home/bailey then move in the needed commands into these directories.&lt;/p&gt;

&lt;p&gt;Run the command below to Create two new directories; bin, and lib64, within the /home/bailey directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /home/elba/&lt;span class="o"&gt;{&lt;/span&gt;bin,lib64&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need bash, ls, and cat commands&lt;/p&gt;

&lt;p&gt;Start by copying /bin/bash on the local computer into the chroot jail at /home/bailey/bin/bash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /bin/bash /home/bailey/bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then copy /bin/ls into /home/bailey/bin/ls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /bin/ls /home/bailey/bin/ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, copy /bin/cat into /home/bailey/bin/cat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /bin/cat /home/bailey/bin/cat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to find and Copy the libraries needed for bash, ls, and cat over to /home/bailey/lib64&lt;/p&gt;

&lt;p&gt;Find the required libraries using ldd:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ldd /bin/bash /bin/ls /bin/cat 
&lt;span class="nb"&gt;cp&lt;/span&gt; /lib64/libtinfo.so.5 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libdl.so.2 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libselinux.so.1 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/librt.so.1 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libcap.so.2 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libacl.so.1 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libc.so.6 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libpthread.so.0 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libattr.so.1 &lt;span class="se"&gt;\ &lt;/span&gt;/lib64/libpcre.so.1 /home/elba/lib64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have the commands in place, but there’s one more thing to do before creating the chrooted environment. &lt;/p&gt;

&lt;p&gt;Create a text file with some sample text in it so we are able to run the commands against it.&lt;/p&gt;

&lt;p&gt;Use nano to create the hello.txt file in the /home/bailey and add some text to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano /home/bailey/hello.txt

&lt;span class="c"&gt;# Write the following in the file:&lt;/span&gt;
Welcome to &lt;span class="nb"&gt;chroot &lt;/span&gt;jail

&lt;span class="c"&gt;# Write out and close the file:&lt;/span&gt;
^O &amp;amp; ^X
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Change the root environment
&lt;/h3&gt;

&lt;p&gt;Finally, create a chrooted environment in /home/bailey with a Bash shell using the chroot command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chroot&lt;/span&gt; /home/bailey /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This has now created a chrooted enviroment at &lt;em&gt;/home/bailey&lt;/em&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Check the commands
&lt;/h3&gt;

&lt;p&gt;Using the command pwd, confirm the present working directory and then confirm that you can use the ls command to list files in the directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd
ls&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the hello.txt file that was created previously, now confirm you can view the contents of hello.txt&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;It's really important to mention that running programs in a chrooted environment is not entirely secure as it is easy for processes to break out of this environment if they are run with root privileges, it cannot handle tampering by privileged users.&lt;/p&gt;

&lt;p&gt;It's advised to revoke root privileges after chrooting in order to reduce these security risks. A better option would be to enforce a real jail With other mechanisms like freeBSD jails and &lt;a href="http://en.wikipedia.org/wiki/FreeBSD_jail#Similar_technologies"&gt;more&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;You have successfully changed your root environment hereby creating a chrooted environment otherwise known as a chroot jail environment. I hope you enjoyed reading this piece as much as i enjoyed writing it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Update existing security list ingress rules in OCI with the python SDK</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Fri, 19 Aug 2022 22:31:15 +0000</pubDate>
      <link>https://dev.to/robogeek95/update-existing-security-list-ingress-rules-in-oci-with-the-python-sdk-20l7</link>
      <guid>https://dev.to/robogeek95/update-existing-security-list-ingress-rules-in-oci-with-the-python-sdk-20l7</guid>
      <description>&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Some knowledge about python programming language&lt;/li&gt;
&lt;li&gt;OCI SDK for python. please check &lt;a href="https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/pythonsdk.htm#SDK_for_Python"&gt;here&lt;/a&gt; to install it, if you do not have it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Feel free to follow along with from &lt;a href="http://github.com"&gt;this&lt;/a&gt; GitHub repository&lt;/p&gt;

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

&lt;p&gt;Security lists are components of your VCN that are responsible for allowing traffic in and out of the VCN, they act like firewalls and are applied to the VNICs of your subnets or VCN. You specify the types of traffic allowed in and out with ingress and egress rules respectively.&lt;/p&gt;

&lt;p&gt;As your VCN grows in complexity, there could be a need to update the security rules of your security list, this is fairly easy from the console but comes with a gotcha when using the API or SDK as stated in the &lt;a href="https://www.notion.so/Quotation-for-B2B-B2P-Logistics-Delivery-management-Application-4f6a2788b87e48548cf67de9b185b1a6"&gt;documentation&lt;/a&gt; that &lt;code&gt;egressSecurityRules&lt;/code&gt;or &lt;code&gt;ingressSecurityRules&lt;/code&gt; objects you provide replace the entire existing objects. This means you risk replacing the entire rules in an existing security list when you are making an update to an existing security list.&lt;/p&gt;

&lt;p&gt;In this article, you would learn how to use the python SDK to update the rules of an existing security list in OCI without losing the existing rules of course.&lt;/p&gt;

&lt;h3&gt;
  
  
  Import oracle SDK
&lt;/h3&gt;

&lt;p&gt;Let’s get started by preparing our environment and ensuring we have all that’s required to follow along this article.&lt;/p&gt;

&lt;p&gt;The oracle python SDK provides the tools you need to interact with the Oracle Cloud Infrastructure using python, so let’s import the SDK module on the command line.&lt;/p&gt;

&lt;p&gt;Run the command below in your terminal to install the oracle SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;oci&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create the file to write the python script using the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;oci-ingress-sl-update.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would create a file named &lt;code&gt;[oci-ingress-sl-update.py](http://oci-ingress-sl-update.py)&lt;/code&gt;, feel free to update the file name.&lt;/p&gt;

&lt;p&gt;Next, open the file you created in your favourite code editor, and the code below to import the oci SDK package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import oci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Authentication
&lt;/h2&gt;

&lt;p&gt;You need to grant access to your tenancy, i would be authenticating using the instance principal, you can use other authentication methods as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;config &lt;span class="o"&gt;=&lt;/span&gt; oci.config.from_file&lt;span class="o"&gt;()&lt;/span&gt;
identity_client &lt;span class="o"&gt;=&lt;/span&gt; oci.identity.IdentityClient&lt;span class="o"&gt;(&lt;/span&gt;config&lt;span class="o"&gt;)&lt;/span&gt;
core_client &lt;span class="o"&gt;=&lt;/span&gt; oci.core.VirtualNetworkClient&lt;span class="o"&gt;(&lt;/span&gt;config&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gets the credentials from the identity file and store in config, &lt;code&gt;oci.config.from_file()&lt;/code&gt; takes as arguments, one is for the config file location and the other tells it it to use the &lt;code&gt;default&lt;/code&gt; config profile. passing empty arguments falls back to default values with the config file at &lt;code&gt;~/.oci/identity_file&lt;/code&gt; and the profile would be &lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We then use the config to authenticate the &lt;code&gt;identity_client&lt;/code&gt; as well as the &lt;code&gt;core_client&lt;/code&gt; which we would be using in a minute.&lt;/p&gt;

&lt;p&gt;Next, we define the constants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;network_compartment_name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"network_compartment"&lt;/span&gt;
vcn_cidr_range &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.104.0.0/16"&lt;/span&gt;
vcn_subnet_cidr_range &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.103.225.0/28"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;network_compartment_name&lt;/code&gt; : The compartment that holds your network resources&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vcn_cidr_range&lt;/code&gt;: The virtual network’s CIDR range&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vcn_subnet_cidr_range&lt;/code&gt;: The Subnet’s CIDR range&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get compartment data
&lt;/h2&gt;

&lt;p&gt;We would be making use of the compartment id later on. In order to get this, we filter through the list of all compartments and match the compartment that matches the network compartment declared earlier.&lt;/p&gt;

&lt;p&gt;Add the following code to get your compartment  id:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;list_compartments_response &lt;span class="o"&gt;=&lt;/span&gt; identity_client.list_compartments&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;compartment_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config[&lt;span class="s1"&gt;'tenancy'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
    &lt;span class="nv"&gt;lifecycle_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ACTIVE"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in &lt;/span&gt;range&lt;span class="o"&gt;(&lt;/span&gt;len&lt;span class="o"&gt;(&lt;/span&gt;list_compartments_response.data&lt;span class="o"&gt;))&lt;/span&gt;:
   &lt;span class="k"&gt;if &lt;/span&gt;list_compartments_response.data[i].name &lt;span class="o"&gt;==&lt;/span&gt; network_compartment_name:
     network_compartment_id &lt;span class="o"&gt;=&lt;/span&gt; list_compartments_response.data[i].id
     &lt;span class="nb"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have the compartment id &lt;code&gt;network_compartment_id&lt;/code&gt;, the next step is to identify the VCN we would be working with within the compartment.&lt;/p&gt;

&lt;p&gt;Add the following code to get the VCN data below your script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;list_vcns_response &lt;span class="o"&gt;=&lt;/span&gt; core_client.list_vcns&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;compartment_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;network_compartment_id&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;vcn &lt;span class="k"&gt;in &lt;/span&gt;range&lt;span class="o"&gt;(&lt;/span&gt;len&lt;span class="o"&gt;(&lt;/span&gt;list_vcns_response.data&lt;span class="o"&gt;))&lt;/span&gt;:
    &lt;span class="k"&gt;if &lt;/span&gt;list_vcns_response.data[vcn].cidr_block &lt;span class="o"&gt;==&lt;/span&gt; vcn_cidr_range[0]:
        vcn_id &lt;span class="o"&gt;=&lt;/span&gt; list_vcns_response.data[vcn].id
        vcn_name &lt;span class="o"&gt;=&lt;/span&gt; list_vcns_response.data[vcn].display_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we get the VCN name and id by filtering through the list of VCNs with the CIDR range declared earlier. You can also filter using the VCN name just like we did for the compartment, but i would be doing this way.&lt;/p&gt;

&lt;p&gt;Now we have the compartment id and the VCN id, we use those details to get the VCNs security list. You would also need to specify the name of the security list since it’s possible to have multiple security lists in a VCN.&lt;/p&gt;

&lt;p&gt;Go ahead and update your script with the following code to get your security list details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;list_security_lists_response &lt;span class="o"&gt;=&lt;/span&gt; core_client.list_security_lists&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;compartment_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;network_compartment_id,
    &lt;span class="nv"&gt;vcn_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vcn_id,
    &lt;span class="nv"&gt;display_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sl_name,
 &lt;span class="o"&gt;)&lt;/span&gt;

vcn_sl_id &lt;span class="o"&gt;=&lt;/span&gt; list_security_lists_response.data[0].id

get_security_list_response &lt;span class="o"&gt;=&lt;/span&gt; core_client.get_security_list&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;security_list_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vcn_sl_id&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# get the current security list data&lt;/span&gt;
&lt;span class="nv"&gt;current_vcn_sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json.loads&lt;span class="o"&gt;(&lt;/span&gt;str&lt;span class="o"&gt;(&lt;/span&gt;get_security_list_response.data.ingress_security_rules&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We simply get the first security list that matches the display name we specified to list_security_lists. Using the id we get the ingress rules for the security list and store it as a json object in &lt;code&gt;current_vcn_sl&lt;/code&gt;. The reason we’re getting the existing rules is so that we are able to include the existing rules along with the updates and not replace them.&lt;/p&gt;

&lt;p&gt;💡 Remember, the idea is to update the ingress security rules&lt;/p&gt;

&lt;p&gt;It would also be nice to keep track of what the security rules are before making the update, the last thing you want to do is mess up the entire control plane without being able to revert the changes.&lt;/p&gt;

&lt;p&gt;The following code would write the security rules to a file named &lt;code&gt;vcn_ingress_list.json&lt;/code&gt; file. Again, feel free to change the file name to whatever suits your use case. The file would be available on the same directory as your script file as soon as you run the script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;with open&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'vcn_ingress_list.json'&lt;/span&gt;, &lt;span class="s2"&gt;"w"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; as f:
   json.dump&lt;span class="o"&gt;(&lt;/span&gt;current_vcn_sl, f, &lt;span class="nv"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;False, &lt;span class="nv"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the security list rules
&lt;/h2&gt;

&lt;p&gt;We have declared all the data we need and we’re ready to start effecting the updates.&lt;/p&gt;

&lt;p&gt;The first thing you want to do is to declare the ingress security rules you want to update as a python object.  i only have two rules to update to the VCN’s ingress security rules, these would tcp and imp connections on the VCN from the subnet. &lt;/p&gt;

&lt;p&gt;Update your file with the following code, replacing the rules with yours. You can create another file to hold the rules if you have a lot more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;sl_update_rules&lt;/span&gt;&lt;span class="o"&gt;=[{&lt;/span&gt;
        &lt;span class="s1"&gt;'description'&lt;/span&gt;: &lt;span class="s1"&gt;'lcm_scan subnet cidr'&lt;/span&gt;,
        &lt;span class="s1"&gt;'source'&lt;/span&gt;: vcn_subnet_cidr_range,
        &lt;span class="s1"&gt;'source_type'&lt;/span&gt;: &lt;span class="s1"&gt;'CIDR_BLOCK'&lt;/span&gt;,
        &lt;span class="s1"&gt;'icmp_options'&lt;/span&gt;: None,
                &lt;span class="s1"&gt;'tcp_options'&lt;/span&gt;: None,
        &lt;span class="s1"&gt;'is_stateless'&lt;/span&gt;: False,
        &lt;span class="s1"&gt;'protocol'&lt;/span&gt;: &lt;span class="s1"&gt;'6'&lt;/span&gt;,
        &lt;span class="s1"&gt;'udp_options'&lt;/span&gt;: None
      &lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'description'&lt;/span&gt;: &lt;span class="s1"&gt;'lcm_scan subnet cidr'&lt;/span&gt;,
        &lt;span class="s1"&gt;'source'&lt;/span&gt;: vcn_subnet_cidr_range,
        &lt;span class="s1"&gt;'source_type'&lt;/span&gt;: &lt;span class="s1"&gt;'CIDR_BLOCK'&lt;/span&gt;,
        &lt;span class="s1"&gt;'icmp_options'&lt;/span&gt;: None,
                &lt;span class="s1"&gt;'tcp_options'&lt;/span&gt;: None,
        &lt;span class="s1"&gt;'is_stateless'&lt;/span&gt;: False,
        &lt;span class="s1"&gt;'protocol'&lt;/span&gt;: &lt;span class="s1"&gt;'1'&lt;/span&gt;,
        &lt;span class="s1"&gt;'udp_options'&lt;/span&gt;: None
      &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;

sl_update_rules &lt;span class="o"&gt;=&lt;/span&gt; current_vcn_sl_rules + sl_update_rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we concatenate the current security rules with the update, that way we include the existing rules with the rules to deploy.&lt;/p&gt;

&lt;p&gt;We also write out the new security list rules in another file named &lt;code&gt;sl_update_rules.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# write out the new security list data&lt;/span&gt;
with open&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sl_update_rules.json'&lt;/span&gt;, &lt;span class="s2"&gt;"w"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; as f:
   json.dump&lt;span class="o"&gt;(&lt;/span&gt;sl_update_rules, f, &lt;span class="nv"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;False, &lt;span class="nv"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API to update the security list doesn’t expect a JSON object, let’s create a function to update the rules into something the API expects using IngressSecurityRule, this function would be called for every one of the rules.&lt;/p&gt;

&lt;p&gt;Add the &lt;code&gt;makeIngressRules&lt;/code&gt; function below to your file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;def makeIngressRules&lt;span class="o"&gt;(&lt;/span&gt;t&lt;span class="o"&gt;)&lt;/span&gt;:
    oci.core.models.IngressSecurityRule&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;t[&lt;span class="s1"&gt;'source'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
        &lt;span class="nv"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;t[&lt;span class="s1"&gt;'protocol'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
        &lt;span class="nv"&gt;source_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;t[&lt;span class="s1"&gt;'source_type'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
        &lt;span class="nv"&gt;is_stateless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;False,
        &lt;span class="nv"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;t[&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update Security Rules
&lt;/h2&gt;

&lt;p&gt;Finally, we’re ready to deploy the new rules live. Update your code to reflect the method to make the call to update the security list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Updating "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;vcn_sl_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;core_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_security_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;security_list_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;vcn_sl_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;update_security_list_details&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;oci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateSecurityListDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sl_display_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ingress_security_rules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;makeIngressRules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sl_update_rules&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically, this says; hey here’s my security list id, i would like to update it’s ingress security rules to now reflect the following rules. This would then convert the JSON security rules update the ingress security rules on the control plane.&lt;/p&gt;

&lt;p&gt;Go ahead and run the scripts with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 oci-ingress-sl-update.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t forget to replace &lt;code&gt;oci-ingress-sl-update.py&lt;/code&gt; with your filename including the file path. If everything goes well, the script should now update your ingress security rules and produce two JSON files, one containing the previous rules and the other one containing both the previous rules and the updates.&lt;/p&gt;

&lt;p&gt;💡 Remember, the script for this article is available &lt;a href="http://github.com"&gt;here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Congratulations, you have learnt how to programatically update your ingress security rules without replacing the entire control plane. You can also update the egress rules using the same approach.&lt;/p&gt;

&lt;p&gt;Thanks for reading, don’t forget to like and share this article. Follow me on twitter and everywhere else &lt;a class="mentioned-user" href="https://dev.to/robogeek95"&gt;@robogeek95&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A visual giude on Quicksort algorithm</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Mon, 31 Jan 2022 07:52:49 +0000</pubDate>
      <link>https://dev.to/robogeek95/a-visual-giude-on-quicksort-algorithm-55df</link>
      <guid>https://dev.to/robogeek95/a-visual-giude-on-quicksort-algorithm-55df</guid>
      <description>&lt;p&gt;An &lt;a href="https://en.wikipedia.org/wiki/Algorithm" rel="noopener noreferrer"&gt;algorithm&lt;/a&gt; is a finite series of steps that a computer would take to implement a task in an efficient manner.&lt;/p&gt;

&lt;p&gt;Sorting algorithms are generally used to rearrange elements of an array to follow a certain order. Popular examples of sorting algorithms include &lt;a href="https://en.wikipedia.org/wiki/Heapsort" rel="noopener noreferrer"&gt;Heapsort&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Merge_sort" rel="noopener noreferrer"&gt;Merge sort&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Quicksort" rel="noopener noreferrer"&gt;Quicksort&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, you would learn the techniques of sorting using a Quicksort algorithm as well as how to implement one in the JavaScript programming language. You would also learn about the algorithmic complexity of this sorting algorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Quicksort
&lt;/h2&gt;

&lt;p&gt;Quicksort is a divide-and-conquer algorithm. It works by selecting a 'pivot' element from the array. Every other element of the array is swapped such that elements greater than the pivot elements are on one side and the lesser elements are on the other side of the array and the array ends up being partitioned into sub-arrays. The sub-arrays are then sorted recursively until the array is sorted. This is done in place, so a little additional memory space is required to implement the sorting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps in implementing Quicksort
&lt;/h2&gt;

&lt;p&gt;Just like every other algorithm, the Quicksort algorithm has a few techniques that bound its implementation. Let’s dig into the steps involved to correctly implement a Quicksort algorithm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Selecting a pivot element
&lt;/h3&gt;

&lt;p&gt;The first step is to pick an element from the array as the pivot element. There are different methods applied to select the pivot element but it is worth mentioning that the method used in sleeting the pivot element might affect the resulting speed of your implementation, you would talk more about this in the complexity analysis section of this article.&lt;/p&gt;

&lt;p&gt;The pivot element is selected by either of the following technique:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first element of the array&lt;/li&gt;
&lt;li&gt;The last element of the array&lt;/li&gt;
&lt;li&gt;A random element selected from the array&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This simply means the pivot element could be any element from the array but it’s a better approach to stick to one method for selecting the for this process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compare and swap elements with respect to the pivot element
&lt;/h3&gt;

&lt;p&gt;The selected pivot element is then used as a reference to swapping each element of the array in such a way that all elements of the array that are lesser than the pivot element are placed on the left-hand side and all other items greater than the pivot are placed on the right-hand side. This process generates two partitions, a partition with elements that are greater than the pivot element and the other partition that holds elements lesser than the partition. Finally, the pivot element is placed in between the two partitions generated which can be said to now be in its correct index. &lt;/p&gt;

&lt;h3&gt;
  
  
  Repeat 🔁
&lt;/h3&gt;

&lt;p&gt;The partitioning process is repeated for every resulting partition of the array until every single item is ultimately in the right place, the array is then said to be fully sorted.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example of implementing Quicksort
&lt;/h2&gt;

&lt;p&gt;Let’s see a quick example of the process of implementing a Quicksort algorithm by sorting an unordered array. We would look at how to implement this algorithm using a programming language later in this article.&lt;/p&gt;

&lt;p&gt;There would have two pointers; the right pointer and the left pointer pointing to both extreme indexes of the array. By comparing the elements at both pointers to that of the pivot element, we decide which element to swap and to which side it should be swiped.&lt;/p&gt;

&lt;p&gt;Next, the elements are swapped so that only the items that are lesser than the pivot element are on the left side and the larger elements are swapped to the left. We determine elements to swap by advancing the pointers and comparing each element till we find an element that doesn't match the requirement for the side it resides. The comparison starts from the left pointer, after we have an element that’s lesser than the pivot element, we then find the next element that’s larger than the pivot element from the right pointer to swap out with.&lt;/p&gt;

&lt;p&gt;The elements of the unsorted array are listed in the image below:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Images and Indicators
&lt;/h3&gt;

&lt;p&gt;In order to make it easier for you to grasp the concepts, this article provides illustrated images in the examples. The several colours used to indicate the different states and interactions of the elements and the pointers during sorting are described below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gray&lt;/strong&gt; - Indicates the element’s default state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yellow&lt;/strong&gt; - Indicates a pivot element&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Green&lt;/strong&gt; - Indicates a sorted element&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the following colours are used for the pointers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Green&lt;/strong&gt; - Indicates the pointer is active&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pink&lt;/strong&gt; - Indicates the pointer is inactive&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  First Iteration
&lt;/h3&gt;

&lt;p&gt;The first step is to select a pivot element. Using the first method for pivot element selection as described above, we select &lt;code&gt;5&lt;/code&gt; as the pivot element, since it’s the first element of the array.&lt;/p&gt;

&lt;p&gt;In this case, the right and left pointers initially point to &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;8&lt;/code&gt; respectively. Element &lt;code&gt;4&lt;/code&gt; is less than the pivot element, we swap it with element  &lt;code&gt;7&lt;/code&gt;. The same goes for elements &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;6&lt;/code&gt;, they are swapped so they are placed on their appropriate sides of the array.&lt;/p&gt;

&lt;p&gt;Finally, we move the pivot element  &lt;code&gt;5&lt;/code&gt; to the centre, it is then marked as sorted.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Second Iteration
&lt;/h3&gt;

&lt;p&gt;This first iteration has placed it’s pivot element in its correct position. The iteration also partitioned the array into two sub-arrays each of which also need to be sorted.&lt;/p&gt;

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

&lt;p&gt;We are sorting the left sub-array completely first, then we proceed to the right sub-array. It’s also okay to go the other way round.&lt;/p&gt;

&lt;p&gt;Following the same method as in the first iteration, we select the pivot element using the first method so we pick &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Scanning through the left pointer, there are no elements greater than the pivot element found so this sub-array is sorted and there would be no swaps on this iteration.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Third Iteration
&lt;/h3&gt;

&lt;p&gt;The second index has placed element &lt;code&gt;1&lt;/code&gt; in its correct position, we also indicate that with a green background in the image below. It generates another sub-array with two elements.&lt;/p&gt;

&lt;p&gt;We select the element on the first index of the third sub-array &lt;code&gt;2&lt;/code&gt; as the pivot element.&lt;/p&gt;

&lt;p&gt;We place the pointers and compare the two elements, all elements of this sub-array also happen to be in place and there are no swaps for this iteration.&lt;/p&gt;

&lt;p&gt;We mark the pivot element sorted. Since there is only one item left unmarked from this sub-array, there is no use partitioning it into another subarray since there would be no comparisons or swaps. Instead, the element is also marked as sorted.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Fourth Iteration
&lt;/h3&gt;

&lt;p&gt;The Third iteration has fully sorted every item on the left side. We proceed to the left subarray next.&lt;/p&gt;

&lt;p&gt;Select &lt;code&gt;6&lt;/code&gt; as the pivot element. Comparing the other elements, element &lt;code&gt;7&lt;/code&gt; is greater than the pivot element &lt;code&gt;6&lt;/code&gt; so it would not be swapped, the same is true for &lt;code&gt;9&lt;/code&gt;. There would be no swaps in the partition.&lt;/p&gt;

&lt;p&gt;We then mark the pivot element for this sub-array &lt;code&gt;6&lt;/code&gt; as sorted. This is indicated with the green background in the image below.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Fifth Iteration
&lt;/h3&gt;

&lt;p&gt;We’re almost done sorting with just one more partition to go. The last partition contains two elements.&lt;/p&gt;

&lt;p&gt;All of the steps are still required, we select the pivot element by picking the first element of the current sub-array &lt;code&gt;9&lt;/code&gt;. &lt;code&gt;7&lt;/code&gt; is less than &lt;code&gt;9&lt;/code&gt;. We swap both elements places them in order.&lt;/p&gt;

&lt;p&gt;We mark the pivot element &lt;code&gt;9&lt;/code&gt; as sorted, we also mark the last element as sorted since it cannot be broken into a sub-array.&lt;/p&gt;

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

&lt;p&gt;We now have a fully sorted array using the Quicksort algorithm.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Implementing a Quicksort algorithm in javascript
&lt;/h2&gt;

&lt;p&gt;Let’s now take a look at the programmatic method of implementing the Quicksort algorithm in the JavaScript programming language.&lt;/p&gt;

&lt;p&gt;open your code editor and create a  new file called &lt;code&gt;quicksort.js&lt;/code&gt;. This file would hold all the code for the Quicksort algorithm we are implementing.&lt;/p&gt;

&lt;p&gt;First, create a function to perform the swap&lt;/p&gt;

&lt;h3&gt;
  
  
  Code to swap
&lt;/h3&gt;

&lt;p&gt;First paste the code below in your file to create the function &lt;code&gt;swap()&lt;/code&gt; :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;leftIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rightIndex&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;leftIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;leftIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rightIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rightIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;swap()&lt;/code&gt; as its name implies, basically performs a swap of the indexes of the provided elements and replaces the new value into the original array.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Code to perform the partition&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Paste the following code for function &lt;code&gt;partition&lt;/code&gt; in your &lt;code&gt;quicksort.js&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt; &lt;span class="c1"&gt;//middle element&lt;/span&gt;
        &lt;span class="nx"&gt;i&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//left pointer&lt;/span&gt;
        &lt;span class="nx"&gt;j&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//right pointer&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//sawpping two elements&lt;/span&gt;
            &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The partition function accepts the unsorted array, starting index and ending index as its arguments. It uses the middle element as the pivot element. The function then swaps the elements of the unsorted array such that all the elements to the left of the pivot are lesser than the pivot and all the elements to the right of the pivot are greater than it. It returns the index of the pivot element in the sorted array after positioning it in its correct position.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;unsortedArray&lt;/code&gt; would be replaced with the actual values of the array that needs to be sorted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement &lt;strong&gt;the sorting&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is the main function that implements quick sort. Update your file to reflect the function:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//index returned from partition&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//more elements on the left side of the pivot&lt;/span&gt;
            &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//more elements on the right side of the pivot&lt;/span&gt;
            &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;quicksort&lt;/code&gt; function executes recursively, invoking itself several times until all of the unsorted arrays are completely sorted. It also expects the unsorted array, a starting index and an ending index of the array to be sorted. &lt;/p&gt;

&lt;p&gt;It uses the index returned from the function &lt;code&gt;partition&lt;/code&gt; to divide the array and perform the Quicksort. &lt;/p&gt;

&lt;p&gt;💡 Quicksort is performed on the same array and no new arrays are created in the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time to test your algorithm
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;unsortedArray&lt;/code&gt; currently holds an empty array, update the &lt;code&gt;unsortedArray&lt;/code&gt; constant in &lt;code&gt;quicksort.js&lt;/code&gt;  to now hold the actual values from the example earlier:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Finally, add the code to invoke the function and log the output to the console:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unsortedArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now, open up your terminal, locate the file and run the file using node. You can run it by running the command below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="nx"&gt;quicksort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;


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

&lt;/div&gt;

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

&lt;h2&gt;
  
  
  Complexity Analysis of Quicksort
&lt;/h2&gt;

&lt;p&gt;The best-case complexity of the quick sort algorithm is O(n logn) also, the average case time complexity is &lt;em&gt;O(*n logn&lt;/em&gt;)*.&lt;/p&gt;

&lt;p&gt;The worst-case time complexity of Quick Sort is O(n2). The worst-case is usually avoided by using a randomized method for selecting the pivot element.&lt;/p&gt;

&lt;p&gt;For the space complexity, Quicksort &lt;strong&gt;in-place&lt;/strong&gt; algorithm, meaning it doesn't take any extra memory space for its implementation because it performs all of the operations on the same array. It takes O(log n) stack space.&lt;/p&gt;

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

&lt;p&gt;This article has walked you through the techniques behind the Quicksort algorithm, an illustrated example as well as how to implement one in javascript.&lt;/p&gt;

&lt;p&gt;Thank you for reading and I hope you learned a lot. My name is Azeez Lukman, please stay tuned for more if you would like to keep adding to your algorithmic toolbox 🧰&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.geeksforgeeks.org/sorting-algorithms/" rel="noopener noreferrer"&gt;https://www.geeksforgeeks.org/sorting-algorithms/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.interviewbit.com/tutorial/quicksort-algorithm/" rel="noopener noreferrer"&gt;https://www.interviewbit.com/tutorial/quicksort-algorithm/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.guru99.com/quicksort-in-javascript.html" rel="noopener noreferrer"&gt;https://www.guru99.com/quicksort-in-javascript.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Quicksort" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Quicksort&lt;/a&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
    </item>
    <item>
      <title>An ultimte guide to building an order tracking dashboard with Appsmith</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Sat, 29 Jan 2022 13:09:38 +0000</pubDate>
      <link>https://dev.to/robogeek95/an-ultimte-guide-to-building-an-order-tracking-dashboard-with-appsmith-4pbh</link>
      <guid>https://dev.to/robogeek95/an-ultimte-guide-to-building-an-order-tracking-dashboard-with-appsmith-4pbh</guid>
      <description>&lt;p&gt;&lt;a href="https://app.appsmith.com/?utm_source=blog&amp;amp;utm_medium=direct&amp;amp;utm_content=appsmith_apps&amp;amp;utm_campaign=weeklyblog&amp;amp;utm_term=appsmith_apps%20%E2%80%9CAppsmith%20open-source%20framework%20for%20building%20internal%20tools%E2%80%9D"&gt;Appsmith&lt;/a&gt; is an open-source framework for developing low code dashboards, workflows, pages, and CRUD apps very quickly. Appsmith allows you to build tools with little or no code. Appsmith has more flexibility than off-the-shelf options and it’s fast to build and easy to maintain.&lt;/p&gt;

&lt;p&gt;In this tutorial, you are going to learn how to use Appsmith to build an order tracking dashboard for an e-commerce store. The store’s order data is stored on a Firestore database, you would also see how to quickly integrate Firestore into your Appsmith dashboard and run queries from Appsmith.&lt;/p&gt;

&lt;p&gt;Before we get started let’s go over some requirements needed to complete this tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://firebase.google.com/"&gt;Firebase&lt;/a&gt; account with &lt;a href="https://cloud.google.com/firestore/"&gt;Firestore&lt;/a&gt; setup&lt;/li&gt;
&lt;li&gt;Experience with Javascript is a plus but not required&lt;/li&gt;
&lt;li&gt;Finally, you can view a demo of what you would be building &lt;a href="https://app.appsmith.com/applications/61ed40aabe698f35db54f7f5/pages/61ed40aabe698f35db54f7f8"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alright, that’s all you need. So let’s jump right in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Before you can start using Appsmith, you need to create an account, so head over to Appsmth to &lt;a href="https://app.appsmith.com/user/login"&gt;create an account&lt;/a&gt; if you have not already done that. Alternatively, you can also deploy Appsmith on your local machine or private server instance since it’s open-source software but that’s beyond the scope of this tutorial.&lt;/p&gt;

&lt;p&gt;You should be redirected to the &lt;a href="https://app.appsmith.com/applications"&gt;dashboard&lt;/a&gt; after signing up. The next step is to create a new application on Appsmith. &lt;/p&gt;

&lt;p&gt;Click the Create New button to create a new application and name it Acme Store. This takes you to an empty workspace with a sidebar. On the sidebar, you should see a navigation menu with a page. Pages are synonymous with web pages. Each page on Appsmith includes the widget, the datasources and the JS objects. in the following content, we would build the app by digging deeper into each of these items.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Datasource
&lt;/h2&gt;

&lt;p&gt;Appsmith allows you to easily integrate APIs or databases such as MongoDB, Firestore and more out of the box. You can run queries to read and write data directly from the Appsmith editor.&lt;/p&gt;

&lt;p&gt;This tutorial integrates with a Firestore database. &lt;/p&gt;

&lt;p&gt;💡 It is assumed that you already have an existing Firestore database set up, you can follow this &lt;a href="https://firebase.google.com/docs/firestore/quickstart"&gt;guide&lt;/a&gt; to quickly get one running.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the Datasource
&lt;/h3&gt;

&lt;p&gt;On the Appsmith dashboard, click on &lt;strong&gt;+&lt;/strong&gt; next to &lt;strong&gt;Datasources&lt;/strong&gt; and find Firebase on the list.&lt;/p&gt;

&lt;p&gt;The Firestore plugin requires three pieces of information to establish a connection; the database URL, the project id and the service account credentials. Follow the below instructions to set it up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project ID:&lt;/strong&gt; Navigate to "Project Settings" in your Firebase console and ensure you're in the "General" tab. You'll find a "Project ID" here, copy this value into the "Project ID" field in the Firestore configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database URL:&lt;/strong&gt; The database URL need to be formed using the Firebase &lt;em&gt;project ID&lt;/em&gt; you found above. Enter the database URL in the following manner &lt;code&gt;your-project-id.firebaseio.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetching Service Account Credentials:&lt;/strong&gt; Navigate to the “service accounts” tab in your firebase console and find a "Generate new private key" button below the code snippet. Click the button to generate a new private key to access this Firestore instance and open the JSON file downloaded. Paste the content of this file into the "Service Account Credentials" field.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After filling up the three fields as described above, click on the "Test" button to verify the configuration and click "Save".&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Data Schema
&lt;/h3&gt;

&lt;p&gt;Remember we’re building an application to track a record of orders. It would be nice to populate the database with some documents at this point so we can focus on integrating these records into the app moving on.&lt;/p&gt;

&lt;p&gt;Collections hold documents. Since Firestore is a no-SQL database, it doesn't expect your documents to be fixed to a certain schema. You can structure every object of your documents as you deem fit but you still try as much as possible to keep your data uniform.&lt;/p&gt;

&lt;p&gt;Create a new collection and call it &lt;code&gt;orders&lt;/code&gt; to record the orders. Then you need to place some documents in the collection. Here’s the orders schema this tutorial is working with: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;date&lt;/code&gt;:&lt;/strong&gt; A &lt;code&gt;timestamp&lt;/code&gt; value for when the order was placed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;shipment&lt;/code&gt;:&lt;/strong&gt; A &lt;code&gt;map&lt;/code&gt;/&lt;code&gt;object&lt;/code&gt; that holds the shipping details for the order. it contains the address, email and phone of string types.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;**items&lt;/code&gt;:** An &lt;code&gt;array&lt;/code&gt; of objects/maps of the items bought.  Each item contains its &lt;code&gt;price&lt;/code&gt;, &lt;code&gt;quantity&lt;/code&gt; and &lt;code&gt;productName&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;**customer**&lt;/code&gt;: info about the customer that placed the order. Contains the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; of the customer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;status&lt;/code&gt;:&lt;/strong&gt; a &lt;code&gt;string&lt;/code&gt; label to track the status of the order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go ahead and populate the orders collection with some document records following the above convention.&lt;/p&gt;

&lt;p&gt;you should have something similar to this:&lt;/p&gt;

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

&lt;p&gt;You also need a collection to hold the list of status you track orders with. It follows the same process as for the &lt;code&gt;orders&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Create a new collection and call it &lt;code&gt;labels&lt;/code&gt; add a document to the collection, name the document &lt;code&gt;status_labels&lt;/code&gt; and populate it with the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;**values&lt;/code&gt;:**  an array of objects/map containing &lt;code&gt;label&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt; properties which are both string types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you should also have something similar to this:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Execute Queries
&lt;/h2&gt;

&lt;p&gt;Now that you have fully integrated the database, you are ready to start adding some actual integrations. Appsmith allows you to create queries to fetch and update data from your datasource using the Appsmith query editor.&lt;/p&gt;

&lt;p&gt;You can create and manage queries from the sidebar on the Appsmith dashboard. Click on the datasource you integrated earlier, on the next page, click on the “new query” button to create a new query.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Get orders
&lt;/h3&gt;

&lt;p&gt;This query would fetch all the records from the &lt;code&gt;orders&lt;/code&gt; collection. &lt;/p&gt;

&lt;p&gt;Create a new query and name it &lt;code&gt;get_orders&lt;/code&gt;. Click the commands dropdown and select ‘Get Documents in Collection’ since we are getting the record of documents in the orders collection. The “Collection/Document Path” should be &lt;code&gt;orders&lt;/code&gt;. Leave the remaining fields as their default.&lt;/p&gt;

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

&lt;p&gt;Run the query and you should have something similar to this in the response field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1642460400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nanos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"shipment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lagos, nigeria"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+2346994948383"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"taylorswift@gmail.com"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1g3VP3gNePsYGZWNaC4k"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"orders/1g3VP3gNePsYGZWNaC4k"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"25000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"productName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stallion Rice"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"draft"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Taylor Swift"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"taylorswift@gmail.com"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get status labels
&lt;/h3&gt;

&lt;p&gt;This query returns the record of status labels in the database. It follows a similar process as getting all orders except this reads a document and not a collection.&lt;/p&gt;

&lt;p&gt;Create a new query, set commands to “Get Single Document” and the path as “labels/status”. &lt;/p&gt;

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

&lt;p&gt;Run the query and you should get a response similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"values"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pending"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"draft"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"draft"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"labels/status"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update order
&lt;/h3&gt;

&lt;p&gt;The final query allows us to update the order directly from the dashboard, to keep this tutorial simple we’re only focusing on updating the order’s status.&lt;/p&gt;

&lt;p&gt;Create a new query and set the command to “Update Document”. Next is the “Collection/Document Path”, set it to &lt;code&gt;orders/{{orders.selectedRow._ref["id"]}}&lt;/code&gt;. Notice how the query extracts the current row data id from the table widget, this way, you’re able to update the selected document. But we don’t have any widgets yet, so let’s go ahead and build that next.&lt;/p&gt;

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

&lt;p&gt;Run the query and firestore should return a timestamp value denoting the last update time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastUpdateTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1642981099&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nanos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88277000&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Widgets
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.appsmith.com/core-concepts/displaying-data-read#widgets"&gt;Widgets&lt;/a&gt; act as the building blocks for Appsmith UI. They can be &lt;a href="https://docs.appsmith.com/core-concepts/designing-an-application#placing-widgets-on-the-canvas"&gt;dragged&lt;/a&gt; from the widget pane, positioned on the canvas, and resized to fit the data they need to display. They also come with properties that can be visually edited to set their data, change their styles, and trigger actions from them.&lt;/p&gt;

&lt;p&gt;Widget properties can be edited via the property pane which is opened using the top-right icon (Edit Widget Properties). Data from a Query can be set in a widget property by referencing the name (unique identifier) of the Query.&lt;/p&gt;

&lt;p&gt;We’ve been going over some boring stuff all day, it’s about time we did something fun. Let’s start building out the UI for the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heading
&lt;/h3&gt;

&lt;p&gt;It would be nice to place a heading on the top of the app. On the sidebar toggle the widgets panel and drag the text widget onto the canvas. Then from the properties panel, change the text to “Acme Store Dashboard”. Next drag in a divider widget right under the heading. &lt;/p&gt;

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

&lt;p&gt;Every other widget would be placed under the header.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table
&lt;/h3&gt;

&lt;p&gt;This would be used to display the orders in tabular form. On the sidebar toggle the widgets panel and drag the table widget onto the canvas. Then from the properties panel, delete the default columns and the default table data. Then create the date, order Id, customer and status columns. &lt;/p&gt;

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

&lt;h3&gt;
  
  
  Details panel
&lt;/h3&gt;

&lt;p&gt;On the selection of each table row, we want to show more data about the order on that row in the details panel. Drag in a “container” widget and logically divide the screen portion under the heading such that the table takes up 60% and the details panel takes up 40% of the screen width.&lt;/p&gt;

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

&lt;p&gt;Add another container widget in the details panel and place a text widget in it, rename the text to “Track Order”. Next, drag in a text widget for order Id and place another text widget next to it to hold the value, do the same for the customer, address, email and phone. &lt;/p&gt;

&lt;p&gt;Place a divider before the address, email and phone fields and place a heading “Shipment” using the text widget above them.&lt;/p&gt;

&lt;p&gt;Add another divider, an heading “Items” and drag in another table widget into the panel. &lt;/p&gt;

&lt;p&gt;💡 You might need to resize the table in an open area of the canvas so that it fits the details panel before you can place it there. learn more about resizing a widget &lt;a href="https://docs.appsmith.com/core-concepts/designing-an-application#resizing-a-widget"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, add a button to update the database with the edits. Update the button text to “Update” from the properties panel.&lt;/p&gt;

&lt;p&gt;You’re almost done with the UI, but first, take some time to update the UI to match the image below:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Integrate Datasource
&lt;/h2&gt;

&lt;p&gt;It's time to bring your implementation to life by making everything you have been implementing communicate with each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Display Data in Tables
&lt;/h3&gt;

&lt;p&gt;The table widget can automatically loop through an array of items provided as the table data. &lt;/p&gt;

&lt;p&gt;Set the table data from the properties pane by referencing the get all orders query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt;get_orders.data&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s take a moment to talk about the brackets. Appsmith supports writing single line javascript from any field between the template syntax &lt;code&gt;{{}}&lt;/code&gt;, the content within it can then point to a variable or be an evaluation.&lt;/p&gt;

&lt;p&gt;Appsmith is reactive, that way, the &lt;code&gt;get_orders&lt;/code&gt; value is stored immediately you tested it earlier so you don’t have to run the query for every field you need it. In the example above, the syntax refers to the data returned from the get_orders query.&lt;/p&gt;

&lt;p&gt;💡 widgets are automatically updated whenever the data in the Query changes&lt;/p&gt;

&lt;p&gt;After adding the table data, the columns and values are automatically populated for you with the top-level properties from the response data, but we don’t want to show that much information on the table. On the right of each icon use the eye icon to hide each column except the date customer and status.&lt;/p&gt;

&lt;p&gt;You also need to add another column for the order id by clicking the “ADD A NEW COLUMN” button and naming it to order Id. Configure the value by clicking the “Setting” icon on the column and place the following syntax in the computed value field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt;currentRow._ref&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;{{currentRow._ref["id"]}}&lt;/code&gt; is used to select the id from the table’s current selected row. We then place a &lt;code&gt;#&lt;/code&gt; character is placed before each value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Display values in the detail panel
&lt;/h3&gt;

&lt;p&gt;The values displayed here would be inferred from the selected row, so it’s dynamic and shows detail for each order.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;Order id&lt;/code&gt;, replace its value field with the following template syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_ref&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the customer value field with the following template syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the label text for the status with the following template syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the options, you need to get the value from the query to get status labels, replace the options field of the status dropdown with the syntax below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;get_status_labels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is the update button. We want to keep track of the orders by updating their status using the labels you have just configured. But when you change the label from the dashboard, it doesn't reflect on the database yet.&lt;/p&gt;

&lt;p&gt;Button widgets in Appsmith have an event handler property which can be found on the properties pane. The idea is to run the update record query each time the button is clicked, persisting the updated status in the Firestore. Select execute a query as the event select the &lt;code&gt;update_order&lt;/code&gt; query you created earlier. Now change the label and click the update button, notice the change from your database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep your data up to date
&lt;/h3&gt;

&lt;p&gt;You’re almost done except that you don’t want your table to have redundant fields. Appsmith allows you to also specify callback actions to handle both success and error events. For now, we are concerned with the success callback, we can use this to fetch the current data from Firestore and Appsmith would automatically propagate the data into the widgets.&lt;/p&gt;

&lt;p&gt;Click on the update button, then select the onSuccess callback from the onClick event handler, select execute a query as the action the select the &lt;code&gt;get_orders&lt;/code&gt; query.&lt;/p&gt;

&lt;p&gt;You should now have a similar dashboard to the one in the image below:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Publish your Application
&lt;/h3&gt;

&lt;p&gt;The last step is to make it available for use, there are a couple of ways to do this;  you can either add people to the organization where the project sits or make it generally available to the public.&lt;/p&gt;

&lt;p&gt;Select the share button from the far right of the navbar and you should see a toggle button labelled &lt;code&gt;Make the application public&lt;/code&gt; in the modal that pops up, toggle it and copy the generated link to start sharing your progress.&lt;/p&gt;

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

&lt;p&gt;💡 Remember, the demo for this tutorial is available &lt;a href="https://app.appsmith.com/applications/61ed40aabe698f35db54f7f5/pages/61ed40aabe698f35db54f7f8"&gt;here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Congratulations! you have seen how easy it is to build a custom dashboard with little code using a WYSWYG editor. You can fully utilize this approach to build a fully functional dashboard for your enterprise and small scale e-commerce applications.&lt;/p&gt;

&lt;p&gt;Thanks for reading, I’m Azeez Lukman and here’s a developer’s journey to building something awesome every day. Please let's meet on &lt;a href="http://twitter.com/robogeek95"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/azeez-lukman-b35057146"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://github.com/Robogeek95"&gt;GitHub&lt;/a&gt; and anywhere else @robogeeek95.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to access string values in Go </title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Tue, 26 Oct 2021 22:42:22 +0000</pubDate>
      <link>https://dev.to/robogeek95/how-to-access-string-values-in-go-16cb</link>
      <guid>https://dev.to/robogeek95/how-to-access-string-values-in-go-16cb</guid>
      <description>&lt;p&gt;GO represents strings as byte slices using under the hood. This means you can access different indexes of a string like you would for a slice variable.&lt;/p&gt;

&lt;p&gt;A byte slice is a slice whose underlying type is a slice. Byte slices are more like lists of bytes that represent UTF-8 encodings of Unicode code points.&lt;/p&gt;

&lt;p&gt;Strings are immutable, unicode compliant and are UTF-8 encoded&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing the individual bytes of a string
&lt;/h3&gt;

&lt;p&gt;I mentioned above that a string is a slice of bytes. We can access every individual byte in a string&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bytes: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%x "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello String"&lt;/span&gt;


    &lt;span class="n"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;String: Hello World  
Bytes: 48 65 6c 6c 6f 20 57 6f 72 6c 64 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We print the bytes in the string 'Hello String' by looping through the string using len() method. the len() method returns the number of bytes in the string, we then use the returned number to loop through the string and access the bytes at each index. The bytes are printed in hexadecimal formats using &lt;code&gt;%x&lt;/code&gt; format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing individual characters of a string
&lt;/h3&gt;

&lt;p&gt;Let's modify the above program a little bit to print the characters of the string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;package&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fmt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bytes: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%x &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;printChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Characters: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%c &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="nl"&gt;name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;


    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="nx"&gt;printChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="nx"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="nx"&gt;World&lt;/span&gt;
&lt;span class="nx"&gt;Characters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;H&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;   &lt;span class="nx"&gt;W&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;
&lt;span class="nx"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="mi"&gt;57&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic remains the same as above, but this time, you would notice the use of &lt;code&gt;%c&lt;/code&gt; format specifier, which is used to to print the &lt;code&gt;characters&lt;/code&gt; of the string in the method.&lt;/p&gt;

&lt;p&gt;In UTF-8 encoding a code point can occupy more than 1 byte, so this method of accessing the characters is not well suited since we are only assuming that each code point occupies one byte. A better approach is to use runes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bytes: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%x "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Characters: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%c "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="n"&gt;testSring&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Señor"&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"String: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testSring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;printChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testSring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testSring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;String: Señor
Characters: S e Ã ± o r
Bytes: 53 65 c3 b1 6f 72
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the program breaks, the characters returns Ã ± instead for ñ. The reason is that the Unicode code point of ñ is U+00F1 and its UTF-8 encoding occupies 2 bytes c3 and b1. We are trying to print characters assuming that each code point will be one byte long which is wrong. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rune
&lt;/h3&gt;

&lt;p&gt;A rune is simply a character. It is a builtin data type in Go. Rune literals are 32-bit integer values that represents a Unicode Codepoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bytes: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%x "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Characters: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;runes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%c "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="n"&gt;testString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Señor"&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"String: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;printChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;printBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;String: Señor
Characters: S e ñ o r
Bytes: 53 65 c3 b1 6f 72
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the string is converted to a slice of runes using []rune. We then loop over it and display the characters. This works because a rune can represent any number of bytes the code point has.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing specific characters in a string
&lt;/h3&gt;

&lt;p&gt;now we have seen how to access all the characters of a string. Let's see how we can access the individual indexes of the string. Remember that a string in Go is a slice of bytes so we can easily access the character at a specific index like we would for a slice, or an array without needing to loop through the string or convert it to a rune.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;testString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello String"&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="m"&gt;108&lt;/span&gt;
&lt;span class="m"&gt;101&lt;/span&gt;
&lt;span class="m"&gt;111&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the unicode code points for the specified indexes&lt;/p&gt;

&lt;p&gt;Trying to access an index that is larger than your string's length throws an index out of range error, since the index specified exceeds the available range in your declared string&lt;/p&gt;

&lt;p&gt;That was swift, all we did was declare the string and specify the index we would like to access. This is actually not our intended purpose, we still need to be able to access the actual character and not it's unicode value.&lt;/p&gt;

&lt;p&gt;To access the character, we convert the Unicode code point using the builtin string method &lt;code&gt;string()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;testString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello String"&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;l
e
o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A simple program to check if a string begins with a lower case letter or an upper case letter
&lt;/h3&gt;

&lt;p&gt;Using our knowledge on accessing string values, we are going to write a small Go program that reports if a string passed in begins with a lower-case or upper-case letter&lt;/p&gt;

&lt;p&gt;Declare package and and a function that checks if the whether the string has a lower-case letter at the begining. &lt;/p&gt;

&lt;p&gt;There is no perform any checks if the parameter is an empty string, so the function checks for that first and returns &lt;code&gt;false&lt;/code&gt; is it's an empty string  &lt;/p&gt;

&lt;p&gt;Next is the actual work, Go comparisons can automatically compare values within a range, in this case, we are checking if the first slice index of the string parameter exists within the range of lower-case letters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;


&lt;span class="c"&gt;// startsWithLowerCase reports whether the string has a lower-case letter at the beginning.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;startsWithLowerCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="sc"&gt;'z'&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;startsWithUpperCase&lt;/code&gt; function also compares the first letter of the string parameter across a range, but this time, it compares across a range of capital letters. add this function to your program&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// startsWithUpperCase reports whether the string has an upper-case letter at the beginning.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;startsWithUpperCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="sc"&gt;'Z'&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's time to wrap up and test out program, declare the main function. Inside the main function, you would declare your test string and call the functions passing the testString as parameter. We want to properly report our results so we use fmt.Printf to format our report and print to the console&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;testString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello String"&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'%s' begins with upper-case letter? %t &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


        &lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


        &lt;span class="n"&gt;startsWithUpperCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"'%s' begins with lower-case letter? %t &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


        &lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


        &lt;span class="n"&gt;startsWithLowerCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testString&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s1"&gt;'Hello String'&lt;/span&gt; begins with upper-case letter? &lt;span class="nb"&gt;true&lt;/span&gt; 
&lt;span class="s1"&gt;'Hello String'&lt;/span&gt; begins with lower-case letter? &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cooool right? You have just created an enterprise grade program. Yes, &lt;code&gt;startsWithLowerCase&lt;/code&gt; is the same logic used to in Go time package for the purpose of preventing  matching strings like "Month" when looking for "Mon"&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;With this deep dive on accessing held in Go strings, you're ready to take over the world. But before that, There’s only one way to learn to develop Go programs: write a lot of code. Keep coding and taking over the world is only a matter of time. &lt;/p&gt;

&lt;p&gt;Thank you for reading, I'm Azeez Lukman and here's a developer's journey building something awesome every day. Please let's meet on Twitter, LinkedIn and GitHub and anywhere else @robogeeek95&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Slicing Slices in GO</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Fri, 08 Oct 2021 04:28:47 +0000</pubDate>
      <link>https://dev.to/robogeek95/slicing-slices-in-go-1j5c</link>
      <guid>https://dev.to/robogeek95/slicing-slices-in-go-1j5c</guid>
      <description>&lt;p&gt;Slices wrap arrays in Go and provide a more general, powerful, and convenient interface to data sequences. In this article, you will cover slice basics such as creating, initializing, and iteration. You will also learn how to grow a slice, work with subsets of slices, and slice tricks.&lt;/p&gt;

&lt;p&gt;Slices contain a list of elements of a particular type, but unlike arrays, there are methods available to add or remove elements from the slice. This is because as the name implies, slices don't hold any actual data themselves. A slice provides a view into the elements of the underlying array and provides extra methods for interacting with the data.&lt;/p&gt;

&lt;p&gt;slices are much more common than arrays&lt;/p&gt;

&lt;h2&gt;
  
  
  Slice Type
&lt;/h2&gt;

&lt;p&gt;The type []T denotes a slice of type T for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This says hey, this is a slice of strings or this slice contains string values. The values would be comma separated. This is similar to how you would declare the type for an array variable, except the length is omitted here. &lt;/p&gt;

&lt;p&gt;For the most part, functions for working with slices is identical to functions for working with arrays. These functions includes ones for accessing elements, using zero values, passing slices to the len function, and for...range loops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slice Values
&lt;/h2&gt;

&lt;p&gt;Like i mentioned above, slices themselves don't store any values at all. You may be wondering how it then holds data. Slices are designed to work as a convenience wrapper for arrays, allowing you to easily perform functions that would have been difficult to manually perform directly on an array.&lt;/p&gt;

&lt;p&gt;I like to think of a slice as a peek into some section of the underlying array. That peek is where you interact with the array from and the data you peek into is what you get to operate on.&lt;/p&gt;

&lt;p&gt;Now, you should note that modifying the peek elements makes the actual changes into the underlying array directly. This could be a blessing and a curse at the same time since the other slices with the same underlying array would see the changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Declaring slices&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To declare the type for a variable that holds a slice, you use an empty pair of square brackets, followed by the type of elements the slice will hold.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;intSlice&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This only declares a slice type that holds integer values as intSlice. Declaring a slice variable doesn’t automatically create a slice. For that, you call the built-in make function. You pass make the type of the slice you want to create and the length of slice it should create and assign it to your slice variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;intSlice&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt;
&lt;span class="nx"&gt;intSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After declaring the slice variable &lt;code&gt;intSlice&lt;/code&gt; . The next line creates the actual slice using the data type and the length. Notice the data type passed into make function is the same as that of the slice variable.&lt;/p&gt;

&lt;p&gt;So the make method created the slice, but hold, what about the values? By default the make method would fill the slice with the underlying data type's zero value of the slice we created for the length we passed in. In our example the slice &lt;code&gt;intSlice&lt;/code&gt; now contains 5 values as 0&lt;/p&gt;

&lt;p&gt;You can now use the builtin slice methods, let's run a few on the newly created slice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intSlice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;//4&lt;/span&gt;
&lt;span class="n"&gt;intSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;// 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we want to fill those spots up with our actual data, you would assign its elements using the same syntax you used for accessing it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;intSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; 
&lt;span class="n"&gt;intSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="n"&gt;intSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt; 
&lt;span class="n"&gt;intSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c"&gt;// 10&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c"&gt;// 8&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inSlice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// 10, 8, 9, 12, 0, 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Slice literal
&lt;/h2&gt;

&lt;p&gt;When you know the values that goes into your slice before declaring, you can directly pass them in using slice literal.  With slice literal, you do not need to use the make function, your slice gets declared and assigned its values in one step &lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;slice literal&lt;/strong&gt;  looks just like an array literal, except the length is omitted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;stringSlice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even use a multi line slice literal to make your more organized&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;stringSlice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s"&gt;"once"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s"&gt;"more"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you use a slice literal, an array is created and the slice is created to reference it, the slice gets a peek of the whole value inserted by the slice literal. The only way to access the array created is through the slice. &lt;/p&gt;

&lt;h2&gt;
  
  
  Slicing arrays
&lt;/h2&gt;

&lt;p&gt;Using the slice operator, you can create a slice directly from the array without using the make function, the operator is similar to the one used for accessing and assigning values in slices, but it has two indexes instead, the first denotes the start of the slice and the other denotes the end, excluding that index. The elements peeked into would span from the first index up to but not including the second index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;arrSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrSlice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 2,4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;omitting the last index causes the slice to include vlalues through to the last index of the array&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;arrSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrSlice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 2,4,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The os.Args package variable contains a slice of strings with the command-line arguments the current program was run with&lt;/p&gt;

&lt;h2&gt;
  
  
  Add items onto a slice
&lt;/h2&gt;

&lt;p&gt;Go provides a built-in append function that takes a slice, and one or more values you want to append to the end of that slice and returns a new, larger slice with all the same elements as the original slice, with the new element(s) added onto the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A slice’s underlying array can’t grow in size. If there isn’t room in the array to add elements, A new, larger array would be created and all its elements will be copied into it, then the slice will be updated to refer to this new array. But since all this happens behind the scenes in the &lt;code&gt;append&lt;/code&gt; function, there’s no easy way to tell whether the slice returned from &lt;code&gt;append&lt;/code&gt; has the &lt;em&gt;same&lt;/em&gt; underlying array as the slice you passed in, or a &lt;em&gt;different&lt;/em&gt; underlying array. If you keep both slices, this can lead to some unpredictable behavior such as inconsistencies.&lt;/p&gt;

&lt;p&gt;To avoid this, Always make sure to assign the return value of append function back to the same slice variable we passed to append&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Slices are a convenience wrapper around arrays, this is why they are very similar to arrays even with the methods used in manipulating them. Slices don't store value but operates on the underlying array. They can only hold one data type just like arrays too.&lt;/p&gt;

&lt;p&gt;Other things to explore includes converting strings to slices and vice versa, you should also look into how slices are used in place of variadic arguments in variadic functions.&lt;/p&gt;

&lt;p&gt;Thank you for reading,  i'm Azeez Lukman, should you need any help or questions please feel free to reach out &lt;a class="mentioned-user" href="https://dev.to/robogeek95"&gt;@robogeek95&lt;/a&gt;
 everywhere&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ansible File Structure, destructured</title>
      <dc:creator>Azeez Lukman</dc:creator>
      <pubDate>Sun, 03 Oct 2021 18:22:50 +0000</pubDate>
      <link>https://dev.to/robogeek95/ansible-file-structure-destructured-27cb</link>
      <guid>https://dev.to/robogeek95/ansible-file-structure-destructured-27cb</guid>
      <description>&lt;p&gt;The big question, Is there a recommended way to structure Ansible projects?&lt;/p&gt;

&lt;p&gt;Well, Ansible doesn’t have enforce patterns on how you put files into folders. But there are a few common approaches popular in the ecosystem you may want to consider. This guides walks you through.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keeping it simple 😉
&lt;/h3&gt;

&lt;p&gt;A pattern recommended though is to keep things as simple as you can, do things simply. Use advanced features only when necessary, if it begins to feel complex for the task, then it's probably complex. The documentation asks you to take the time to look for a simpler solution.&lt;/p&gt;

&lt;p&gt;Look no further, one solution is to start with the minimum pattern that is easy to build upon when you need to, and that is what this article is all about.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A typical Ansible file-structure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Keep your files organized in your working Ansible project directory like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;ansible&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;ansible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cfg&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;first_playbook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;inventory&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;group_vars&lt;/span&gt;
    &lt;span class="err"&gt;│  &lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;vyos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
    &lt;span class="err"&gt;│  &lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;eos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;roles&lt;/span&gt;
    &lt;span class="err"&gt;│  &lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;static_route&lt;/span&gt;
    &lt;span class="err"&gt;│  &lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;system&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;second_playbook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;third_playbook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this you can expand your inventory and create and run more network playbooks, let's destructure all these and what goes into them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ansible.cfg
&lt;/h3&gt;

&lt;p&gt;This is the ansible config file, commonly referred to as the brain and the heart of Ansible. It is file that defines Ansible config, and is responsible for how all processes in Ansible functions.&lt;/p&gt;

&lt;p&gt;By default Ansible reads its configuration file in /etc/ansible/ansible.cfg, however this behavior can be altered. The recommended practice is either to have an ansible.cfg in your current project working directory or to set it as an environment variable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Playbooks
&lt;/h3&gt;

&lt;p&gt;Ansible Playbooks are way to automate deployment tasks by using a repeatable, re-usable, simple configuration management and multi-platform deployment system.&lt;/p&gt;

&lt;p&gt;Each playbook contains one or more plays and each play defines the managed nodes to target and runs one or tasks on it. Each task calls an Ansible module. When you run a playbook, the plays are executed sequentially, &lt;strong&gt;play&lt;/strong&gt; by &lt;strong&gt;play&lt;/strong&gt; and each play also executes it's tasks sequentially from top to bottom.&lt;/p&gt;

&lt;p&gt;Ansible lets you define more than one playbook with each paybook focused on one function, you can have one playbook to create your deployment and another one to destroy it. Our example structure show first_playbook.yml, second_playbook.yml and third_playbook.yml.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inventory
&lt;/h3&gt;

&lt;p&gt;The Ansible inventory file defines the groups of hosts, commands, modules, and tasks a playbook can operate on. It functions as a list of managed nodes. An inventory can specify information like IP address for each managed node, you can designate different servers into groups like webservers, or databases&lt;/p&gt;

&lt;h3&gt;
  
  
  Group_vars
&lt;/h3&gt;

&lt;p&gt;Ansible uses a combination of a hosts file and a group_vars directory to pull variables per host group and run Ansible plays/tasks against hosts. group_vars/all is used to set variables that will be used for every host that Ansible is ran against.&lt;/p&gt;

&lt;p&gt;The group_vars in Ansible are a convenient way to apply variables to multiple hosts at once, they also provide a pattern for the reusability of group variables, saving you efforts to sort the hosts and also enhance the flexibility in your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Roles
&lt;/h3&gt;

&lt;p&gt;Roles allows to easily reuse your grouped content, One way to use roles is with the roles option for a play, then ansible follow your file structure and the order listed below to execute the role and replace the play task with its values.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any &lt;code&gt;pre_tasks&lt;/code&gt; defined in the play.&lt;/li&gt;
&lt;li&gt;Any handlers triggered by pre_tasks.&lt;/li&gt;
&lt;li&gt;Each role listed in &lt;code&gt;roles:&lt;/code&gt;, in the order listed. Any role dependencies defined in the role’s &lt;code&gt;meta/main.yml&lt;/code&gt; run first, subject to tag filtering and conditionals.&lt;/li&gt;
&lt;li&gt;Any &lt;code&gt;tasks&lt;/code&gt; defined in the play.&lt;/li&gt;
&lt;li&gt;Any handlers triggered by the roles or tasks.&lt;/li&gt;
&lt;li&gt;Any &lt;code&gt;post_tasks&lt;/code&gt; defined in the play.&lt;/li&gt;
&lt;li&gt;Any handlers triggered by post_tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Time for an example
&lt;/h3&gt;

&lt;p&gt;In addition to the above recommendations, i also recommend that you practalize your knowledge, &lt;a href="https://rafael-natali.medium.com/?source=post_page-----e97918bf41de--------------------------------"&gt;Rafael&lt;/a&gt; has written an amazing article on how to automate the setup of a Kubernetes cluster on GCP following a similar structure.&lt;/p&gt;

&lt;p&gt;This is the format he implemented&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;ansible&lt;/span&gt;                    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="nx"&gt;folder&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;ansible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cfg&lt;/span&gt;            &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;         &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;playbook&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;provision&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;playbook&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;inventory&lt;/span&gt;             
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;gcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;            &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;inventory&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;roles&lt;/span&gt;
        &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;destroy_k8s&lt;/span&gt;        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;remove&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;        
        &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;
        &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
        &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;destroy_network&lt;/span&gt;    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;remove&lt;/span&gt; &lt;span class="nx"&gt;VPC&lt;/span&gt;
        &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;
        &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
        &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;                &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;
        &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;
        &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
        &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt;            &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Ansible&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;VPC&lt;/span&gt;
            &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;
                &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Ansible makes deploying your infrastructure easier and it's best when used as intended, Don't over complicate it, start simple and with time you would discover what structure works best for your organization.&lt;/p&gt;

&lt;p&gt;Thank you for reading, I hope you learned a lot already. I'm Azeez Lukman and here's a developer's journey building something awesome every day. Please let's meet on Twitter, LinkedIn, GitHub and anywhere else @robogeeek95&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>cloud</category>
      <category>beginners</category>
      <category>introduction</category>
    </item>
  </channel>
</rss>
