<?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: AF uarabei</title>
    <description>The latest articles on DEV Community by AF uarabei (@af).</description>
    <link>https://dev.to/af</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%2F557880%2F0ee6af06-f5f4-420d-a3c4-6b178ecd1b8c.jpeg</url>
      <title>DEV Community: AF uarabei</title>
      <link>https://dev.to/af</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/af"/>
    <language>en</language>
    <item>
      <title>GCP CI/CD Pipeline: Build Docker images after commits to a repo branch (Google Cloud Source Repositories)</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Fri, 23 Sep 2022 18:09:40 +0000</pubDate>
      <link>https://dev.to/af/gcp-cicd-pipeline-build-docker-images-after-commits-to-a-repo-branch-google-cloud-source-repositories-500o</link>
      <guid>https://dev.to/af/gcp-cicd-pipeline-build-docker-images-after-commits-to-a-repo-branch-google-cloud-source-repositories-500o</guid>
      <description>&lt;p&gt;In this article we will learn how to connect GCP's code versioning service (&lt;a href="https://cloud.google.com/source-repositories/docs/create-code-repository#:~:text=Cloud%20Source%20Repositories%20are%20private,version%20control%20for%20your%20code." rel="noopener noreferrer"&gt;Cloud Source Repositories&lt;/a&gt;) to &lt;a href="https://cloud.google.com/build" rel="noopener noreferrer"&gt;Cloud Build&lt;/a&gt; to automate building Docker images and pushing them to &lt;a href="https://cloud.google.com/container-registry" rel="noopener noreferrer"&gt;GCP Container Registry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cloud and containers have truly revolutionized deployment and management of web infrastructure. Ability to build docker images triggered by a push or a pull request allows developers focus more on code and less on infrastructure.&lt;/p&gt;

&lt;p&gt;The process of setting up this pipeline will follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a repository in Cloud Source Repositories&lt;/li&gt;
&lt;li&gt;Push source code files to our repo&lt;/li&gt;
&lt;li&gt;Create a trigger in Cloud Build service&lt;/li&gt;
&lt;li&gt;Set trigger to build a Docker image when there is a new commit to the specified branch&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Creating a repository in Cloud Source Repositories
&lt;/h3&gt;

&lt;p&gt;Navigate to Cloud Source Repositories using sidebar or a search bar at the top.&lt;/p&gt;

&lt;p&gt;Verify that you are creating your repository in the correct project and then click &lt;code&gt;Add repository&lt;/code&gt; button in the top right corner:&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%2Fjb0vaejhklw6v3oopvtw.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%2Fjb0vaejhklw6v3oopvtw.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Creating a Cloud Source Repository pt1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we will be using GCP's version control we need to select &lt;code&gt;Create new repository&lt;/code&gt; option and click &lt;code&gt;Continue&lt;/code&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%2Fvt0jc2fnq6naojpzs4uz.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%2Fvt0jc2fnq6naojpzs4uz.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Creating a Cloud Source Repository  pt2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we will need to enter the name of our repo and select the project. Click &lt;code&gt;Create&lt;/code&gt; button after you are done:&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%2Fmmxrdtkerfniz3d59ynk.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%2Fmmxrdtkerfniz3d59ynk.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Creating a Cloud Source Repository  pt3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the final step we will clone our newly created repository to our local machine using the instructions provided:&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%2Fwz2sxk01a7c2ksr5v0o6.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%2Fwz2sxk01a7c2ksr5v0o6.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Creating a Cloud Source Repository  pt4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can upload your code to the repo using either SSH (1st option) or using gcloud CLI. I will let reader decide which option to use. &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Source files
&lt;/h3&gt;

&lt;p&gt;For this project we will have 2 sources files:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;:&lt;/p&gt;

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

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.7-slim&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;flask
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /myapp&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; main.py /myapp/main.py&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "/myapp/main.py"]&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;:&lt;/p&gt;

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

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CI/CD pipeline with GCP Cloud Source Repositories and Docker&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Following the instructions push these files to the repo and verify that they are uploaded:&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%2Fvqurv4gwkhe169qk1l50.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%2Fvqurv4gwkhe169qk1l50.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Setting up repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Creating a Cloud Build trigger
&lt;/h3&gt;

&lt;p&gt;If you are using Cloud Build for the first time you will be asked to enable the API first. Click &lt;code&gt;Enable&lt;/code&gt; to activate this API. It might take a minute, it is normal.&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Triggers&lt;/code&gt; in the sidebar:&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%2Fh2pawhrbphq71zos8rx0.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%2Fh2pawhrbphq71zos8rx0.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Creating a build trigger pt1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create a new trigger click on the &lt;code&gt;Create new trigger&lt;/code&gt; button at the bottom of the page:&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%2Fbslq8l29axwo7pqpzil6.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%2Fbslq8l29axwo7pqpzil6.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Creating a build trigger pt2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the trigger creation page we will need to pay attention to 4 important parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Trigger name&lt;/li&gt;
&lt;li&gt;Event that will trigger the action (I left it as default &lt;code&gt;Push to a branch&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Source repository (click on the dropdown and select your repo and the branch that this trigger will monitor)&lt;/li&gt;
&lt;li&gt;Configuration type (select &lt;code&gt;Dockerfile&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After you are done click &lt;code&gt;Create&lt;/code&gt; to finish setting up the trigger.&lt;/p&gt;

&lt;p&gt;To test our trigger we will first invoke it manually by clicking &lt;code&gt;RUN&lt;/code&gt; button:&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%2Fhqmhqqp5vrdxcnb640ix.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%2Fhqmhqqp5vrdxcnb640ix.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Running the trigger manually pt1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A popup will appear asking for confirmation. Click &lt;code&gt;Run trigger&lt;/code&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%2Fsznydklipa8qg0j24qzf.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%2Fsznydklipa8qg0j24qzf.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Running the trigger manually pt2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we click the &lt;code&gt;History&lt;/code&gt; option in the sidebar on the left we can see the build history:&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%2Fw50aj9d967wnoldhenwi.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%2Fw50aj9d967wnoldhenwi.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Running the trigger manually pt3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My build has succeeded:&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%2Fbo1frsj26xau60jnmos5.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%2Fbo1frsj26xau60jnmos5.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Running the trigger manually pt4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  4. Verifying that Dockerimage is built automatically
&lt;/h3&gt;

&lt;p&gt;GCP has a service for storing container image called Container Registry.&lt;/p&gt;

&lt;p&gt;Navigate to Contianer Registry and you should see your image there:&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%2Fpo0piakta586y41vrkmm.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%2Fpo0piakta586y41vrkmm.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Docker image from manual trigger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And finally, lets do a test with a test push. Let's modify our &lt;code&gt;main.py&lt;/code&gt; file and push changes to the repository. I modified the text a little and added &lt;code&gt;v2.0&lt;/code&gt;:&lt;/p&gt;

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

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CI/CD pipeline with GCP Cloud Source Repositories and Docker v2.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Commit and push new changes to the repo. It should run the trigger automatically. You should see a running process in the History tab (mine completed really fast):&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%2Fnqqw2awahhgjnjnytf6r.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%2Fnqqw2awahhgjnjnytf6r.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Docker image from automated trigger pt1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's go to the container registry and verify that the new image there:&lt;br&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%2Fz3gz007m191p74mscgdg.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%2Fz3gz007m191p74mscgdg.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Docker image from automated trigger pt2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There will be two images, one from running the trigger manually and the second one from pushing code to the tracked branch.&lt;br&gt;
And yes, as we can see the new image is there!&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%2Fyabk3fcxzfs5cxvolem4.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%2Fyabk3fcxzfs5cxvolem4.png" alt="GCP CI/CD Pipeline for Docker images with Cloud Source Repositories. Docker image from automated trigger pt3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;That's it. You have created a CI/CD pipeline that builds a Docker image when new code is committed to the tracked branch!&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>cloud</category>
      <category>cicd</category>
      <category>docker</category>
    </item>
    <item>
      <title>GCP CI/CD Pipeline: Build Docker images after commits to a repo branch (Github)</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Fri, 23 Sep 2022 18:08:59 +0000</pubDate>
      <link>https://dev.to/af/gcp-cicd-pipeline-build-docker-images-after-commits-to-a-repo-branch-github-3381</link>
      <guid>https://dev.to/af/gcp-cicd-pipeline-build-docker-images-after-commits-to-a-repo-branch-github-3381</guid>
      <description>&lt;p&gt;In this article we will learn how to create a CI/CD pipeline on GCP using Cloud Build, Github, and Docker.&lt;/p&gt;

&lt;p&gt;For this article I will be using this &lt;a href="https://github.com/periwinkleFTW/cicd-blog-gcp-cb-docker"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a trigger
&lt;/h3&gt;

&lt;p&gt;First we would need to navigate to Code Build. Select the &lt;code&gt;Triggers&lt;/code&gt; tab in the sidebar and &lt;code&gt;Create Trigger&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F90xh3k3oxrn74d2dflfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F90xh3k3oxrn74d2dflfz.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Creating a trigger pt1" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the name of your trigger and select &lt;code&gt;Connect new repository&lt;/code&gt; in the Source section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feujagwuklm05jls99rwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feujagwuklm05jls99rwl.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Attaching Github repository to Cloud Build pt1" width="800" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see a sidebar that will appear on the right hand side with different options for repositories supported by Cloud Build. I am using Github, so I selected the first option. Click &lt;code&gt;Continue&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxu55e2mp77ultri3cs2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxu55e2mp77ultri3cs2s.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Attaching Github repository to Cloud Build pt2" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be asked to authorize Cloud Build to access your github account and repositories:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlwvhanuwhfod85kzbo7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlwvhanuwhfod85kzbo7.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Attaching Github repository to Cloud Build pt3" width="800" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select your github account and repository for this trigger:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8n7mmj7zwp0pvwrpu7ns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8n7mmj7zwp0pvwrpu7ns.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Attaching Github repository to Cloud Build pt4" width="800" height="1034"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then select the &lt;code&gt;Dockerfile&lt;/code&gt; in the Configuration section and hit Create at the bottom of the page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhiqfhttebvjw4qjvf8mc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhiqfhttebvjw4qjvf8mc.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Creating a trigger pt2" width="800" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see your newly created trigger with the connected repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0x29x53bwvgj7jpl2s7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0x29x53bwvgj7jpl2s7.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Creating a trigger pt3" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Run trigger manually
&lt;/h3&gt;

&lt;p&gt;Let's test our trigger by running it manually first.&lt;br&gt;
Next to your trigger there is a button &lt;code&gt;RUN&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52vhur7wah14jcoax17k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52vhur7wah14jcoax17k.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Running trigger manually pt1" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A sidebar will popup on the right hand side asking you to confirm the details of deployment. Press &lt;code&gt;Run Trigger&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8wi1ou68zuuuqdqx88f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8wi1ou68zuuuqdqx88f.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Running trigger manually pt2" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can see the new image in the Container Registry. Mine is called &lt;code&gt;github.com&lt;/code&gt;. But it is there. The trigger is working!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5ngicdzonnp995gtd46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5ngicdzonnp995gtd46.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Running trigger manually pt3" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpnqbay2mi1uc41cywsp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpnqbay2mi1uc41cywsp9.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Running trigger manually pt4" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Run trigger automatically
&lt;/h3&gt;

&lt;p&gt;And finally, let's push new code to the repository and test the trigger for automatic build.&lt;/p&gt;

&lt;p&gt;I will let reader do the code pushing. &lt;/p&gt;

&lt;p&gt;If you want to see current or past builds, Code Build has a section called &lt;code&gt;History&lt;/code&gt; in the sidebar on the left. It is a great to monitor builds.&lt;/p&gt;

&lt;p&gt;When I pushed new code to my repository a new build was triggered right away and it appeared in the &lt;code&gt;History&lt;/code&gt; section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hryuj5esvbq71120jye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hryuj5esvbq71120jye.png" alt="GCP CI/CD pipeline using Code Build, Docker, and Github. Running trigger automatically pt4" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;That's it! Thank you for reading.&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>cloud</category>
      <category>cicd</category>
      <category>docker</category>
    </item>
    <item>
      <title>Terraform: My experience taking the exam</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Thu, 21 Jul 2022 03:31:37 +0000</pubDate>
      <link>https://dev.to/af/terraform-my-experience-taking-the-exam-49oj</link>
      <guid>https://dev.to/af/terraform-my-experience-taking-the-exam-49oj</guid>
      <description>&lt;p&gt;After writing several articles about Terraform I finally felt prepared I took the exam. I am glad that I passed that I passed. Now I am a certified Terraform Associate.&lt;/p&gt;

&lt;p&gt;In this final chapter of the series I will tell you about the exam and what I think about it.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Registration
&lt;/h3&gt;

&lt;p&gt;Registration for the exam is available on &lt;a href="https://www.hashicorp.com/certification/terraform-associate"&gt;this page&lt;/a&gt;. Weird thing about the portal is that it required a Github account. The unfortunate part is that my Github email is different from my personal email tied to Credly where I have all of my certification badges. If you are like me and prefer to have your Credly badges in one place make sure to register a Github account for that email and use it for registering for the exam.&lt;/p&gt;

&lt;p&gt;Registration itself is straight forward. You pay $70.50USD and select date and time using PSI portal. After registration you will get an email with required links and you are all set.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Before the Exam
&lt;/h3&gt;

&lt;p&gt;PSI would allow you to access the exam page 30 minutes prior to the exam. In this time you would need to download PSI secure browser which is about 180MB so make sure your internet connection allows for timely. Then you would need to install it and grant the necessary permissions like screen recording, access to camera and microphone.&lt;/p&gt;

&lt;p&gt;When you launch PSI browser it will run a check and ask you to close applications that PSI does not allow during exam. For me it asked to close other Browsers and Ipad mirroring service (I didn't even know I had such process running in the background). Closing all those apps will pass the PSI browser checks and you will be presented with the next task.&lt;/p&gt;

&lt;p&gt;The browser will ask you to take a picture of your government issued ID and taking sweeping videos of your sitting area (horizontal and vertical).&lt;/p&gt;

&lt;p&gt;Once you are done with that you will be connected to the proctor with a new chat window. The proctor will verify your name and the sitting area. He may ask you to show him the table and/or ask you to remove certain items. If he is happy with what he sees he will start the exam. &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Exam
&lt;/h3&gt;

&lt;p&gt;The exam is 1 hour long and mine had 57 questions in it. All questions were multiple choice and some True/False questions here and there. I was done in about 30 minutes.&lt;/p&gt;

&lt;p&gt;After you submit your answers you will be given the result right away.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Thoughts about questions
&lt;/h3&gt;

&lt;p&gt;I passed with a score of 86%. I think I could have done better, but a pass is a pass.&lt;/p&gt;

&lt;p&gt;I covered most of the topics for this exam in the series, though some questions threw me off.&lt;/p&gt;

&lt;p&gt;This is the list of topics I wish I covered more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built-in functions&lt;/li&gt;
&lt;li&gt;CLI commands and available options/flags&lt;/li&gt;
&lt;li&gt;Workspaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are using this series as a prep for the exam, I would recommend going through &lt;a href="https://learn.hashicorp.com/collections/terraform/certification-associate-tutorials"&gt;official study guide with tutorials&lt;/a&gt; to make sure you cover all the bases.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

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

&lt;p&gt;This wraps up this series. I hope you learned something. Good luck!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Terraform Cloud with VCS Workflow(Github)</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Sun, 17 Jul 2022 21:22:51 +0000</pubDate>
      <link>https://dev.to/af/terraform-cloud-with-vcs-github-integration-1fjj</link>
      <guid>https://dev.to/af/terraform-cloud-with-vcs-github-integration-1fjj</guid>
      <description>&lt;p&gt;VSC integrations are a popular and, quite frankly, a useful tool that allow collaboration between many people. In this article we will learn how to add a Github integration to our Terraform Cloud.&lt;/p&gt;

&lt;p&gt;It is assumed that you already have a Terraform Cloud account and an organization.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Select your organization and click 'Setting' tab:&lt;br&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%2Fgr169oednfgwlogl5a7w.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%2Fgr169oednfgwlogl5a7w.png" alt="Adding Github integration to Terraform Cloud pt1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;There will be a button 'Connect to version control':&lt;br&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%2Fgu0bj72mh1osqu5qikin.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%2Fgu0bj72mh1osqu5qikin.png" alt="Adding Github integration to Terraform Cloud pt2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;You will be presented with 3 options for your workflow. We are interested in 'Version Control Workflow':&lt;br&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%2F25lg09a9hov7q2dns5z4.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%2F25lg09a9hov7q2dns5z4.png" alt="Adding Github integration to Terraform Cloud pt3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I am interested in Github and that's what I will select:&lt;br&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%2Fequ50h2gqhbfi5amkaxd.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%2Fequ50h2gqhbfi5amkaxd.png" alt="Adding Github integration to Terraform Cloud pt4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;After selecting your VCS provider you will see a popup asking you to grant permissions to Terraform Cloud to access your Github. Click 'Authorize Terraform Cloud':&lt;br&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%2Fs6u9yhy0l2li6gg9qjg5.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%2Fs6u9yhy0l2li6gg9qjg5.png" alt="Adding Github integration to Terraform Cloud pt5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;If everything went well you will see a list of your repositories. &lt;br&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%2Fleutr7bfh7343mgq2g2y.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%2Fleutr7bfh7343mgq2g2y.png" alt="Adding Github integration to Terraform Cloud pt6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I will select the repo that used for this blog series:&lt;br&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%2Fnwox2vxueudzpc4x5686.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%2Fnwox2vxueudzpc4x5686.png" alt="Adding Github integration to Terraform Cloud pt7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Then we will be redirected to a settings confirmation page. Important fields here are the 'Apply Method' and 'VSC Branch'. Once you have confirmed the settings click 'Update VSC settings' button at the bottom of the page:&lt;br&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%2Fg9r7vsz7j5kvgfy8iszw.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%2Fg9r7vsz7j5kvgfy8iszw.png" alt="Adding Github integration to Terraform Cloud pt8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;After that you will a green success message text:&lt;br&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%2Fbfnumhwr28cnvpyay86m.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%2Fbfnumhwr28cnvpyay86m.png" alt="Adding Github integration to Terraform Cloud pt9"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This is it. You have now connected your Github account to Terraform Cloud! &lt;br&gt;
Thank you for reading and see you in the next article!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Terraform State Migration and State Refresh</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Thu, 14 Jul 2022 05:58:54 +0000</pubDate>
      <link>https://dev.to/af/terraform-state-migration-and-state-refresh-5gha</link>
      <guid>https://dev.to/af/terraform-state-migration-and-state-refresh-5gha</guid>
      <description>&lt;h2&gt;
  
  
  Terraform state migration
&lt;/h2&gt;

&lt;p&gt;We have learned a lot about Terraform's backend and its features. But there is one important topic that is usually skipped by new learners. This topic is state migration.&lt;/p&gt;

&lt;p&gt;There are many reasons why you may have a need to migrate your state: moving to cloud, switching cloud providers, centralizing state management, and many others.&lt;/p&gt;

&lt;p&gt;Luckily, Terraform developers thought about this issue and provided us with tools to make this process manageable. &lt;/p&gt;

&lt;p&gt;Code for this article can be found &lt;a href="https://github.com/periwinkleFTW/terraform-path-to-cert/tree/master/practice-pt-6" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We will start with a local backend and then migrate to AWS S3 backend. &lt;/p&gt;

&lt;p&gt;First let's create a configuration with a local backend in &lt;code&gt;terraform.tf&lt;/code&gt;:&lt;/p&gt;

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

&lt;span class="c1"&gt;# terraform.tf&lt;/span&gt;

&lt;span class="c1"&gt;# Local backend&lt;/span&gt;
&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# Provider-specific settings&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 2.7.0"&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;# Terraform version&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 0.14.9"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Reinitialize the backend, validate, plan, and apply:&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;$ &lt;/span&gt;terraform init
&lt;span class="c"&gt;# output&lt;/span&gt;
Terraform has been successfully initialized!

&lt;span class="nv"&gt;$ &lt;/span&gt;terraform validate
&lt;span class="c"&gt;# output&lt;/span&gt;
Success! The configuration is valid.

&lt;span class="nv"&gt;$ &lt;/span&gt;terraform plan
&lt;span class="c"&gt;# output&lt;/span&gt;
Plan: 25 to add, 0 to change, 0 to destroy.

&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply
&lt;span class="c"&gt;# output&lt;/span&gt;
Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 25 added, 0 changed, 0 destroyed.


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Verify that resources have been deployed using a &lt;code&gt;state list&lt;/code&gt; command:&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;$ &lt;/span&gt;terraform state list
&lt;span class="c"&gt;# output&lt;/span&gt;
data.aws_ami.ubuntu
data.aws_availability_zones.available
data.aws_region.current
aws_eip.nat_gateway_eip
aws_internet_gateway.internet_gateway
aws_nat_gateway.nat_gateway
aws_route_table.private_route_table
aws_route_table.public_route_table
aws_route_table_association.private
aws_route_table_association.public
aws_security_group.private_sg
aws_security_group.public_sg
aws_security_group_rule.private_in
aws_security_group_rule.private_out
aws_security_group_rule.public_http_in
aws_security_group_rule.public_https_in
aws_security_group_rule.public_out
aws_security_group_rule.public_ssh_in
aws_subnet.private_subnet
aws_subnet.public_subnet
aws_vpc.vpc
module._server_from_local_module.data.aws_ami.ubuntu
module._server_from_local_module.aws_instance.web_server
module.another_server_from_a_module.data.aws_ami.ubuntu
module.another_server_from_a_module.aws_instance.web_server
module.autoscaling_from_github.data.aws_default_tags.current
module.autoscaling_from_github.data.aws_partition.current
module.autoscaling_from_github.aws_autoscaling_group.this[0]
module.autoscaling_from_github.aws_launch_template.this[0]
module.autoscaling_from_registry.data.aws_default_tags.current
module.autoscaling_from_registry.data.aws_partition.current
module.autoscaling_from_registry.aws_autoscaling_group.this[0]
module.autoscaling_from_registry.aws_launch_template.this[0]
module.my_server_module.data.aws_ami.ubuntu
module.my_server_module.aws_instance.web_server


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We know that our local backend works and we can now learn how to migrate our state to an S3 bucket on AWS.&lt;/p&gt;

&lt;p&gt;Details on how to create an S3 bucket and a DynamoDB table can be found in &lt;a href="https://dev.to/af/terraform-standard-backends-s3-with-versioning-and-state-locking-with-dynamodb-1ng7"&gt;this article&lt;/a&gt;. You will need these values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 bucket name&lt;/li&gt;
&lt;li&gt;DynamoDB table name&lt;/li&gt;
&lt;li&gt;Your region&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Backend settings are inside the &lt;code&gt;terraform.tf&lt;/code&gt; file and we need to modify it to let Terraform know about new backend. I commented out the local backend for demonstration purposes:&lt;/p&gt;

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

&lt;span class="c1"&gt;# terraform.tf&lt;/span&gt;

&lt;span class="c1"&gt;# Local backend&lt;/span&gt;
&lt;span class="c1"&gt;# terraform {&lt;/span&gt;
&lt;span class="c1"&gt;#   # Provider-specific settings&lt;/span&gt;
&lt;span class="c1"&gt;#   required_providers {&lt;/span&gt;
&lt;span class="c1"&gt;#     aws = {&lt;/span&gt;
&lt;span class="c1"&gt;#       version = "&amp;gt;= 2.7.0"&lt;/span&gt;
&lt;span class="c1"&gt;#       source  = "hashicorp/aws"&lt;/span&gt;
&lt;span class="c1"&gt;#     }&lt;/span&gt;
&lt;span class="c1"&gt;#   }&lt;/span&gt;
&lt;span class="c1"&gt;#   # Terraform version&lt;/span&gt;
&lt;span class="c1"&gt;#   required_version = "&amp;gt;= 0.14.9"&lt;/span&gt;
&lt;span class="c1"&gt;# }&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bucket&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-state-migration"&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev/aws_infrastructure"&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ca-central-1"&lt;/span&gt;
    &lt;span class="nx"&gt;dynamodb_table&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tf-state-mig"&lt;/span&gt;
    &lt;span class="nx"&gt;encrypt&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;# Provider-specific settings&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 2.7.0"&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;# Terraform version&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 0.14.9"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;All that is left to do is migrate our backend to S3:&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;$ &lt;/span&gt;terraform init &lt;span class="nt"&gt;-migrate-state&lt;/span&gt;
&lt;span class="c"&gt;# output&lt;/span&gt;
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;span class="nb"&gt;yes


&lt;/span&gt;Successfully configured the backend &lt;span class="s2"&gt;"s3"&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v4.18.0

Terraform has been successfully initialized!

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

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


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Let's check if the resources are still there:&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;$ &lt;/span&gt;terraform state list
&lt;span class="c"&gt;# output&lt;/span&gt;
data.aws_ami.ubuntu
data.aws_availability_zones.available
data.aws_region.current
aws_eip.nat_gateway_eip
aws_internet_gateway.internet_gateway
aws_nat_gateway.nat_gateway
aws_route_table.private_route_table
aws_route_table.public_route_table
aws_route_table_association.private
aws_route_table_association.public
aws_security_group.private_sg
aws_security_group.public_sg
aws_security_group_rule.private_in
aws_security_group_rule.private_out
aws_security_group_rule.public_http_in
aws_security_group_rule.public_https_in
aws_security_group_rule.public_out
aws_security_group_rule.public_ssh_in
aws_subnet.private_subnet
aws_subnet.public_subnet
aws_vpc.vpc
module._server_from_local_module.data.aws_ami.ubuntu
module._server_from_local_module.aws_instance.web_server
module.another_server_from_a_module.data.aws_ami.ubuntu
module.another_server_from_a_module.aws_instance.web_server
module.autoscaling_from_github.data.aws_default_tags.current
module.autoscaling_from_github.data.aws_partition.current
module.autoscaling_from_github.aws_autoscaling_group.this[0]
module.autoscaling_from_github.aws_launch_template.this[0]
module.autoscaling_from_registry.data.aws_default_tags.current
module.autoscaling_from_registry.data.aws_partition.current
module.autoscaling_from_registry.aws_autoscaling_group.this[0]
module.autoscaling_from_registry.aws_launch_template.this[0]
module.my_server_module.data.aws_ami.ubuntu
module.my_server_module.aws_instance.web_server


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We can also check our bucket to see if the state file was created there:&lt;br&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%2Fhtjacfednafm2dlguguc.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%2Fhtjacfednafm2dlguguc.png" alt="Terraform migrating local state to S3 bucket and DynamoDB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We already covered the benefits of storing backend remotely and how it is often the best choice when there are many people working on infrastructure and they need to collaborate.&lt;/p&gt;

&lt;p&gt;Congratulation! You have just migrated your backend from a local machine to a remote location. This is a valuable skill because most of the time you would start working on a new project locally and migrate it to a remote backend afterwards. Now you know how to do it.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Let's migrate our remote backend back to our local machine.&lt;/p&gt;

&lt;p&gt;This is relatively easy. All we need to do is delete the &lt;code&gt;backend&lt;/code&gt; block from the Terraform settings and force Terraform to fall back to the default local backend.&lt;/p&gt;

&lt;p&gt;This is the modified &lt;code&gt;terraform.tf&lt;/code&gt; file:&lt;/p&gt;

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

&lt;span class="c1"&gt;# terraform.tf&lt;/span&gt;

&lt;span class="c1"&gt;# Local backend&lt;/span&gt;
&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# Provider-specific settings&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 2.7.0"&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;# Terraform version&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 0.14.9"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We will go through the same steps as before. Validate, initialize with &lt;code&gt;-migrate-state&lt;/code&gt; flag, check &lt;code&gt;state list&lt;/code&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;$ &lt;/span&gt;terraform validate
&lt;span class="c"&gt;# output&lt;/span&gt;
Success! The configuration is valid.

&lt;span class="nv"&gt;$ &lt;/span&gt;terraform init &lt;span class="nt"&gt;-migrate-state&lt;/span&gt;
Initializing modules...

Initializing the backend...
Terraform has detected you&lt;span class="s1"&gt;'re unconfiguring your previously set "s3" backend.
Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "s3" backend to the
  newly configured "local" backend. No existing state was found in the newly
  configured "local" backend. Do you want to copy this state to the new "local"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes



Successfully unset the backend "s3". Terraform will now operate locally.

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v4.18.0

Terraform has been successfully initialized!

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

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


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Let's check the state list:&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;$ &lt;/span&gt;terraform state list
&lt;span class="c"&gt;# output with list of resources...&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Finally, let's destroy our resources:&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;$ &lt;/span&gt;terraform destroy
&lt;span class="c"&gt;# output&lt;/span&gt;
Destroy &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 25 destroyed.


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This is it. We migrated our backend to an S3 bucket from local machine and back. Give yourself a round of applause!&lt;/p&gt;

&lt;p&gt;Terraform makes it really easy to migrate your state file wherever you need and I absolutely love this feature.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform state refresh
&lt;/h2&gt;

&lt;p&gt;When you run &lt;code&gt;terraform refresh&lt;/code&gt; Terraform reads the settings of all existing resources belonging to the current configuration and updates Terraform state to ensure that things match. This command only modifies the state. Refresh is run automatically as a part of &lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;This command is useful to deal with what is known as configuration drift. There are instances when we need to go and modify an existing resource. With &lt;code&gt;terraform refresh&lt;/code&gt; we can let Terraform know about these changes and prevent configuration drift where the settings of remote resources differ from the Terraform configuration.&lt;/p&gt;

&lt;p&gt;To demonstrate how this command works we will intentionally introduce a configuration drift by modifying a tag of an EC2 instance manually. Then we will run the &lt;code&gt;refresh&lt;/code&gt; command and let Terraform state be in sync with the real configuration of our resources.&lt;/p&gt;

&lt;p&gt;If your configuration is not up run the &lt;code&gt;apply&lt;/code&gt; command:&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;$ &lt;/span&gt;terraform apply


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Let's see the state list and select an instance to modify:&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;$ &lt;/span&gt;terraform state list
&lt;span class="c"&gt;# output&lt;/span&gt;
data.aws_ami.ubuntu
data.aws_availability_zones.available
data.aws_region.current
aws_eip.nat_gateway_eip
aws_internet_gateway.internet_gateway
aws_nat_gateway.nat_gateway
aws_route_table.private_route_table
aws_route_table.public_route_table
aws_route_table_association.private
aws_route_table_association.public
aws_security_group.private_sg
aws_security_group.public_sg
aws_security_group_rule.private_in
aws_security_group_rule.private_out
aws_security_group_rule.public_http_in
aws_security_group_rule.public_https_in
aws_security_group_rule.public_out
aws_security_group_rule.public_ssh_in
aws_subnet.private_subnet
aws_subnet.public_subnet
aws_vpc.vpc
module._server_from_local_module.data.aws_ami.ubuntu
module._server_from_local_module.aws_instance.web_server
module.another_server_from_a_module.data.aws_ami.ubuntu
module.another_server_from_a_module.aws_instance.web_server
module.autoscaling_from_github.data.aws_default_tags.current
module.autoscaling_from_github.data.aws_partition.current
module.autoscaling_from_github.aws_autoscaling_group.this[0]
module.autoscaling_from_github.aws_launch_template.this[0]
module.autoscaling_from_registry.data.aws_default_tags.current
module.autoscaling_from_registry.data.aws_partition.current
module.autoscaling_from_registry.aws_autoscaling_group.this[0]
module.autoscaling_from_registry.aws_launch_template.this[0]
module.my_server_module.data.aws_ami.ubuntu
module.my_server_module.aws_instance.web_server


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

&lt;/div&gt;

&lt;p&gt;I chose &lt;code&gt;module.my_server_module.aws_instance.web_server&lt;/code&gt;. Let's see what kind of data Terraform state has on this instance:&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;$ &lt;/span&gt;terraform state show module.my_server_module.aws_instance.web_server

&lt;span class="c"&gt;# output&lt;/span&gt;

&lt;span class="c"&gt;# module.my_server_module.aws_instance.web_server:&lt;/span&gt;
resource &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web_server"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    ami                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-04a579d2f00bb4001"&lt;/span&gt;
    arn                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:ec2:ca-central-1:490750479946:instance/i-0d09c23db0e4dbb51"&lt;/span&gt;
    associate_public_ip_address          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true
    &lt;/span&gt;availability_zone                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ca-central-1a"&lt;/span&gt;
    cpu_core_count                       &lt;span class="o"&gt;=&lt;/span&gt; 1
    cpu_threads_per_core                 &lt;span class="o"&gt;=&lt;/span&gt; 1
    disable_api_termination              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;ebs_optimized                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;get_password_data                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;hibernation                          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    id&lt;/span&gt;                                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"i-0d09c23db0e4dbb51"&lt;/span&gt;
    instance_initiated_shutdown_behavior &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"stop"&lt;/span&gt;
    instance_state                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"running"&lt;/span&gt;
    instance_type                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
    ipv6_address_count                   &lt;span class="o"&gt;=&lt;/span&gt; 0
    ipv6_addresses                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    monitoring                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;primary_network_interface_id         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eni-01fef74a6aff22cac"&lt;/span&gt;
    private_dns                          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ip-10-0-0-224.ca-central-1.compute.internal"&lt;/span&gt;
    private_ip                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.224"&lt;/span&gt;
    public_ip                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3.97.16.128"&lt;/span&gt;
    secondary_private_ips                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    security_groups                      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    source_dest_check                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true
    &lt;/span&gt;subnet_id                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"subnet-0f1f35c97902550da"&lt;/span&gt;
    tags                                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Web Server from module"&lt;/span&gt;
        &lt;span class="s2"&gt;"Terraform"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    tags_all                             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Web Server from module"&lt;/span&gt;
        &lt;span class="s2"&gt;"Terraform"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    tenancy                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;
    user_data_replace_on_change          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;vpc_security_group_ids               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"sg-08fc17f9b71be12fd"&lt;/span&gt;,
    &lt;span class="o"&gt;]&lt;/span&gt;

    capacity_reservation_specification &lt;span class="o"&gt;{&lt;/span&gt;
        capacity_reservation_preference &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"open"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    credit_specification &lt;span class="o"&gt;{&lt;/span&gt;
        cpu_credits &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"standard"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    enclave_options &lt;span class="o"&gt;{&lt;/span&gt;
        enabled &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    maintenance_options &lt;span class="o"&gt;{&lt;/span&gt;
        auto_recovery &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    metadata_options &lt;span class="o"&gt;{&lt;/span&gt;
        http_endpoint               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"enabled"&lt;/span&gt;
        http_put_response_hop_limit &lt;span class="o"&gt;=&lt;/span&gt; 1
        http_tokens                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"optional"&lt;/span&gt;
        instance_metadata_tags      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"disabled"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    root_block_device &lt;span class="o"&gt;{&lt;/span&gt;
        delete_on_termination &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true
        &lt;/span&gt;device_name           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/dev/sda1"&lt;/span&gt;
        encrypted             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
        &lt;/span&gt;iops                  &lt;span class="o"&gt;=&lt;/span&gt; 100
        tags                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
        throughput            &lt;span class="o"&gt;=&lt;/span&gt; 0
        volume_id             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vol-04f7e86e0d3cdcd7a"&lt;/span&gt;
        volume_size           &lt;span class="o"&gt;=&lt;/span&gt; 8
        volume_type           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"gp2"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;I will introduce drift by adding a tag to this instance:&lt;br&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%2Fahqs8fvl6mevdp5jo6iu.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%2Fahqs8fvl6mevdp5jo6iu.png" alt="Terraform state refresh"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Now we run the refresh command:&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;$ &lt;/span&gt;terraform refresh


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

&lt;/div&gt;

&lt;p&gt;If we check the data about this instance we can see that name (look at &lt;code&gt;tags&lt;/code&gt; and &lt;code&gt;tags_all&lt;/code&gt;) was updated to &lt;code&gt;refresh-demo&lt;/code&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;$ &lt;/span&gt;terraform state show
module.my_server_module.aws_instance.web_server

&lt;span class="c"&gt;# output&lt;/span&gt;
&lt;span class="c"&gt;# module.my_server_module.aws_instance.web_server:&lt;/span&gt;
resource &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web_server"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    ami                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-04a579d2f00bb4001"&lt;/span&gt;
    arn                                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:ec2:ca-central-1:490750479946:instance/i-0d09c23db0e4dbb51"&lt;/span&gt;
    associate_public_ip_address          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true
    &lt;/span&gt;availability_zone                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ca-central-1a"&lt;/span&gt;
    cpu_core_count                       &lt;span class="o"&gt;=&lt;/span&gt; 1
    cpu_threads_per_core                 &lt;span class="o"&gt;=&lt;/span&gt; 1
    disable_api_termination              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;ebs_optimized                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;get_password_data                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;hibernation                          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    id&lt;/span&gt;                                   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"i-0d09c23db0e4dbb51"&lt;/span&gt;
    instance_initiated_shutdown_behavior &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"stop"&lt;/span&gt;
    instance_state                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"running"&lt;/span&gt;
    instance_type                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
    ipv6_address_count                   &lt;span class="o"&gt;=&lt;/span&gt; 0
    ipv6_addresses                       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    monitoring                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;primary_network_interface_id         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eni-01fef74a6aff22cac"&lt;/span&gt;
    private_dns                          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ip-10-0-0-224.ca-central-1.compute.internal"&lt;/span&gt;
    private_ip                           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.224"&lt;/span&gt;
    public_ip                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3.97.16.128"&lt;/span&gt;
    secondary_private_ips                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    security_groups                      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    source_dest_check                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true
    &lt;/span&gt;subnet_id                            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"subnet-0f1f35c97902550da"&lt;/span&gt;
    tags                                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"refresh-demo"&lt;/span&gt;
        &lt;span class="s2"&gt;"Terraform"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    tags_all                             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"refresh-demo"&lt;/span&gt;
        &lt;span class="s2"&gt;"Terraform"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    tenancy                              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;
    user_data_replace_on_change          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
    &lt;/span&gt;vpc_security_group_ids               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"sg-08fc17f9b71be12fd"&lt;/span&gt;,
    &lt;span class="o"&gt;]&lt;/span&gt;

    capacity_reservation_specification &lt;span class="o"&gt;{&lt;/span&gt;
        capacity_reservation_preference &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"open"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    credit_specification &lt;span class="o"&gt;{&lt;/span&gt;
        cpu_credits &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"standard"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    enclave_options &lt;span class="o"&gt;{&lt;/span&gt;
        enabled &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    maintenance_options &lt;span class="o"&gt;{&lt;/span&gt;
        auto_recovery &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    metadata_options &lt;span class="o"&gt;{&lt;/span&gt;
        http_endpoint               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"enabled"&lt;/span&gt;
        http_put_response_hop_limit &lt;span class="o"&gt;=&lt;/span&gt; 1
        http_tokens                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"optional"&lt;/span&gt;
        instance_metadata_tags      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"disabled"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    root_block_device &lt;span class="o"&gt;{&lt;/span&gt;
        delete_on_termination &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true
        &lt;/span&gt;device_name           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/dev/sda1"&lt;/span&gt;
        encrypted             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
        &lt;/span&gt;iops                  &lt;span class="o"&gt;=&lt;/span&gt; 100
        tags                  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
        throughput            &lt;span class="o"&gt;=&lt;/span&gt; 0
        volume_id             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vol-04f7e86e0d3cdcd7a"&lt;/span&gt;
        volume_size           &lt;span class="o"&gt;=&lt;/span&gt; 8
        volume_type           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"gp2"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Lastly, I will destroy the infrastructure because I have no use for it anymore:&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;$ &lt;/span&gt;terraform destroy &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Please note that this command only updates the state to match any manual changes to the resources. If you want to make permanent changes it is recommended that you modify the configuration and reapply the changes.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Thank you for reading. We got pretty far into Terraform and I hope that people find these articles helpful. See you in the next article!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>cloud</category>
      <category>aws</category>
      <category>devops</category>
    </item>
    <item>
      <title>Terraform Enhanced Backend on Terraform Cloud with AWS access keys</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Fri, 01 Jul 2022 21:39:16 +0000</pubDate>
      <link>https://dev.to/af/terraform-enhanced-backend-on-terraform-cloud-with-aws-access-keys-227m</link>
      <guid>https://dev.to/af/terraform-enhanced-backend-on-terraform-cloud-with-aws-access-keys-227m</guid>
      <description>&lt;p&gt;Enhanced backend in Terraform means a backend that can store state AND perform operations for configuration management.&lt;/p&gt;

&lt;p&gt;Terraform has 2 enhanced backends that can store state and execute operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;local&lt;/code&gt; backend (default, stored locally)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;remote&lt;/code&gt; backend (used in &lt;a href="https://app.terraform.io/" rel="noopener noreferrer"&gt;Terraform Cloud&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We worked with &lt;code&gt;local&lt;/code&gt; backend quite extensively throughout these series. This article will show how to use Terraform Cloud and &lt;code&gt;remote&lt;/code&gt; backend that will allow us to store backend remotely and execute commands like &lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; with the output showing in the local terminal.&lt;/p&gt;

&lt;p&gt;In this article we will setup our Terraform configuration to work with Terraform Cloud and a &lt;code&gt;remote&lt;/code&gt; backend.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Here is the plan for this tutorial:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a workspace&lt;/li&gt;
&lt;li&gt;Setup &lt;code&gt;remote&lt;/code&gt; backend in our configuration&lt;/li&gt;
&lt;li&gt;Initialize our Terraform configuration&lt;/li&gt;
&lt;li&gt;Add AWS access tokens to the Terraform Cloud to allow remote execution of commands&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;br&gt;
The code for this tutorial can be found &lt;a href="https://github.com/periwinkleFTW/terraform-path-to-cert/tree/master/practice-pt-5" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In a &lt;a href="https://dev.to/af/terraform-state-4jp5"&gt;previous article&lt;/a&gt; I covered how to create a Terraform Cloud account and an organization.&lt;/p&gt;

&lt;p&gt;In order to proceed you will need to login into your &lt;a href="https://app.terraform.io" rel="noopener noreferrer"&gt;Terraform Cloud&lt;/a&gt; account and get the name of your organization:&lt;br&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%2Fzy0dqle09bpp9a8j1ul3.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%2Fzy0dqle09bpp9a8j1ul3.png" alt="Getting organization name from Terraform Cloud"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We will also need a workspace for our. Click on "New workspace". Make sure that you have selected the correct organization.&lt;br&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%2Fk3u1j4ckw49lsz0ldy2u.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%2Fk3u1j4ckw49lsz0ldy2u.png" alt="Creating Terraform workspace pt1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Select the &lt;code&gt;CLI-driven workflow&lt;/code&gt;:&lt;br&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%2F28qzorzhy5s2ovh1twet.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%2F28qzorzhy5s2ovh1twet.png" alt="Creating Terraform workspace pt2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Enter the name (optionally add description) and press &lt;code&gt;Create workspace&lt;/code&gt;:&lt;br&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%2Fsvyuxxjmvm89b0q8z4a4.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%2Fsvyuxxjmvm89b0q8z4a4.png" alt="Creating Terraform workspace pt3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;And our organization has a new workspace. Good job!&lt;br&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%2Fzeamnob3v1sqbj952pey.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%2Fzeamnob3v1sqbj952pey.png" alt="Creating Terraform workspace pt4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Now we will see how to use it in our configuration. First, let's create a remote backend and point Terraform to it. Make sure that you put the correct organization and workspace names:&lt;/p&gt;

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

&lt;span class="c1"&gt;# terraform.tf&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"remote"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hostname&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app.terraform.io"&lt;/span&gt;
    &lt;span class="nx"&gt;organization&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-blog"&lt;/span&gt;

    &lt;span class="nx"&gt;workspaces&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="s2"&gt;"demo-app-on-aws"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;It is assumed that you done &lt;code&gt;terraform login&lt;/code&gt; and added Terraform API token.&lt;/p&gt;

&lt;p&gt;Since we changed the settings we need to reinitialize Terraform:&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;$ &lt;/span&gt;terraform init
&lt;span class="c"&gt;# Output&lt;/span&gt;
Initializing modules...

Initializing the backend...

Successfully configured the backend &lt;span class="s2"&gt;"remote"&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Terraform will automatically
use this backend unless the backend configuration changes.


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

&lt;/div&gt;

&lt;p&gt;If you get this error:&lt;/p&gt;

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

│ The &lt;span class="s2"&gt;"remote"&lt;/span&gt; backend encountered an unexpected error &lt;span class="k"&gt;while &lt;/span&gt;reading the
│ organization settings: unauthorized


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

&lt;/div&gt;

&lt;p&gt;It means that your Terraform Cloud API token is not valid anymore. This problem can be fixed by running &lt;code&gt;terraform login&lt;/code&gt; and going the steps. You can also find a step-by-step guide in &lt;a href="https://dev.to/af/terraform-state-4jp5"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Let's see what happens when we try to execute a dry-run:&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;$ &lt;/span&gt;terraform plan
&lt;span class="c"&gt;# Output&lt;/span&gt;
Running plan &lt;span class="k"&gt;in &lt;/span&gt;the remote backend. Output will stream here. Pressing Ctrl-C
will stop streaming the logs, but will not stop the plan running remotely.

Preparing the remote plan...

To view this run &lt;span class="k"&gt;in &lt;/span&gt;a browser, visit:
https://app.terraform.io/app/terraform-blog/demo-app-on-aws/runs/run-fACfrx3XtjhNh1zW

Waiting &lt;span class="k"&gt;for &lt;/span&gt;the plan to start...

Terraform v1.2.4
on linux_amd64
Initializing plugins and modules...
╷
│ Error: error configuring Terraform AWS Provider: no valid credential sources &lt;span class="k"&gt;for &lt;/span&gt;Terraform AWS Provider found.
│ 
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ &lt;span class="k"&gt;for &lt;/span&gt;more information about providing credentials.
│ 
│ Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, request send failed, Get &lt;span class="s2"&gt;"http://169.254.169.254/latest/meta-data/iam/security-credentials/"&lt;/span&gt;: dial tcp 169.254.169.254:80: i/o &lt;span class="nb"&gt;timeout&lt;/span&gt;
│ 
│ 
│   with provider[&lt;span class="s2"&gt;"registry.terraform.io/hashicorp/aws"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
│   on main.tf line 3, &lt;span class="k"&gt;in &lt;/span&gt;provider &lt;span class="s2"&gt;"aws"&lt;/span&gt;:
│    3: provider &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
│ 
╵
Operation failed: failed running terraform plan &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We are interested in the first part of the output indicating that plan is running remotely:&lt;/p&gt;

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

Running plan &lt;span class="k"&gt;in &lt;/span&gt;the remote backend. Output will stream here. Pressing Ctrl-C
will stop streaming the logs, but will not stop the plan running remotely.

Preparing the remote plan...

To view this run &lt;span class="k"&gt;in &lt;/span&gt;a browser, visit:
https://app.terraform.io/app/terraform-blog/demo-app-on-aws/

Waiting &lt;span class="k"&gt;for &lt;/span&gt;the plan to start...


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We also got an error stating that we did not provide valid credentials for the AWS provider.&lt;/p&gt;

&lt;p&gt;Terraform Cloud allows us to add credentials as environment variables inside the workspace. Please note that you need your &lt;code&gt;AWS_ACCESS_KEY&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; to complete the next step.&lt;/p&gt;

&lt;p&gt;Select your workspace. You will see a &lt;code&gt;Variable&lt;/code&gt; tab at the top. Click that and you will arrive at the screen where you can add environment variables. That's where we will put our AWS credentials that will allow Terraform to deploy resources remotely.&lt;br&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%2Fnahwuav6ezm4iydlzp0f.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%2Fnahwuav6ezm4iydlzp0f.png" alt="Adding environment variables to Terraform Cloud enhanced remote backend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Now it's time to add our AWS access tokens to the environment. Select &lt;code&gt;Environment variable&lt;/code&gt; radio button. &lt;code&gt;AWS_SECRET_ACCESS_TOKEN&lt;/code&gt; will need to have the "sensitive" checkbox selected. This is important. Value field is where the actual key will go. See the picture for details:&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%2F5d65aj1c8qs0lgb5wfwq.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%2F5d65aj1c8qs0lgb5wfwq.png" alt="Adding AWS access token to Terraform Cloud"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This how it is supposed to look like after you are done. Pay attention how &lt;code&gt;AWS_ACCESS_KEY&lt;/code&gt; is public, yet &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; is private.&lt;br&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%2Fqmtnjal9zz2k1noarmx4.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%2Fqmtnjal9zz2k1noarmx4.png" alt="Adding AWS access token to Terraform Cloud pt2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's do another dry to verify that Terraform can use access to manage the infrastructure:&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;$ &lt;/span&gt;terraform plan
&lt;span class="c"&gt;# output&lt;/span&gt;
Running plan &lt;span class="k"&gt;in &lt;/span&gt;the remote backend. Output will stream here. Pressing Ctrl-C
will stop streaming the logs, but will not stop the plan running remotely.

Preparing the remote plan...

To view this run &lt;span class="k"&gt;in &lt;/span&gt;a browser, visit:
https://app.terraform.io/app/terraform-blog/demo-app-on-aws/

Waiting &lt;span class="k"&gt;for &lt;/span&gt;the plan to start...
&lt;span class="c"&gt;# lots of output here with resources&lt;/span&gt;
Plan: 25 to add, 0 to change, 0 to destroy.


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;And let's apply the changes:&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;$ &lt;/span&gt;terraform apply
&lt;span class="c"&gt;# lots of output but you should see this at the end&lt;/span&gt;
Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 25 added, 0 changed, 0 destroyed.


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Verify that resources with the list command:&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;$ &lt;/span&gt;terraform state list
data.aws_ami.ubuntu
data.aws_availability_zones.available
data.aws_region.current
aws_eip.nat_gateway_eip
aws_internet_gateway.internet_gateway
aws_nat_gateway.nat_gateway
aws_route_table.private_route_table
aws_route_table.public_route_table
aws_route_table_association.private
aws_route_table_association.public
aws_security_group.private_sg
aws_security_group.public_sg
aws_security_group_rule.private_in
aws_security_group_rule.private_out
aws_security_group_rule.public_http_in
aws_security_group_rule.public_https_in
aws_security_group_rule.public_out
aws_security_group_rule.public_ssh_in
aws_subnet.private_subnet
aws_subnet.public_subnet
aws_vpc.vpc
module._server_from_local_module.data.aws_ami.ubuntu
module._server_from_local_module.aws_instance.web_server
module.another_server_from_a_module.data.aws_ami.ubuntu
module.another_server_from_a_module.aws_instance.web_server
module.autoscaling_from_github.data.aws_default_tags.current
module.autoscaling_from_github.data.aws_partition.current
module.autoscaling_from_github.aws_autoscaling_group.this[0]
module.autoscaling_from_github.aws_launch_template.this[0]
module.autoscaling_from_registry.data.aws_default_tags.current
module.autoscaling_from_registry.data.aws_partition.current
module.autoscaling_from_registry.aws_autoscaling_group.this[0]
module.autoscaling_from_registry.aws_launch_template.this[0]
module.my_server_module.data.aws_ami.ubuntu
module.my_server_module.aws_instance.web_server


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Awesome! We have connected Terraform Cloud, added AWS API tokens in a secure manner. Now we can create, modify, and destroy resources using our local terminal with the state store remotely.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Finally, let's destroy the resources:&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;$ &lt;/span&gt;terraform destroy
&lt;span class="c"&gt;# output&lt;/span&gt;
Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 0 added, 0 changed, 25 destroyed.


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;You can also view the history of commands executed by this backend by clicking on &lt;code&gt;Runs&lt;/code&gt; tab within your organization:&lt;br&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%2Fntgstay3j2e5iz4u5dpe.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%2Fntgstay3j2e5iz4u5dpe.png" alt="History of commands on Terraform Cloud and enhanced backend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This wraps up this tutorial. Thank you for reading! See you in the next article.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Terraform Standard Backends: HTTP Backend</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Wed, 29 Jun 2022 02:07:59 +0000</pubDate>
      <link>https://dev.to/af/terraform-standard-backends-http-backend-17lp</link>
      <guid>https://dev.to/af/terraform-standard-backends-http-backend-17lp</guid>
      <description>&lt;p&gt;Another backend type which we will explore is called &lt;a href="https://www.terraform.io/language/settings/backends/http"&gt;HTTP backend&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This type of backend allows us to store state using a REST client. &lt;/p&gt;

&lt;p&gt;State will be fetched using &lt;code&gt;GET&lt;/code&gt;, updated via &lt;code&gt;POST&lt;/code&gt;, and finally destroyed using &lt;code&gt;DELETE&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This backend also supports state locking which, as we learned previously, is an incredibly handy feature. When locking is enabled you can use &lt;code&gt;LOCK&lt;/code&gt; and &lt;code&gt;UNLOCK&lt;/code&gt; requests to include the lock info in the body. The endpoint will return &lt;code&gt;423:Locked&lt;/code&gt; or &lt;code&gt;409:Conflict&lt;/code&gt; if the lock is active and &lt;code&gt;200:OK&lt;/code&gt; if there is no lock.&lt;/p&gt;

&lt;p&gt;This is how you add an HTTP backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# terraform.tf&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"http"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://myrest.api.com/foo"&lt;/span&gt;

    &lt;span class="nx"&gt;lock_method&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PUT"&lt;/span&gt;
    &lt;span class="nx"&gt;lock_address&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://myrest.api.com/foo"&lt;/span&gt;

    &lt;span class="nx"&gt;unlock_address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://myrest.api.com/foo"&lt;/span&gt;
    &lt;span class="nx"&gt;unlock_method&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"DELETE"&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 was a very short article, but since we are on the topic of backends I thought this simple backend will be a good addition.&lt;/p&gt;

&lt;p&gt;Thank you for reading! See you in the next article!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Terraform Standard Backends: S3 with versioning and state locking with DynamoDB</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Tue, 28 Jun 2022 02:11:26 +0000</pubDate>
      <link>https://dev.to/af/terraform-standard-backends-s3-with-versioning-and-state-locking-with-dynamodb-1ng7</link>
      <guid>https://dev.to/af/terraform-standard-backends-s3-with-versioning-and-state-locking-with-dynamodb-1ng7</guid>
      <description>&lt;p&gt;We learned a little bit about Terraform's state and backend in the previous article. Now it is time to explore Terraform's Standard Backend in more detail.&lt;/p&gt;

&lt;p&gt;Standard backends allow us to store the state remotely while modifying it locally through CLI. In essence it means that state is stored remotely while all Terraform operations are performed locally. We have seen an example of such backend in the previous article where we configured an AWS S3 bucket to store the state. We were still able to add resources, plan, and apply changes locally on our machine.&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://www.terraform.io/language/settings/backends/s3" rel="noopener noreferrer"&gt;link&lt;/a&gt; to the Terraform documentation regarding S3 backend. &lt;/p&gt;

&lt;p&gt;We can see that Terraform several backends. The following picture shows the list of the currently available backends. Official docs also have the settings you'd need to configure to make it work for each backend.&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%2Fr6s7ecjxs5dkgvp97dml.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%2Fr6s7ecjxs5dkgvp97dml.png" alt="Supported Terraform Backends"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the attractive features of cloud storage like S3 is that they come with file versioning. This means that state is versioned with minimal effort. Since this feature is outside of Terraform you need to find out how to enable versioning on your bucket.&lt;/p&gt;

&lt;p&gt;Another benefit of cloud storage is that you can enable encryption of the state file. Enabling &lt;code&gt;Server-side encryption&lt;/code&gt; for your bucket will add an extra layer of security to the Terraform state file. &lt;/p&gt;

&lt;h2&gt;
  
  
  State locking on AWS S3
&lt;/h2&gt;

&lt;p&gt;Locking is not supported out of the box for S3 backend, we need to enable it using AWS DynamoDB table.&lt;/p&gt;

&lt;p&gt;To enable this feature you will to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create an S3 bucket. Enable &lt;code&gt;Versioning&lt;/code&gt; and &lt;code&gt;Default Encryption&lt;/code&gt;&lt;br&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%2F6creri6ztopx628fluup.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%2F6creri6ztopx628fluup.png" alt="Creating S3 bucket with versioning and encryption to store Terraform State"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a DynamoDB table and select a name for Partition Key and table name (this is important). I chose table name "TF-locking" and partition key "lockID". Leave other settings as default and hit 'Create Table'.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fqbkwzry5t1dvxybbv8b2.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%2Fqbkwzry5t1dvxybbv8b2.png" alt="Creating a DynamoDB table for Terraform State Locking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modify the settings inside &lt;code&gt;terraform.tf&lt;/code&gt; to let Terraform know about your new table. See the snippet below.&lt;/li&gt;
&lt;li&gt; We have successfully configured locking on S3!
```terraform
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  terraform.tf
&lt;/h1&gt;

&lt;p&gt;terraform {&lt;br&gt;
  backend "s3" {&lt;br&gt;
    bucket = "terraform-state-remote"&lt;br&gt;
    key    = "dev/aws_infrastructure"&lt;br&gt;
    region = "ca-central-1"&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dynamodb_table = "TF-locking"
encrypt        = true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;# other settings below ...&lt;br&gt;
}&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;amp;nbsp;

Last thing we need to do is to run `init` command with reconfigure flag:
```bash


$ terraform init --reconfigure


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

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;To see locks you need to go the table you created and select 'View Items' and if there are any existing locks they would be displayed in the &lt;code&gt;lockID&lt;/code&gt; column in the AWS console.&lt;/p&gt;

&lt;p&gt;Thank you for reading! See you in the next article!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>terraform</category>
      <category>devops</category>
    </item>
    <item>
      <title>Terraform State</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Wed, 22 Jun 2022 01:10:12 +0000</pubDate>
      <link>https://dev.to/af/terraform-state-4jp5</link>
      <guid>https://dev.to/af/terraform-state-4jp5</guid>
      <description>&lt;p&gt;Terraform blocks and modules are the things you use to build your infrastructure, but state is how you manage it after deployment.&lt;/p&gt;

&lt;p&gt;A Terraform state is a record of the managed infrastructure. Each time you make an execution plan and attempt to create or modify resource, Terraform will compare your configuration to the existing state.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Local backend
&lt;/h2&gt;

&lt;p&gt;The location of the state file is specified in Terraform backend. By default the state is stored locally, in the working directory inside the &lt;code&gt;terraform.tfstate&lt;/code&gt; file. Data is stored in the JSON format and is relatively human-readable. Please note that you should not modify this file. It is extremely rare for anyone to modify it and even in those instances you should know exactly what you are doing.&lt;/p&gt;

&lt;p&gt;Backend settings are often specified in the &lt;code&gt;terraform.tf&lt;/code&gt; file inside the &lt;code&gt;terraform&lt;/code&gt; block. Not specifying a backend is equivalent to this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"local"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform.tfstate"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# other settings...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Viewing state
&lt;/h2&gt;

&lt;p&gt;We can see what the current state contains by running &lt;code&gt;terraform show&lt;/code&gt; command. Please note that if do not have any running resources the state file will be empty. You can run &lt;code&gt;terraform apply&lt;/code&gt; to deploy resources and they will be visible in the &lt;code&gt;show&lt;/code&gt; output.&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;$ &lt;/span&gt;terraform show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will output a lot of data and sometimes we are just interested in a more compressed view with just a list of resources and their names.&lt;br&gt;
This can be view with the &lt;code&gt;state list&lt;/code&gt; 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="nv"&gt;$ &lt;/span&gt;terraform state list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform state locking
&lt;/h2&gt;

&lt;p&gt;We have touched a little bit on how critical the state is to Terraform and its operation. At some point you might want to have other people to work or manage your Terraform configuration. This is when you want to implement controls to lock the state to prevent accidental updates or changes to the state. &lt;/p&gt;

&lt;p&gt;State locking does exactly that. When you have several people working on existing infrastructure you want control when and how changes to it are made. Locking will prevent corruption and it is something that everyone working with Terraform should know about.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;To demonstrate Terraform state lock I will first apply my configuration with &lt;code&gt;terraform apply&lt;/code&gt; but I will not enter &lt;code&gt;yes&lt;/code&gt; to confirm the apply. The deployment will be paused. At this stage the state will be locked. &lt;/p&gt;

&lt;p&gt;I will open another terminal window and run &lt;code&gt;apply&lt;/code&gt; command again I get this output:&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;$ &lt;/span&gt;terraform apply
╷
│ Error: Error acquiring the state lock
│ 
│ Error message: resource temporarily unavailable
│ Lock Info:
│   ID:        3853fd24-37f7-06be-f354-a6bb5bd4270b
│   Path:      terraform.tfstate
│   Operation: OperationTypeApply
│   Who:       andreyf@Andreys-MacBook-Pro-2.local
│   Version:   1.1.9
│   Created:   2022-06-22 01:03:41.259138 +0000 UTC
│   Info:      
│ 
│ 
│ Terraform acquires a state lock to protect the state from
│ being written
│ by multiple &lt;span class="nb"&gt;users &lt;/span&gt;at the same time. Please resolve the issue
│ above and try
│ again. For most commands, you can disable locking with the
│ &lt;span class="s2"&gt;"-lock=false"&lt;/span&gt;
│ flag, but this is not recommended.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see Terraform encountered an error acquiring the state lock and realizes that there are 2 concurrent apply commands.&lt;/p&gt;

&lt;p&gt;If there are several people working on a configuration and pushing changes, it helps to set the &lt;code&gt;-lock-timeout=100s&lt;/code&gt; which sets the timeout of 100 seconds to the apply command and waits for the lock to be released before applying changes. Here is an example with 300 seconds (5min):&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;$ &lt;/span&gt;terraform apply &lt;span class="nt"&gt;-lock-timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;300s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Not all Terraform backends support, but some do. Here is a list of the backends that support state locking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local backend&lt;/li&gt;
&lt;li&gt;Remote backend (Terraform Enterprise, Terraform Cloud)&lt;/li&gt;
&lt;li&gt;AWS S3 backend (with DynamoDB)&lt;/li&gt;
&lt;li&gt;Google Cloud Storage backend&lt;/li&gt;
&lt;li&gt;Azure Storage backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform state backend authentication
&lt;/h2&gt;

&lt;p&gt;Terraform state may contain a lot of sensitive data and protecting the state from unauthorized access is extremely important. Storing the state remotely allows team members to access it too, but it also exposes it to access from other people. Supported backends handle authentication differently. &lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform S3 standard backend with environment variable authentication
&lt;/h3&gt;

&lt;p&gt;This backend configuration allows us to store the state file inside an S3 bucket.&lt;/p&gt;

&lt;p&gt;To setup this backend you would need to create an S3 bucket, make sure that &lt;code&gt;Block ALL PUBLIC ACCESS&lt;/code&gt; checkmark is selected because we are trying to protect our state. &lt;/p&gt;

&lt;p&gt;Then we need update the backend inside the &lt;code&gt;terraform.tf&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# terraform.tf&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-demo-terraform-state-bucket"&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev/s3_terraform_state"&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ca-central-1"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# more settings below...&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;key&lt;/code&gt; specifies where the state file will be stored inside the bucket.&lt;/p&gt;

&lt;p&gt;We already imported &lt;code&gt;AWS_ACCESS_KEY&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; in installation and usage section this should work. If you need a refresher this is how it's done:&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;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"my_key"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&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;&lt;span class="s2"&gt;"my_secret_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the backend was changed we need to run &lt;code&gt;terraform init&lt;/code&gt; command to initialize the backend.&lt;/p&gt;

&lt;p&gt;In this exercise we covered two things: setting up an S3 bucket state location and reviewed using environment variables for authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform Remote Enhanced Backed with user token authentication
&lt;/h3&gt;

&lt;p&gt;This is a service provided by Terraform. It allows users to store state files inside Terraform Cloud. In order to use it we need to create a user token and import it into our local environment.&lt;/p&gt;

&lt;p&gt;To follow the example in this section you would need a Terraform account on &lt;a href="https://app.terraform.io/"&gt;Terraform Cloud&lt;/a&gt;. Once logged in create a new organization by providing an organization name and an email.&lt;/p&gt;

&lt;p&gt;Once you are done creating an organization, let's go back to our terminal and punch in this 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="nv"&gt;$ &lt;/span&gt;terraform login
&lt;span class="c"&gt;# output&lt;/span&gt;
Terraform will request an API token &lt;span class="k"&gt;for &lt;/span&gt;app.terraform.io using your browser.

If login is successful, Terraform will store the token &lt;span class="k"&gt;in &lt;/span&gt;plain text &lt;span class="k"&gt;in
&lt;/span&gt;the following file &lt;span class="k"&gt;for &lt;/span&gt;use by subsequent commands:
    /Users/andreyf/.terraform.d/credentials.tfrc.json

Do you want to proceed?
  Only &lt;span class="s1"&gt;'yes'&lt;/span&gt; will be accepted to confirm.

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

&lt;/div&gt;



&lt;p&gt;Enter &lt;code&gt;yes&lt;/code&gt; for the first prompt. It will open a browser window and print this output:&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="nt"&gt;---------------------------------------------------------------------------------&lt;/span&gt;

Terraform must now open a web browser to the tokens page &lt;span class="k"&gt;for &lt;/span&gt;app.terraform.io.

If a browser does not open this automatically, open the following URL to proceed:
    https://app.terraform.io/app/settings/tokens?source&lt;span class="o"&gt;=&lt;/span&gt;terraform-login


&lt;span class="nt"&gt;---------------------------------------------------------------------------------&lt;/span&gt;

Generate a token using your browser, and copy-paste it into this prompt.

Terraform will store the token &lt;span class="k"&gt;in &lt;/span&gt;plain text &lt;span class="k"&gt;in &lt;/span&gt;the following file
&lt;span class="k"&gt;for &lt;/span&gt;use by subsequent commands:
    /Users/andreyf/.terraform.d/credentials.tfrc.json

Token &lt;span class="k"&gt;for &lt;/span&gt;app.terraform.io:
  Enter a value: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I named my token &lt;code&gt;terraform login credentials&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgh523o6ohbyennf9q1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgh523o6ohbyennf9q1v.png" alt="Terraform cloud token generation" width="800" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Create API token&lt;/code&gt; and you will get the token.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Now we need to paste this token in our terminal to complete the setup process:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7e0l3ilg8rvyv59wc5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7e0l3ilg8rvyv59wc5n.png" alt="Adding Terraform token to terraform login" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This is the output I got after I added the token:&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="nt"&gt;----------------&lt;/span&gt;

Generate a token using your browser, and copy-paste it into this prompt.

Terraform will store the token &lt;span class="k"&gt;in &lt;/span&gt;plain text &lt;span class="k"&gt;in &lt;/span&gt;the following file
&lt;span class="k"&gt;for &lt;/span&gt;use by subsequent commands:
    /Users/andreyf/.terraform.d/credentials.tfrc.json

Token &lt;span class="k"&gt;for &lt;/span&gt;app.terraform.io:
  Enter a value: 


Retrieved token &lt;span class="k"&gt;for &lt;/span&gt;user andreyfrol


&lt;span class="nt"&gt;---------------------------------------------------------------------------------&lt;/span&gt;

                                          -                                
                                          &lt;span class="nt"&gt;-----&lt;/span&gt;                           -
                                          &lt;span class="nt"&gt;---------&lt;/span&gt;                      &lt;span class="nt"&gt;--&lt;/span&gt;
                                          &lt;span class="nt"&gt;---------&lt;/span&gt;  -                &lt;span class="nt"&gt;-----&lt;/span&gt;
                                           &lt;span class="nt"&gt;---------&lt;/span&gt;  &lt;span class="nt"&gt;------&lt;/span&gt;        &lt;span class="nt"&gt;-------&lt;/span&gt;
                                             &lt;span class="nt"&gt;-------&lt;/span&gt;  &lt;span class="nt"&gt;---------&lt;/span&gt;  &lt;span class="nt"&gt;----------&lt;/span&gt;
                                                &lt;span class="nt"&gt;----&lt;/span&gt;  &lt;span class="nt"&gt;----------&lt;/span&gt; &lt;span class="nt"&gt;----------&lt;/span&gt;
                                                  &lt;span class="nt"&gt;--&lt;/span&gt;  &lt;span class="nt"&gt;----------&lt;/span&gt; &lt;span class="nt"&gt;----------&lt;/span&gt;
   Welcome to Terraform Cloud!                     -  &lt;span class="nt"&gt;----------&lt;/span&gt; &lt;span class="nt"&gt;-------&lt;/span&gt;
                                                      &lt;span class="nt"&gt;---&lt;/span&gt;  &lt;span class="nt"&gt;-----&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;
   Documentation: terraform.io/docs/cloud             &lt;span class="nt"&gt;--------&lt;/span&gt;   -
                                                      &lt;span class="nt"&gt;----------&lt;/span&gt;
                                                      &lt;span class="nt"&gt;----------&lt;/span&gt;
                                                       &lt;span class="nt"&gt;---------&lt;/span&gt;
                                                           &lt;span class="nt"&gt;-----&lt;/span&gt;
                                                               -


   New to TFC? Follow these steps to instantly apply an example configuration:

   &lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/hashicorp/tfc-getting-started.git
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;tfc-getting-started
   &lt;span class="nv"&gt;$ &lt;/span&gt;scripts/setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I think this is a good point to wrap up this article. Terraform state is a big topic and it will likely require more than one article to cover the basics. &lt;/p&gt;

&lt;p&gt;Thank you for reading and see you in the next article!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>XPath vs CSS Selector: what is going on with these two?</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Mon, 20 Jun 2022 18:40:37 +0000</pubDate>
      <link>https://dev.to/af/xpath-vs-css-selector-what-is-going-on-with-these-two-4i7g</link>
      <guid>https://dev.to/af/xpath-vs-css-selector-what-is-going-on-with-these-two-4i7g</guid>
      <description>&lt;p&gt;As I was learning scraping I have done many tutorials on it. Some tutorials used XPath and others used god ol' CSS Selectors. Until today I always resorted to CSS because it was a familiar choice. All I new about XPath is that Scrapy uses it by default and any CSS selectors are converted to XPath behind the scenes. Being a complete noob at the time I did not give it much thought. Alas, the time has come for me to sink my teeth into this topic and understand what is the difference between these two types of selectors.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  XPath
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  What it is
&lt;/h3&gt;

&lt;p&gt;XPath stands for XML Path. It uses XML document and queries it to identify elements within it. The path part of XPath means that we need to specify the path from the beginning to the desired element.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of XPath
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Allows navigation up the DOM when looking for elements&lt;/li&gt;
&lt;li&gt;More flexible than CSS Selectors&lt;/li&gt;
&lt;li&gt;Allows searching for full or partial text in element names with &lt;code&gt;contains&lt;/code&gt; keyword&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  CSS Selector
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  What it is
&lt;/h3&gt;

&lt;p&gt;CSS Selector uses styles specified in Cascading Style Sheet (CSS) to select desired elements. Most of the web pages online are styled using CSS and that makes CSS Selector a popular choice for a lot of people.&lt;/p&gt;

&lt;p&gt;CSS relies on tags, class names, and ids among other things to select what we want. This is in contrast with XPath which uses tree-like structure to select the element.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of CSS Selector
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity because CSS is easy to pick up &lt;/li&gt;
&lt;li&gt;Faster than XPath because we can specify the exact element and completely disregard everything else on the page&lt;/li&gt;
&lt;li&gt;Allows attribute selection based on values assigned to them&lt;/li&gt;
&lt;li&gt;Allows pseudo selectors for elements whose state is declared with CSS, such as on-hover attributes and checkboxes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Syntax for XPath and CSS Selector
&lt;/h1&gt;

&lt;p&gt;This a great table that shows the differences between XPath and CSS Selector made by &lt;a href="https://gist.github.com/slotix/11f0930b2d46d2946249a10e6216735b#file-css3vsxpath-csv"&gt;Slotix&lt;/a&gt; :&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6iz0mfocerlnregrbwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6iz0mfocerlnregrbwg.png" alt="xpath-vs-css-selector" width="734" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>scraping</category>
      <category>xpath</category>
    </item>
    <item>
      <title>Terraform Workflow (write-&gt;plan-&gt;apply)</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Sun, 19 Jun 2022 22:36:40 +0000</pubDate>
      <link>https://dev.to/af/terraform-workflow-write-plan-apply-512h</link>
      <guid>https://dev.to/af/terraform-workflow-write-plan-apply-512h</guid>
      <description>&lt;p&gt;Now that we are familiar with Terraform's building blocks we can start exploring &lt;em&gt;how&lt;/em&gt; Terraform expects people to use it.&lt;/p&gt;

&lt;p&gt;It may sound silly, but learning workflow can prevent common pitfalls and unexpected problems. I am sure all of us ended up in a situation when we were using something incorrectly. It happens to me very often because I want to use something as soon as possible hoping that I will figure things out as I go. &lt;/p&gt;

&lt;p&gt;Since this blog doubles as my study notes, I believe I should not slack off and included this section because it is something that will be tested on the exam.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This photo illustrates basic workflow that Terraform wants its users to follow:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1ormw9rdlb77vosclve.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1ormw9rdlb77vosclve.jpeg" alt="Terraform workflow" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We touched on it during the practice and we followed this workflow without it being formally introduced. So here it is.&lt;/p&gt;

&lt;p&gt;First we write our configuration and initialize our project.&lt;/p&gt;

&lt;p&gt;Then we format and validate the code to tidy it up and check for syntax error.&lt;/p&gt;

&lt;p&gt;After that we do a dry-run (&lt;code&gt;terraform plan&lt;/code&gt;) to see what exactly Terraform will attempt to deploy and verify it.&lt;/p&gt;

&lt;p&gt;Last step is an actual deploy with &lt;code&gt;terraform apply&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One command that is used often is &lt;code&gt;terraform destroy&lt;/code&gt; which destroys deployed resource from current configuration.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Terraform &lt;code&gt;init&lt;/code&gt; command
&lt;/h2&gt;

&lt;p&gt;This is a command that we used a lot and it is used to initialize terraform projects and update providers. This is the first command we would run after writing our configuration or after cloning existing configuration.&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;$ &lt;/span&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's also a command that needs to be run after we add/import new modules and checks if all versions are correct.&lt;/p&gt;

&lt;p&gt;This command downloads Terraform backend and sets up things like lock file and other important internal files.&lt;/p&gt;

&lt;p&gt;Rule of thumb is that we need to run &lt;code&gt;init&lt;/code&gt; whenever we add new modules, change versions, add/remove providers, or change Terraform backend in some way. Luckily, Terraform will inform us if we forgot to initialize our configuration.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform &lt;code&gt;validate&lt;/code&gt; command
&lt;/h2&gt;

&lt;p&gt;Validate command does exactly what its name suggests. It checks the code for syntax errors and ensures that it is internally consistent. It only looks at the configuration files (&lt;code&gt;*.tf&lt;/code&gt;) in the current working 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="nv"&gt;$ &lt;/span&gt;terraform validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want &lt;code&gt;validate&lt;/code&gt; to check files inside folders (eg you have &lt;code&gt;modules/&lt;/code&gt; directory), you need to set &lt;code&gt;-recursive&lt;/code&gt; flag:&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;$ &lt;/span&gt;terraform validate &lt;span class="nt"&gt;-recursive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform &lt;code&gt;plan&lt;/code&gt; command
&lt;/h2&gt;

&lt;p&gt;This command is often called a &lt;code&gt;dry-run&lt;/code&gt; so make sure you remember it. When you hear the words "execution plan" that would be it as well.&lt;/p&gt;

&lt;p&gt;It is used to determine the changes to apply to the existing (if any) resources. You will get a report of what is going to be created, modified, or destroyed. Terraform also allows for saving this plan in a file.&lt;/p&gt;

&lt;p&gt;You can save the plan and execute that saved plan at a later time or use it for analysis and record keeping.&lt;/p&gt;

&lt;p&gt;Execution plan is not a requirement for deployment, but it is always a good idea to see what will happen.&lt;/p&gt;

&lt;p&gt;That's how you run it:&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;$ &lt;/span&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform &lt;code&gt;apply&lt;/code&gt; command
&lt;/h2&gt;

&lt;p&gt;This is how you actually deploy your resources or applying changes to your infrastructure. As with &lt;code&gt;plan&lt;/code&gt; command, you will also get a report identifying which resources are to be created, modified, or destroyed. &lt;/p&gt;

&lt;p&gt;After running this command Terraform will also create a &lt;code&gt;state&lt;/code&gt; file. This is a living record of all deployed resources. State warrants a whole articles on its own given how important it is. &lt;/p&gt;

&lt;p&gt;One thing to note, this command only applies to the resources specified in your current configuration. It will not touch any existing resources that are not part of the configuration you are deploying.&lt;/p&gt;

&lt;p&gt;That's how you deploy resource with Terraform:&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;$ &lt;/span&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you don't want to type &lt;code&gt;yes&lt;/code&gt; every time, you can set an auto-approve tag:&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;$ &lt;/span&gt;terraform apply &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform &lt;code&gt;destroy&lt;/code&gt; command
&lt;/h2&gt;

&lt;p&gt;Destroying resources is an integral part of Terraform. Deploying consistent and reproducible infrastructure implies that you will be creating and destroying resources when needed.&lt;/p&gt;

&lt;p&gt;We used this command extensive in the practice section of this series because we do not want to leave any technical debt behind. It also ensures that we do not incur any unnecessary charges from AWS.&lt;/p&gt;

&lt;p&gt;Just like with plan and apply commands, Terraform will show you what exactly it will attempt to destroy.&lt;/p&gt;

&lt;p&gt;This is how you use it:&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;$ &lt;/span&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also supports &lt;code&gt;auto-approve&lt;/code&gt; flag:&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;$ &lt;/span&gt;terraform destroy &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Thank you for reading! At this point you are becoming somewhat knowledgeable about Terraform and its capabilities. We still have one big topic to cover. This topic is &lt;em&gt;State&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;See you in the next article!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Terraform Practice pt4: Module Inputs and Outputs</title>
      <dc:creator>AF uarabei</dc:creator>
      <pubDate>Sun, 19 Jun 2022 07:44:53 +0000</pubDate>
      <link>https://dev.to/af/practice-pt4-terraform-module-inputs-and-outputs-1p9d</link>
      <guid>https://dev.to/af/practice-pt4-terraform-module-inputs-and-outputs-1p9d</guid>
      <description>&lt;p&gt;To make out modules truly useful we need a way to pass input parameters to them and get output from them to use in our configuration.&lt;/p&gt;

&lt;p&gt;Code for this example &lt;a href="https://github.com/periwinkleFTW/terraform-path-to-cert/tree/master/practice-pt-4"&gt;HERE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is usually done by creating a &lt;code&gt;varaibles.tf&lt;/code&gt; and &lt;code&gt;outputs.tf&lt;/code&gt;. This file layout is the best practice and people working with Terraform would generally implement it this way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;varaibles.tf&lt;/code&gt; will store input variables and &lt;code&gt;outputs.tf&lt;/code&gt; will store outputs from our module.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;First, let's refactor out &lt;code&gt;server&lt;/code&gt; module and create 3 files: &lt;code&gt;main.tf&lt;/code&gt;, &lt;code&gt;variables.tf&lt;/code&gt;, and &lt;code&gt;outputs.tf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next we need to break down our code and put in inside the proper files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/server/variables.tf&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"subnet_id"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"size"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"security_groups"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;any&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 terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/server/main.tf&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;most_recent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;filter&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="s2"&gt;"name"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;filter&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="s2"&gt;"virtualization-type"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hvm"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;owners&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"099720109477"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web_server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ubuntu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_security_group_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;security_groups&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&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="s2"&gt;"Web Server from module"&lt;/span&gt;
    &lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&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 terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/server/outputs.tf&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_ip"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_dns"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_dns&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now delete &lt;code&gt;server.tf&lt;/code&gt;. Initialize, format, validate, and plan to check the new code.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This is the new project structure:&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;.&lt;/span&gt;
├── main.tf
├── modules
│   └── server
│       ├── main.tf
│       ├── outputs.tf
│       ├── server.tf
│       └── variables.tf
├── outputs.tf
├── terraform.tf
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Terrafrom input variables
&lt;/h1&gt;

&lt;p&gt;As with many configurations out there Terraform provides us with ability to specify required and optional parameters. If you look into server's &lt;code&gt;variable.tf&lt;/code&gt; you can see that some variables have default values and some do not. &lt;/p&gt;

&lt;p&gt;Optional parameters will have a &lt;code&gt;default&lt;/code&gt; value to fall back on in case it was not provided. &lt;/p&gt;

&lt;p&gt;Required parameters do not have &lt;code&gt;default&lt;/code&gt; meaning that it should be specified one way or the other. &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Terraform outputs
&lt;/h1&gt;

&lt;p&gt;Similar to variables, outputs serve the same purpose as inputs of providing data between different parts of the configuration. The difference lies in how they are accessed and the fact that outputs are read-only. In order to access outputs you must call them from the module where you intend to access them.&lt;/p&gt;

&lt;p&gt;Outputs is the only way for us to access attributes from child modules. &lt;/p&gt;

&lt;p&gt;Outputs can be accessed using dot notation (this is &lt;code&gt;main.tf&lt;/code&gt; in the root dir):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# main.tf&lt;/span&gt;

&lt;span class="c1"&gt;# ... more code above&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_ip"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_server_module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading! See you in the next article!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
