<?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>Forem: Bhaskara teja Bulusu</title>
    <description>The latest articles on Forem by Bhaskara teja Bulusu (@bhaskara_tejabulusu_b4bf).</description>
    <link>https://forem.com/bhaskara_tejabulusu_b4bf</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%2F3627862%2F71c75d80-9a16-4a6a-9a0a-202c79bc7fcf.png</url>
      <title>Forem: Bhaskara teja Bulusu</title>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bhaskara_tejabulusu_b4bf"/>
    <language>en</language>
    <item>
      <title>Day-15: VPC Peering using AWS Terraform</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Thu, 11 Dec 2025 18:15:22 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-15-vpc-peering-using-aws-terraform-2j75</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-15-vpc-peering-using-aws-terraform-2j75</guid>
      <description>&lt;h2&gt;
  
  
  Day 15: VPC Peering with Terraform
&lt;/h2&gt;

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

&lt;p&gt;Today, we're diving into one of the most powerful networking concepts in AWS: &lt;strong&gt;VPC Peering&lt;/strong&gt;. This tutorial will guide you through creating a complete, production-ready setup that connects two VPCs across different AWS regions, enabling seamless communication between resources in geographically distributed environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is VPC Peering?
&lt;/h2&gt;

&lt;p&gt;VPC Peering is a networking connection between two Virtual Private Clouds that enables you to route traffic between them using private IP addresses. When implemented across regions, it becomes an invaluable tool for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Disaster Recovery&lt;/strong&gt;: Distribute workloads across regions for high availability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low Latency Access&lt;/strong&gt;: Route traffic directly between regions without internet gateways&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Replication&lt;/strong&gt;: Securely replicate data between regional databases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global Applications&lt;/strong&gt;: Build truly global applications with regional presence&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;Our infrastructure will consist of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary VPC&lt;/strong&gt; in &lt;code&gt;us-east-1&lt;/code&gt; (10.0.0.0/16)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secondary VPC&lt;/strong&gt; in &lt;code&gt;us-west-1&lt;/code&gt; (10.1.0.0/16)&lt;/li&gt;
&lt;li&gt;EC2 instances in both VPCs running Apache web servers&lt;/li&gt;
&lt;li&gt;Bi-directional VPC peering connection&lt;/li&gt;
&lt;li&gt;Security groups configured for cross-region communication&lt;/li&gt;
&lt;li&gt;Complete networking stack (subnets, route tables, internet gateways)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Multi-Region Provider Configuration
&lt;/h2&gt;

&lt;p&gt;The foundation of multi-region deployment lies in configuring multiple AWS provider aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&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;6.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"primary"&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;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"secondary"&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;"us-west-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Takeaway&lt;/strong&gt;: Using provider aliases allows you to manage resources in multiple regions from a single Terraform configuration. Each resource references its target region using the &lt;code&gt;provider&lt;/code&gt; argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Defining Variables
&lt;/h2&gt;

&lt;p&gt;We define our network configuration using variables for flexibility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"primary_region"&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;string&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;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"secondary_region"&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;string&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;"us-west-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"primary_vpc_cidr"&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;string&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;"10.0.0.0/16"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"secondary_vpc_cidr"&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;string&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;"10.1.0.0/16"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"primary_sn_cidr"&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;string&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;"10.0.14.0/24"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"secondary_sn_cidr"&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;string&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;"10.1.12.0/24"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Non-overlapping CIDR blocks are crucial for VPC peering. Our primary (10.0.x.x) and secondary (10.1.x.x) ranges ensure no conflicts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Data Sources for Dynamic Configuration
&lt;/h2&gt;

&lt;p&gt;We use data sources to fetch the latest Ubuntu AMIs and available availability zones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_availability_zones"&lt;/span&gt; &lt;span class="s2"&gt;"primary"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_availability_zones"&lt;/span&gt; &lt;span class="s2"&gt;"secondary"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt; &lt;span class="s2"&gt;"primary_ami"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;provider&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="nx"&gt;primary&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;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;"amazon"&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;"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-jammy-22.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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_ami"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&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;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;"amazon"&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;"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-jammy-22.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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Data Sources?&lt;/strong&gt; Instead of hardcoding AMI IDs (which vary by region), we dynamically query for the latest Ubuntu 22.04 image in each region.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Creating VPCs in Multiple Regions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Primary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc"&lt;/span&gt; &lt;span class="s2"&gt;"primary_vpc"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc_cidr&lt;/span&gt;

  &lt;span class="nx"&gt;enable_dns_hostnames&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;enable_dns_support&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;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;"VPC"&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Primary"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Secondary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_vpc"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;instance_tenancy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;

  &lt;span class="nx"&gt;enable_dns_hostnames&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;enable_dns_support&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;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;"VPC"&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Secondary"&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;strong&gt;Important&lt;/strong&gt;: Both VPCs have DNS support enabled, which is essential for resources within the VPC to resolve domain names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Network Infrastructure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Subnets
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Subnet in Primary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"primary_sn"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc&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;cidr_block&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_sn_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;map_public_ip_on_launch&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;availability_zone&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;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;"Primary subnet"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Subnet in Secondary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_sn"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc&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;cidr_block&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_sn_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;map_public_ip_on_launch&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;availability_zone&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;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;"Secondary subnet"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Internet Gateways
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// IGW for primary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_internet_gateway"&lt;/span&gt; &lt;span class="s2"&gt;"primary_igw"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc&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;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;"Primary IGW"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// IGW for secondary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_internet_gateway"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_igw"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc&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;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;"Secondary IGW"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Route Tables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Route table for primary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table"&lt;/span&gt; &lt;span class="s2"&gt;"primary_rt"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc&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;route&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;
    &lt;span class="nx"&gt;gateway_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_internet_gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_igw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;}&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;"Primary VPC Route Table"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Route table for secondary VPC&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_rt"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc&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;route&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;
    &lt;span class="nx"&gt;gateway_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_internet_gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_igw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;}&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;"Secondary VPC Route Table"&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;h2&gt;
  
  
  Step 6: The Heart of It - VPC Peering
&lt;/h2&gt;

&lt;p&gt;This is where the magic happens! Creating a cross-region VPC peering connection involves two steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Creating the Peering Connection (Requester)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc_peering_connection"&lt;/span&gt; &lt;span class="s2"&gt;"primary_to_secondary"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc&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;peer_vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc&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;peer_region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_region&lt;/span&gt;
  &lt;span class="nx"&gt;auto_accept&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;"Primary to secondary peering"&lt;/span&gt;
    &lt;span class="nx"&gt;Side&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Requestor"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Accepting the Peering Connection (Acceptor)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc_peering_connection_accepter"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_vpc_accepter"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_peering_connection_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc_peering_connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_to_secondary&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;auto_accept&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;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;Side&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Accepter"&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;strong&gt;Critical Note&lt;/strong&gt;: For cross-region peering, you must set &lt;code&gt;auto_accept = false&lt;/code&gt; on the requester and use the &lt;code&gt;aws_vpc_peering_connection_accepter&lt;/code&gt; resource in the target region.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Updating Route Tables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Route from primary to secondary&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route"&lt;/span&gt; &lt;span class="s2"&gt;"primary_to_secondary"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;route_table_id&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_rt&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;destination_cidr_block&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cidr_block&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_peering_connection_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc_peering_connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_to_secondary&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;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_vpc_peering_connection_accepter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc_accepter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Route from secondary to primary&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_to_primary"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;route_table_id&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_rt&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;destination_cidr_block&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cidr_block&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_peering_connection_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc_peering_connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_to_secondary&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;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_vpc_peering_connection_accepter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc_accepter&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;strong&gt;Essential&lt;/strong&gt;: The &lt;code&gt;depends_on&lt;/code&gt; ensures routes are only created after the peering connection is accepted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Security Groups for Cross-Region Traffic
&lt;/h2&gt;

&lt;p&gt;Security groups control the traffic flow between our regions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Primary VPC Security Group&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"primary_sg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc&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;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH from anywhere"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow traffic from secondary vpc"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;65535&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc_cidr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow icmp from secondary vpc"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;-1&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;-1&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc_cidr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"icmp"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;egress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow all outbound traffic"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-1"&lt;/span&gt;
  &lt;span class="p"&gt;}&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;"Primary SG"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Secondary VPC Security Group&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_sg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_vpc&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;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow ssh from anywhere"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow all traffic from primary vpc"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;65535&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc_cidr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow ICMP from primary"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;-1&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;-1&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"icmp"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_vpc_cidr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;egress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow all outbound traffic"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-1"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&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;strong&gt;Security Best Practice&lt;/strong&gt;: Notice how we allow ICMP (ping) between VPCs for connectivity testing and all TCP traffic between the VPC CIDR ranges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: EC2 Instances with User Data
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local Values for User Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;primary_user_data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
    #!/bin/bash
    # Update packages
    apt-get update -y

    # Install Apache
    apt-get install apache2 -y

    # Start Apache
    systemctl start apache2
    systemctl enable apache2

    # Create a sample HTML page
    echo "&amp;lt;h1&amp;gt;Hello from Terraform EC2 Local Variable!&amp;lt;/h1&amp;gt;" &amp;gt; /var/www/html/index.html
&lt;/span&gt;&lt;span class="no"&gt;  EOF

&lt;/span&gt;   &lt;span class="nx"&gt;secondary_user_data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
    #!/bin/bash
    # Update packages
    apt-get update -y

    # Install Apache
    apt-get install apache2 -y

    # Start Apache
    systemctl start apache2
    systemctl enable apache2

    # Create a sample HTML page
    echo "&amp;lt;h1&amp;gt;Hello from Terraform EC2 Local Variable!&amp;lt;/h1&amp;gt;" &amp;gt; /var/www/html/index.html
&lt;/span&gt;&lt;span class="no"&gt;  EOF
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  EC2 Instances
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// EC2 instance in primary region&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"primary_instance"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;primary&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_ami&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="s2"&gt;"t3.micro"&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_sn&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;key_name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_key_pair&lt;/span&gt;
  &lt;span class="nx"&gt;security_groups&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_sg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;user_data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_user_data&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;"Primary Instance"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// EC2 instance in secondary region&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"secondary_instance"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&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="nx"&gt;secondary&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_ami&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;count&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;
  &lt;span class="nx"&gt;key_name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_key_pair&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_sn&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;security_groups&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_sg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;user_data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary_user_data&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;"Secondary Instance"&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;h2&gt;
  
  
  Deployment Steps
&lt;/h2&gt;

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



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

&lt;/div&gt;



&lt;p&gt;This downloads the AWS provider and initializes the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Review the Execution Plan
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;This shows you exactly what resources Terraform will create across both regions.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Apply the Configuration
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; when prompted. Terraform will create approximately 20+ resources across two AWS regions!&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Verify the Deployment
&lt;/h3&gt;

&lt;p&gt;After successful deployment, you can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Test connectivity via SSH&lt;/strong&gt;: Connect to instances in both regions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test VPC peering&lt;/strong&gt;: Ping the private IP of one instance from the other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test web server&lt;/strong&gt;: Access Apache on both instances via their public IPs&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Testing Cross-Region Connectivity
&lt;/h2&gt;

&lt;p&gt;Once deployed, SSH into the primary instance and try pinging the secondary instance's private IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# From primary instance&lt;/span&gt;
ping &amp;lt;secondary-instance-private-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see successful responses, proving the VPC peering is working!&lt;/p&gt;

&lt;p&gt;To avoid ongoing charges, destroy the infrastructure when done:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;Congratulations! You've successfully built a multi-region infrastructure with VPC peering using Terraform. This architecture pattern is foundational for enterprise-grade AWS deployments requiring high availability, disaster recovery, and global reach.&lt;/p&gt;

&lt;p&gt;The power of Infrastructure as Code truly shines when managing complex, multi-region setups like this. What would take hours of manual clicking in the AWS console is now reproducible, version-controlled, and automated!&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Experiment with adding more subnets and availability zones&lt;/li&gt;
&lt;li&gt;Implement Transit Gateway for hub-and-spoke topology&lt;/li&gt;
&lt;li&gt;Add VPC Flow Logs for network monitoring&lt;/li&gt;
&lt;li&gt;Configure AWS PrivateLink for service-to-service communication&lt;/li&gt;
&lt;li&gt;Implement cross-region load balancing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/WGt000THDmQ?si=mBJ36uPnPvBAISii" rel="noopener noreferrer"&gt;https://youtu.be/WGt000THDmQ?si=mBJ36uPnPvBAISii&lt;/a&gt;&lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-14: Project - Deploying a Static website using Terraform</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Tue, 09 Dec 2025 08:39:49 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-14-project-deploying-a-static-website-using-terraform-pjd</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-14-project-deploying-a-static-website-using-terraform-pjd</guid>
      <description>&lt;h2&gt;
  
  
  Project - Deploy a Static Website with AWS S3 and CloudFront using Terraform
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Objective
&lt;/h3&gt;

&lt;p&gt;Deploy a static website using AWS S3 for storage and CloudFront for content delivery.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture Diagram
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of Terraform&lt;/li&gt;
&lt;li&gt;AWS account with necessary permissions&lt;/li&gt;
&lt;li&gt;Terraform installed on your local machine&lt;/li&gt;
&lt;li&gt;AWS CLI configured with your credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set Up Your Terraform Configuration&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Create a new directory for your project and navigate into it.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;main.tf&lt;/code&gt; file to define your Terraform configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Define the AWS Provider&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;    &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&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;"us-east-1"&lt;/span&gt; &lt;span class="c1"&gt;# Change to your preferred region&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create variables.tf&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;    &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The name of the S3 bucket to create"&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;string&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create an S3 Bucket&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;    &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"static_website"&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="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_name&lt;/span&gt;     &lt;span class="c1"&gt;# Change to a unique bucket name&lt;/span&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Make the Bucket Private&lt;/strong&gt;
make the bucket private by blocking all public access
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Block all public access to the S3 bucket.&lt;/span&gt;

  &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket_public_access_block"&lt;/span&gt; &lt;span class="s2"&gt;"block_public_access"&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="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;static_website&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;block_public_acls&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;block_public_policy&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;ignore_public_acls&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;restrict_public_buckets&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a Bucket Policy to Allow Access from CloudFront&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

    &lt;span class="c1"&gt;// main.tf&lt;/span&gt;
    &lt;span class="c1"&gt;// Add bucket policy to allow access from another CloudFront &lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket_policy"&lt;/span&gt; &lt;span class="s2"&gt;"allow_access_from_another_account"&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="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;static_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="c1"&gt;// implicit dependency on S3 bucket&lt;/span&gt;

&lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_s3_bucket_public_access_block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;block_public_access&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3_bucket_policy&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// locals.tf&lt;/span&gt;
&lt;span class="c1"&gt;// local variables&lt;/span&gt;
&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;s3_bucket_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;templatefile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_policy_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bucket_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;static_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;cloudfront_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_cloudfront_distribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3_distribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//variables.tf&lt;/span&gt;
&lt;span class="c1"&gt;// Read bucket policy from json file&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_policy_file"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The file name that contains the bucket policy in JSON format"&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;string&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;"bucket_policy.json.tmpl"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// bucket_policy.json.tmpl&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"Version"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"Statement"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"Sid"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"AllowCloudFrontService"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"Effect"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"Principal"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cloudfront.amazonaws.com"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"Action"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="s2"&gt;"Resource"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"${bucket_arn}/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"Condition"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"StringEquals"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"AWS:SourceArn"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"${cloudfront_arn}"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Upload Static Website Files&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Create a folder named &lt;code&gt;www&lt;/code&gt; in your project directory and add your static website files (e.g., &lt;code&gt;index.html&lt;/code&gt;, &lt;code&gt;styles.css&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;aws_s3_object&lt;/code&gt; resource to upload these files to the S3 bucket.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Add files to the S3 bucket&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_object"&lt;/span&gt; &lt;span class="s2"&gt;"static_files"&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="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;static_bucket&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;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${path.module}/www"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"**"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;"${path.module}/www/${each.value}"&lt;/span&gt;

    &lt;span class="nx"&gt;etag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filemd5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${path.module}/www/${each.value}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;content_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"text/html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;css&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"text/css"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;js&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"application/javascript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;png&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;jpg&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"image/jpeg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;jpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"image/jpeg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;gif&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"image/gif"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;svg&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"image/svg+xml"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;each&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;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;each&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;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;"application/octet-stream"&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;ol&gt;
&lt;li&gt;&lt;strong&gt;Create Origin Access Identity for CloudFront&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is an IAM to the resource (example: s3 bucket) where it provides access control to specific origin. &lt;br&gt;
OAC is related to cloudfront which blocks direct access to the content in s3 bucket ensuring that all the requests are made through designated cloudfront CDN.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// origin access control for CloudFront&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudfront_origin_access_control"&lt;/span&gt; &lt;span class="s2"&gt;"cloudfront_oac"&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;"CloudFront-OAC"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"OAC for accessing S3 bucket"&lt;/span&gt;
  &lt;span class="nx"&gt;origin_access_control_origin_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt;
  &lt;span class="nx"&gt;signing_behavior&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"always"&lt;/span&gt;
  &lt;span class="nx"&gt;signing_protocol&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sigv4"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a CloudFront Distribution&lt;/strong&gt;
In this step, we will create a cloudfront distribution to serve the content from the S3 bucket.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// create CloudFront distribution&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudfront_distribution"&lt;/span&gt; &lt;span class="s2"&gt;"s3_distribution"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;domain_name&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;static_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_regional_domain_name&lt;/span&gt;
    &lt;span class="nx"&gt;origin_access_control_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_cloudfront_origin_access_control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloudfront_oac&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;origin_id&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3_origin_id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;enabled&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;is_ipv6_enabled&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;comment&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Some comment"&lt;/span&gt;
  &lt;span class="nx"&gt;default_root_object&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"index.html"&lt;/span&gt;  &lt;span class="c1"&gt;// specify the default root object (home page)&lt;/span&gt;


  &lt;span class="nx"&gt;default_cache_behavior&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;allowed_methods&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"HEAD"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;// specify allowed methods from users&lt;/span&gt;
    &lt;span class="nx"&gt;cached_methods&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"HEAD"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;// specify cached methods&lt;/span&gt;
    &lt;span class="nx"&gt;target_origin_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3_origin_id&lt;/span&gt; &lt;span class="c1"&gt;// reference to origin id&lt;/span&gt;

    &lt;span class="nx"&gt;forwarded_values&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;query_string&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;// do not forward query strings&lt;/span&gt;

      &lt;span class="nx"&gt;cookies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;forward&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"none"&lt;/span&gt; &lt;span class="c1"&gt;// do not forward cookies&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;viewer_protocol_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"redirect-to-https"&lt;/span&gt; &lt;span class="c1"&gt;// enforce HTTPS&lt;/span&gt;
    &lt;span class="nx"&gt;min_ttl&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;default_ttl&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;
    &lt;span class="nx"&gt;max_ttl&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;price_class&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PriceClass_200"&lt;/span&gt;  &lt;span class="c1"&gt;// use price class 200 for cost optimization&lt;/span&gt;

  &lt;span class="nx"&gt;restrictions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;geo_restriction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;restriction_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"none"&lt;/span&gt;  &lt;span class="c1"&gt;// allow access from all geographic locations&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;viewer_certificate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cloudfront_default_certificate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;// use default CloudFront certificate for HTTPS&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"s3_origin_id"&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;"S3-StaticWebsiteOrigin"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Output the CloudFront Domain Name&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;    &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"cloudfront_domain_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The domain name of the CloudFront distribution"&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_cloudfront_distribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3_distribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain_name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize and Apply Terraform Configuration&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;terraform init&lt;/code&gt; to initialize the Terraform configuration.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;terraform apply&lt;/code&gt; to create the resources. Review the plan and confirm the apply.&lt;/li&gt;
&lt;li&gt;After the apply is complete, note the CloudFront domain name from the output.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Your Static Website&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Open a web browser and navigate to the CloudFront domain name to see your static website in action.&lt;/li&gt;
&lt;li&gt;It will automatically redirect to HTTPS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This mini project demonstrated how to deploy a static website using AWS S3 and CloudFront with Terraform. You can further enhance this setup by adding custom domains using Route 53, SSL certificates using AWS Certificate Manager (ACM), and additional security measures as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal Output:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Static Website Accessed via CloudFront:&lt;/strong&gt;&lt;/p&gt;

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

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

&lt;p&gt;Congratulations! You have successfully deployed a static website using AWS S3 and CloudFront with Terraform.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/bK6RimAv2nQ"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-13: Data sources in Terraform</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Sun, 07 Dec 2025 18:43:11 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-13-data-sources-in-terraform-3gha</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-13-data-sources-in-terraform-3gha</guid>
      <description>&lt;p&gt;&lt;strong&gt;What are Data Sources?&lt;/strong&gt;&lt;br&gt;
Data source in terraform refers to a way to read existing resources instead of creating new ones. Data sources lookup and use the data from things that already exist in your cloud or other services. This is useful when you want to reference information about resources that are not managed by your terraform configuration.&lt;/p&gt;

&lt;p&gt;example: You can use data sources to fetch information about existing VPCs, subnets, AMIs, security groups, etc.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"data_source_type"&lt;/span&gt; &lt;span class="s2"&gt;"data_source_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# Configuration arguments&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Filters:&lt;/strong&gt;&lt;br&gt;
Filters are used in data sources to narrow down the results based on specific criteria. They help you to find the exact resource you are looking for by applying conditions just like search queries.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="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;"filter_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;"value1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"value2"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Task : Use Data Sources in Terraform AWS Provider to fetch existing resources information.
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Creating an EC2 instance by fetching the AMI ID using Data Source and Subnet ID using Data Source&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c1"&gt;# Fetch the latest Ubuntu AMI&lt;/span&gt;
&lt;span class="nx"&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;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;"amazon"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// Canonical&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Fetch existing VPC by Name tag&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc"&lt;/span&gt; &lt;span class="s2"&gt;"selected"&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;"tag: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;"shared-primary-vpc"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Fetch existing Subnet by Name tag within the selected VPC&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"selected"&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;"tag: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;"shared-primary-subnet"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Create an EC2 instance using the fetched AMI and Subnet&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"example"&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="nx"&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="s2"&gt;"t2.micro"&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selected&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;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;"day-13-instance"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// outputs.tf&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_id"&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;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_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;example&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;Now, the terraform configuration uses data sources to fetch the latest Ubuntu AMI and existing subnet information to create an EC2 instance.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/MSr67lWCyD8?start=13"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-12: AWS Terraform Functions</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Fri, 05 Dec 2025 17:48:06 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-12-aws-terraform-functions-mhn</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-12-aws-terraform-functions-mhn</guid>
      <description>&lt;p&gt;&lt;strong&gt;Advanced Functions in Terraform:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building upon the foundational functions covered in Day 11, today we explore more specialized functions that enhance Terraform's capability to handle complex data transformations, validations, and operations. These functions are essential for creating robust, production-ready infrastructure as code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types of Advanced Functions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Numeric Functions:&lt;/strong&gt;&lt;br&gt;
Numeric functions are used to perform mathematical operations and manipulate numeric values. These functions allow you to perform calculations, absolute value operations, statistical operations, and other numeric transformations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;abs()&lt;/code&gt;, &lt;code&gt;ceil()&lt;/code&gt;, &lt;code&gt;floor()&lt;/code&gt;, &lt;code&gt;max()&lt;/code&gt;, &lt;code&gt;min()&lt;/code&gt;, &lt;code&gt;sum()&lt;/code&gt;, &lt;code&gt;sqrt()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Validation Functions:&lt;/strong&gt;&lt;br&gt;
Validation functions are used to validate input values and ensure they meet specific criteria. These functions help enforce data integrity and prevent configuration errors by checking conditions and formats.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;can()&lt;/code&gt;, &lt;code&gt;regex()&lt;/code&gt;, &lt;code&gt;length()&lt;/code&gt;, &lt;code&gt;startswith()&lt;/code&gt;, &lt;code&gt;endswith()&lt;/code&gt;, &lt;code&gt;contains()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Date/Time Functions:&lt;/strong&gt;&lt;br&gt;
Date and time functions are used to manipulate and format date and time values. These functions allow you to perform operations such as parsing, formatting, timestamping, and calculating time differences.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;formatdate()&lt;/code&gt;, &lt;code&gt;timeadd()&lt;/code&gt;, &lt;code&gt;timestamp()&lt;/code&gt;, &lt;code&gt;timecmp()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;File Functions:&lt;/strong&gt;&lt;br&gt;
File functions are used to read, manipulate, and check file contents and properties. These functions allow you to read files, check file existence, work with file paths, and perform other file-related operations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;file()&lt;/code&gt;, &lt;code&gt;fileexists()&lt;/code&gt;, &lt;code&gt;dirname()&lt;/code&gt;, &lt;code&gt;basename()&lt;/code&gt;, &lt;code&gt;jsondecode()&lt;/code&gt;, &lt;code&gt;jsonencode()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Examples from DAY-12:
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Numeric Functions - Cost Analysis and Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Absolute Values and Statistical Operations:&lt;/strong&gt;&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;// variables.tf&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"monthly_cost"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The estimated monthly cost"&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;number&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;-100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;200.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;300.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// main.tf&lt;/span&gt;
&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Convert negative costs to absolute values&lt;/span&gt;
    &lt;span class="nx"&gt;absolute_monthly_cost&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;cost&lt;/span&gt; &lt;span class="nx"&gt;in&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;monthly_cost&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="c1"&gt;// Find maximum cost using max() function&lt;/span&gt;
    &lt;span class="nx"&gt;maximum_monthly_cost&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;absolute_monthly_cost&lt;/span&gt;&lt;span class="p"&gt;...)&lt;/span&gt;

    &lt;span class="c1"&gt;// Calculate total cost using sum() function&lt;/span&gt;
    &lt;span class="nx"&gt;total_monthly_cost&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;absolute_monthly_cost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// outputs.tf&lt;/span&gt;
&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"absolute_monthly_cost"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;absolute_monthly_cost&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The absolute values of the estimated monthly costs"&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;"maximum_monthly_cost"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maximum_monthly_cost&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The maximum estimated monthly cost"&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;"total_monthly_cost"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total_monthly_cost&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The total estimated monthly cost"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Validation Functions - Input Validation and Quality Control
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Regex Validation and Length Checking:&lt;/strong&gt;&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;// variables.tf&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_type"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The type of instance to use"&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;string&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="nx"&gt;validation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"^t[2-3]&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;."&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;instance_type&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nx"&gt;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"instance type must start with 't2.' or 't3.'"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;validation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;length&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;instance_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;length&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;instance_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
    &lt;span class="nx"&gt;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"length of instance type must be between 2 and 20 characters"&lt;/span&gt;
  &lt;span class="p"&gt;}&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;"backup_file_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The name of the backup file"&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;string&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;"bucket_backup"&lt;/span&gt;

    &lt;span class="nx"&gt;validation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;endswith&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;backup_file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"_backup"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"backup file must end with '_backup'"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// main.tf&lt;/span&gt;
&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&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;instance_type&lt;/span&gt;
    &lt;span class="nx"&gt;backup_file_name&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;backup_file_name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// outputs.tf&lt;/span&gt;
&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_type"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_type&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The type of instance being used"&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;"backup_file_name"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backup_file_name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Date/Time Functions - Timestamp Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Current Timestamp and Date Formatting:&lt;/strong&gt;&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="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get current timestamp&lt;/span&gt;
    &lt;span class="nx"&gt;current_time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Format timestamp to YYYY-MM-DD format&lt;/span&gt;
    &lt;span class="nx"&gt;formatted_time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formatdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"YYYY-MM-DD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Create timestamped bucket name&lt;/span&gt;
    &lt;span class="nx"&gt;bucket_name_with_timestamp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"bhaskaratejabulusu-s3-bucket-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formatted_time&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// outputs.tf&lt;/span&gt;
&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_name_with_timestamp"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_name_with_timestamp&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The S3 bucket name appended with the current timestamp"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. File Functions - Configuration File Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File Existence Checking and JSON Processing:&lt;/strong&gt;&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="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if config file exists&lt;/span&gt;
    &lt;span class="nx"&gt;config_file_exists&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileexists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./config.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Conditionally load file content based on existence&lt;/span&gt;
    &lt;span class="nx"&gt;file_config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config_file_exists&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;jsondecode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./config.json"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Get directory name from file path&lt;/span&gt;
    &lt;span class="nx"&gt;directory_name_of_file&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./config.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Read specific value from JSON file&lt;/span&gt;
    &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsondecode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./config.json"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Create JSON file from variable data&lt;/span&gt;
&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"local_file"&lt;/span&gt; &lt;span class="s2"&gt;"my_json_file"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&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;my_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my_data.json"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// variables.tf&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"my_data"&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;map&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="nx"&gt;default&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;"bhaskara"&lt;/span&gt;
    &lt;span class="nx"&gt;age&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="nx"&gt;is_active&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// outputs.tf&lt;/span&gt;
&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"file_config"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file_config&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The configuration loaded from config.json file"&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;"directory_name_of_file"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directory_name_of_file&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The directory name of the config.json file"&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;"username"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The username from the config file or default"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Collection Functions with Type Conversion - Region Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Set Operations and List Concatenation:&lt;/strong&gt;&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;// variables.tf&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"default_regions"&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;string&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="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"us-west-2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"new_regions"&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;string&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="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"eu-west-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ap-south-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sa-east-1"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// main.tf&lt;/span&gt;
&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Combine regions and remove duplicates using toset()&lt;/span&gt;
    &lt;span class="nx"&gt;combined_regions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;concat&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;default_regions&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;new_regions&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// outputs.tf&lt;/span&gt;
&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"regions"&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="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;combined_regions&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The combined unique regions from default and new regions"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Always validate inputs&lt;/strong&gt; using validation blocks with appropriate functions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle file existence&lt;/strong&gt; gracefully using &lt;code&gt;fileexists()&lt;/code&gt; before reading files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use appropriate numeric functions&lt;/strong&gt; for calculations to avoid precision issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Format timestamps consistently&lt;/strong&gt; across your infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine functions effectively&lt;/strong&gt; to create robust data transformation pipelines&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/ZYCCu9rZkU8"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-11: AWS Terraform Functions</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Thu, 04 Dec 2025 17:56:18 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-11-aws-terraform-functions-20dg</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-11-aws-terraform-functions-20dg</guid>
      <description>&lt;h2&gt;
  
  
  Functions in Terraform
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Functions:&lt;/strong&gt;&lt;br&gt;
A function is a predefined operation that takes one or more input values (arguments) and returns a single output value. Functions are used to perform common tasks, manipulate data, and transform values within Terraform configurations.&lt;br&gt;
functions increse the reusability and modularity of Terraform code, making it easier to manage and maintain infrastructure as code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In terraform, we cannot create our own functions but we can use the built-in functions provided by terraform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Types of Functions in Terraform:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validation Functions:&lt;/strong&gt;&lt;br&gt;
Validation functions are used to validate input values and ensure they meet specific criteria. These functions help enforce&lt;br&gt;
data integrity and prevent configuration errors.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;can()&lt;/code&gt;, &lt;code&gt;contains()&lt;/code&gt;, &lt;code&gt;length()&lt;/code&gt;, &lt;code&gt;regex()&lt;/code&gt;, &lt;code&gt;alltrue()&lt;/code&gt;, &lt;code&gt;anytrue()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;String Functions:&lt;/strong&gt;&lt;br&gt;
String functions are used to manipulate and transform string values. These functions allow you to perform operations such as concatenation, substring extraction, and case conversion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;concat()&lt;/code&gt;, &lt;code&gt;join()&lt;/code&gt;, &lt;code&gt;lower()&lt;/code&gt;, &lt;code&gt;upper()&lt;/code&gt;, &lt;code&gt;replace()&lt;/code&gt;, &lt;code&gt;split()&lt;/code&gt;, &lt;code&gt;trimspace()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Numeric Functions:&lt;/strong&gt;&lt;br&gt;
Numeric functions are used to perform mathematical operations and manipulate numeric values. These functions allow you to perform calculations, rounding, and other numeric transformations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;abs()&lt;/code&gt;, &lt;code&gt;ceil()&lt;/code&gt;, &lt;code&gt;floor()&lt;/code&gt;, &lt;code&gt;max()&lt;/code&gt;, &lt;code&gt;min()&lt;/code&gt;, &lt;code&gt;round()&lt;/code&gt;, &lt;code&gt;sqrt()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Collection Functions:&lt;/strong&gt;&lt;br&gt;
Collection functions are used to manipulate and transform collections such as lists, maps, and sets. These functions allow you to perform operations such as filtering, mapping, and aggregating values within collections.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;length()&lt;/code&gt;, &lt;code&gt;contains()&lt;/code&gt;, &lt;code&gt;distinct()&lt;/code&gt;, &lt;code&gt;flatten()&lt;/code&gt;, &lt;code&gt;join()&lt;/code&gt;, &lt;code&gt;lookup()&lt;/code&gt;, &lt;code&gt;merge()&lt;/code&gt;, &lt;code&gt;slice()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Type Conversion Functions:&lt;/strong&gt;&lt;br&gt;
Type conversion functions are used to convert values from one data type to another. These functions allow you to change the type of a value to ensure compatibility with other operations or functions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;tostring()&lt;/code&gt;, &lt;code&gt;tonumber()&lt;/code&gt;, &lt;code&gt;tolist()&lt;/code&gt;, &lt;code&gt;tomap()&lt;/code&gt;, &lt;code&gt;toset()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Date and Time Functions:&lt;/strong&gt;&lt;br&gt;
Date and time functions are used to manipulate and format date and time values. These functions allow you to perform operations such as parsing, formatting, and calculating time differences.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;formatdate()&lt;/code&gt;, &lt;code&gt;timeadd()&lt;/code&gt;, &lt;code&gt;timestamp()&lt;/code&gt;, &lt;code&gt;timecmp()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lookup Functions:&lt;/strong&gt;&lt;br&gt;
Lookup functions are used to retrieve values from maps or other data structures based on specified keys. These functions allow you to access specific values within complex data structures.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;lookup()&lt;/code&gt;, &lt;code&gt;element()&lt;/code&gt;, &lt;code&gt;index()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Validation Functions:&lt;/strong&gt;&lt;br&gt;
Validation functions are used to validate input values and ensure they meet specific criteria. These functions help enforce data integrity and prevent configuration errors.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;can()&lt;/code&gt;, &lt;code&gt;contains()&lt;/code&gt;, &lt;code&gt;length()&lt;/code&gt;, &lt;code&gt;regex()&lt;/code&gt;, &lt;code&gt;alltrue()&lt;/code&gt;, &lt;code&gt;anytrue()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;File Functions:&lt;/strong&gt;&lt;br&gt;
File functions are used to read and manipulate file contents. These functions allow you to read files, encode/decode file contents, and perform other file-related operations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;file()&lt;/code&gt;, &lt;code&gt;filebase64()&lt;/code&gt;, &lt;code&gt;filesha256()&lt;/code&gt;, &lt;code&gt;templatefile()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Transform "Project ALPHA Resource" → "project-alpha-resource"
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
variable "project_name" {
    default = "Project ALPHA Resource"

}

// main.tf
locals {
    formatted_name = lower(replace(var.project_name, " ", "-"))
}

//outputs.tf
output "formatted_name" {
    value = local.formatted_name
}

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

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Resource Tagging - Merge default and environment tags
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf

variable "org_tags" {
  type = map(string)
  default = {
    "org" = "haschicorp"
    "project" = "automation"
  }
}

variable "default_tags" {
    type = map(string)
    default = {
      "env" = "dev"
      "name" = "env_tags"
    }

}

// main.tf
locals{
      tags = merge(var.default_tags, var.org_tags)
}
 // outputs.tf
output "merged_tags" {
    value = local.tags
}

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

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Sanitize bucket names for AWS compliance
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
variable "inconsistent_bucket_name" {
    type = string
    default = "My.Project_ALPHA.Bucket."

}

// main.tf
locals {
    sanitized_bucket_name = lower(replace(replace(trimspace(var.inconsistent_bucket_name), "_", "-"), ".", "-"))
}

// outputs.tf
output "sanitized_bucket_name" {
    value = local.sanitized_bucket_name
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Security Group Ports - Transform "80,443,8080" into security group rules
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
variable "allowed_ports" {
    type = string
    default = "80,443,8080"

}

// main.tf

  port_list = (split(",",var.ports))

  sg_rules = [ for port in local.port_list :
    {
        name = "port-${port}"
        port = tonumber(port)
    }

   ]

// outputs.tf
output "sg_rules" {
    value = local.sg_rules
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Environment Lookup - Select instance size by environment
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
variable "environment" {
    type = string
    default = "development"

}

variable "env_instances" {
    type = map(string)
    default = {
      "dev" = "t2.medium"
      "stage" = "t2.small"  
      "prod" = "t2.large"
    }

}

// main.tf
locals {
    instance_size = lookup(var.env_instances, var.environment, "t2.micro")
}

// outputs.tf
output "instance_size" {
    value = local.instance_size
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/-dKsmU4Z1hM"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-10: Conditional expressions, Dynamic blocks, Splat expressions in terraform</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Wed, 03 Dec 2025 16:08:21 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-10-conditional-expressions-dynamic-blocks-splat-expressions-in-terraform-4j0c</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-10-conditional-expressions-dynamic-blocks-splat-expressions-in-terraform-4j0c</guid>
      <description>&lt;p&gt;&lt;strong&gt;Conditional Expressions:&lt;/strong&gt;&lt;br&gt;
Conditional expressions in Terraform allow you to choose between two values based on a condition. The syntax is &lt;code&gt;condition ? true_value : false_value&lt;/code&gt;. This is useful for setting resource attributes based on variable values or other conditions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;chose instances based on the environment (dev/prod)&lt;/li&gt;
&lt;li&gt;enable monitoring based on the configurations&lt;/li&gt;
&lt;li&gt;select different AMIs based on region&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
resource "aws_instance" "instance" {
    ami = "ami-0fa3fe0fa7920f68e"
    region = "us-east-1"
    instance_type = var.environment == "dev" ? "t3.micro" : "t3.small"
    count = var.instance_count

    tags = var.tags  
}

// variables.tf
variable "environment" {
    type = string
    default = "dev"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Splat Expressions:&lt;/strong&gt;&lt;br&gt;
Splat expressions allow you to extract multiple values from a list of objects. The syntax is &lt;code&gt;resource_type.resource_name[*].attribute&lt;/code&gt;. This is useful for retrieving attributes from multiple instances of a resource.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
resource "aws_instance" "instance" {
    ami = "ami-0fa3fe0fa7920f68e"
    region = "us-east-1"
    instance_type = var.environment == "dev" ? "t3.micro" : "t3.small"
    count = var.instance_count

    tags = var.tags  
}

// splat expression example in Terraform
output "instance_ids" {
    value = aws_instance.instance[*].id
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dynamic Blocks:&lt;/strong&gt;&lt;br&gt;
Dynamic blocks in Terraform allow you to generate multiple nested blocks within a resource based on a list or map variable. The syntax is &lt;code&gt;dynamic "block_name" { for_each = var.list_variable ... }&lt;/code&gt;. This is useful for creating multiple similar configurations without duplicating code.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf

# ingress values
variable "ingress_values" {
  type = list(object({
    from_port   = number
    to_port     = number
    protocol    = string
    cidr_blocks = list(string)
  }))

  default = [
    {
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    },
    {
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  ]
}



// main.tf

// Dynamic block example in Terraform
resource "aws_security_group" "security_group" {
    name = "sg"

    dynamic "ingress" {
        for_each = var.ingress_values
      content {
        from_port   = ingress.value.from_port
        to_port     = ingress.value.to_port
        protocol    = ingress.value.protocol
        cidr_blocks = ingress.value.cidr_blocks
      }
    }

      egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

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

&lt;/div&gt;



&lt;p&gt;So, by using conditional expressions, splat expressions, and dynamic blocks, you can create more flexible, reusable, and maintainable Terraform configurations.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/R4ShnFDJwI8"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-09: Lifecycle management rules in terraform</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Wed, 03 Dec 2025 04:21:12 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-09-lifecycle-management-rules-in-terraform-5fai</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-09-lifecycle-management-rules-in-terraform-5fai</guid>
      <description>&lt;p&gt;&lt;strong&gt;Lifecycle rules:&lt;/strong&gt;&lt;br&gt;
In terraform lifecycle rules are the ones that actually controls how the resource is created/updated/destroyed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;improve security&lt;/li&gt;
&lt;li&gt;Better maintenance of resources&lt;/li&gt;
&lt;li&gt;control over the resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are 6 rules to manage the lifecycle &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ignore_changes&lt;/li&gt;
&lt;li&gt;prevent_destroy&lt;/li&gt;
&lt;li&gt;replace_triggered_by&lt;/li&gt;
&lt;li&gt;create_before_destroy&lt;/li&gt;
&lt;li&gt;precondition&lt;/li&gt;
&lt;li&gt;postcondition&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;1. Create before destroy:&lt;/strong&gt;&lt;br&gt;
If there is any change in the resource, this rule ensures that the resource with updated changes is created and then the old resource will be destroyed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This reduces the downtime while making changes (Zero-downtime deployment)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example:&lt;br&gt;
create an instance before destroying&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
// Create before destroy to avoid downtime
resource "aws_instance" "instance" {
    ami = "ami-0f64121fa59598bf7"
    instance_type = "t3.micro"
    region = tolist(var.allowed_region)[0]

    tags = var.tags

    lifecycle {
      create_before_destroy = true
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Prevent destroy:&lt;/strong&gt;&lt;br&gt;
This rule prevents the resource from being destroyed accidentally.&lt;br&gt;
example:&lt;br&gt;
prevent destroy for s3 bucket&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
// prevent destroy to avoid accidental deletion
resource "aws_s3_bucket" "bucket" {
    bucket = "${var.username}-bucket-${var.environment}-day-09"

    lifecycle {
      prevent_destroy = true
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Ignore changes:&lt;/strong&gt;&lt;br&gt;
This rule ignores the changes made to the resource outside terraform.&lt;br&gt;
example:&lt;br&gt;
ignore changes to tags&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
// Ignore changes to tags
resource "aws_instance" "instance" {
    ami = "ami-0f64121fa59598bf7"
    instance_type = "t3.micro"
    region = tolist(var.allowed_region)[0]

    tags = var.tags

    lifecycle {
      ignore_changes = [tags]
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Replace triggered by:&lt;/strong&gt;&lt;br&gt;
This rule replaces the resource when there is a change in the specified attribute.&lt;br&gt;
example:&lt;br&gt;
replace resource when there is a change in instance_type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
// Replace instance when there is a change in instance_type
resource "aws_instance" "instance" {
    ami = "ami-0f64121fa59598bf7"
    instance_type = "t3.micro"
    region = tolist(var.allowed_region)[0]

    tags = var.tags

    lifecycle {
      replace_triggered_by = [instance_type]
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Precondition:&lt;/strong&gt;&lt;br&gt;
This rule checks the condition before creating/updating the resource.&lt;br&gt;
example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
// Precondition to check instance type
resource "aws_instance" "instance" {
    ami = "ami-0f64121fa59598bf7"
    instance_type = "t3.micro"
    region = tolist(var.allowed_region)[0]

    tags = var.tags

    lifecycle {
      precondition {
        condition     = var.instance_type == "t3.micro"
        error_message = "Instance type must be t3.micro"
      }
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Postcondition:&lt;/strong&gt;&lt;br&gt;
This rule checks the condition after creating/updating the resource.&lt;br&gt;
example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
// Postcondition to check instance state
resource "aws_instance" "instance" {
    ami = "ami-0f64121fa59598bf7"
    instance_type = "t3.micro"
    region = tolist(var.allowed_region)[0]

    tags = var.tags

    lifecycle {
      postcondition {
        condition     = aws_instance.instance.instance_state == "running"
        error_message = "Instance is not in running state"
      }
    }

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best practices:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use lifecycle rules to manage resources effectively.&lt;/li&gt;
&lt;li&gt;Always test the lifecycle rules in a non-production environment before applying them to production.&lt;/li&gt;
&lt;li&gt;Document the lifecycle rules used in the terraform code for better understanding and maintenance.&lt;/li&gt;
&lt;li&gt;Regularly review and update the lifecycle rules as per the changing requirements and best practices.&lt;/li&gt;
&lt;li&gt;Be cautious while using ignore_changes - it can hide important changes.&lt;/li&gt;
&lt;li&gt;Use create_before_destroy for critical resources to avoid downtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/60tOSwpvldY"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-08: Meta Arguments in terraform</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Tue, 02 Dec 2025 06:04:40 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-08-meta-arguments-in-terraform-4gc6</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-08-meta-arguments-in-terraform-4gc6</guid>
      <description>&lt;h2&gt;
  
  
  Meta arguments
&lt;/h2&gt;

&lt;p&gt;In terraform, the meta arguments are classified into 5 types&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;depends_on&lt;/li&gt;
&lt;li&gt;count&lt;/li&gt;
&lt;li&gt;for_each&lt;/li&gt;
&lt;li&gt;provider&lt;/li&gt;
&lt;li&gt;lifecycle&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;count:&lt;/strong&gt;&lt;br&gt;
An argument used to create multiple resources with numeric indexing.&lt;br&gt;
Usually, this is the length of the list.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;used for iterating over a list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
variable "bucket_count_list" {
    type = list(string)
    default = [ "bhaskaratejabulusu-bucket-day-08-list-1", 
                    "bhaskaratejabulusu-bucket-day-08-list-2" ]
}

// main.tf
resource "aws_s3_bucket" "bucket1" {
    count = length(var.bucket_count_list)
    bucket = var.bucket_count_list[count.index] // iterates over a list 
                                                   from 0 to [count-1]

}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;for_each&lt;/strong&gt;&lt;br&gt;
An argument in terraform to create multiple resources with map/sets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iterates over values / key-value pairs&lt;/li&gt;
&lt;li&gt;used in maps and sets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to use for_each the datatype must be either map or a set&lt;/p&gt;

&lt;p&gt;example for set and map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf

// set
variable "bucket_count_set" {
    type = set(string)
    default = [ "bhaskaratejabulusu-bucket-day-08-set-1", 
                    "bhaskaratejabulusu-bucket-day-08-set-2" ]

}

// map
variable "bucket_count_map" {
    type =  map(string)
    default = {
        "bucket1" = "bhaskaratejabulusu-bucket-day-08-map-1",
        "bucket2" = "bhaskaratejabulusu-bucket-day-08-map-2"
    }

}


// main.tf

// using set
resource "aws_s3_bucket" "bucket2" {
    for_each = var.bucket_count_set
    bucket = each.value // iterates over the set using a for loop 
                             internally and retrieves every value

}

// using map
resource "aws_s3_bucket" "bucket3" {
    for_each = var.bucket_count_map
    bucket = each.value

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;depends_on&lt;/strong&gt;&lt;br&gt;
An argument used to explicitly specify that a resource or module must be created or updated after one or more other resources or modules. It establishes a manual dependency, ensuring the correct order of operations, even when there’s no direct reference between the resources.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.tf
resource "aws_s3_bucket" "bucket1" {
    count = length(var.bucket_count_list)
    bucket = var.bucket_count_list[count.index]

}

resource "aws_s3_bucket" "bucket2" {
    for_each = var.bucket_count_set
    bucket = each.value

    depends_on = [ aws_s3_bucket.bucket1 ]

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

&lt;/div&gt;



&lt;p&gt;In the above code, the bucket2 is dependent on bucket1 so terraform will wait for bucket1 to be created and then bucket2 will be created ensuring the correct order.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/XMMsnkovNX4?start=1473"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-07: AWS Terraform Type constraints</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Mon, 01 Dec 2025 17:23:13 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-07-aws-terraform-type-constraints-5ad</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-07-aws-terraform-type-constraints-5ad</guid>
      <description>&lt;h2&gt;
  
  
  Terraform Variable Type Constraint Tasks
&lt;/h2&gt;

&lt;p&gt;The variables in terraform are classified into two types&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Based on Purpose&lt;/li&gt;
&lt;li&gt;Based on value (Type Constraints)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Type constraints are again classified into three types&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primitive --&amp;gt; String, Number, Bool&lt;/li&gt;
&lt;li&gt;Complex --&amp;gt; List, Set, Tuple, Map, Object&lt;/li&gt;
&lt;li&gt;Null and Any&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see one by one&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;String:&lt;/strong&gt;&lt;br&gt;
Combination of characters is known as a string. in terraform the string is enclosed between quotes&lt;br&gt;
example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;environment - "development"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Use the simple &lt;code&gt;string&lt;/code&gt; type variables to set the AWS Provider configuration and apply a basic naming convention.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf

variable "environment" {
    type = string
    description = "The environment for the resources"
    default = "dev"
}

// main.tf
resource "aws_s3_bucket" "bucket" {
  bucket = "${local.bucket_name}-bucket-${var.environment}"
  region = var.region

  tags = {
    Name        = "My S3 bucket"
    Environment = var.environment
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Number:&lt;/strong&gt;&lt;br&gt;
The number type constraint in terrraform is just a simple numeric value.&lt;br&gt;
example:&lt;br&gt;
count=1&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Use the &lt;code&gt;number&lt;/code&gt; constraint to define the desired quantity of a resource using Terraform’s &lt;code&gt;count&lt;/code&gt; argument.&lt;br&gt;
&lt;/p&gt;

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

// variables.tf
variable "instance_count" {
    type = number
    description = "Number of EC2 instances to create"
    default = 1
}

//main.tf
resource "aws_instance" "ec2_instance" {
  ami = "ami-0fa3fe0fa7920f68e"
  count = var.instance_count

}

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

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Boolean:&lt;/strong&gt;&lt;br&gt;
The boolean constraint in terraform is defined as the value which is either true or false&lt;br&gt;
example:&lt;br&gt;
monitoring = true&lt;/p&gt;

&lt;p&gt;example code:&lt;br&gt;
&lt;strong&gt;Objective:&lt;/strong&gt; Use &lt;code&gt;bool&lt;/code&gt; variables to control binary configuration settings (true/false flags) for AWS resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
variable "monitoring_enabled" {
    type = bool
    default = true
}

variable "associate_public_ip" {
    type = bool
    default = true
}

// main.tf

# Create an ec2 instance
resource "aws_instance" "ec2_instance" {
  ami = "ami-0fa3fe0fa7920f68e"
  count = var.instance_count
  monitoring = var.config.monitoring
  associate_public_ip_address = var.associate_public_ip

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

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;List:&lt;/strong&gt;&lt;br&gt;
The list in terraform is an ordered collection of elements of same type&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;duplicates are allowed&lt;/li&gt;
&lt;li&gt;elements in list are accessed using index
example:
regions = ["us-east-1","us-west-1","eu-west-1"]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example code:&lt;br&gt;
&lt;strong&gt;Objective:&lt;/strong&gt; Use a &lt;code&gt;list(string)&lt;/code&gt; to define multiple, ordered values of the same type for sequential use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
# CIDR block
variable "cidr_block" {
    type = list(string)
    default = [ "10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12" ]
}

# Allowed VM Types
variable "allowed_vm_types" {
    type = list(string)
    default = [ "t2.micro", "t2.small", "t3.micro", "t3.small" ]
}

// main.tf

# Create an ec2 instance
resource "aws_instance" "ec2_instance" {
  ami = "ami-0fa3fe0fa7920f68e"
  instance_type = var.allowed_vm_types[2]
  count = var.instance_count
  monitoring = var.config.monitoring
  associate_public_ip_address = var.associate_public_ip


  tags = var.tags
}


# Create a VPC
resource "aws_vpc" "myvpc" {
  cidr_block = var.cidr_block[1]

  tags = {
    Name = "Default VPC"
  }
}

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

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Set:&lt;/strong&gt;&lt;br&gt;
A set in terraform is an unordered collection of unique elements of same type.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;duplicate values are not allowed&lt;/li&gt;
&lt;li&gt;should be accessed using values (no index)&lt;/li&gt;
&lt;li&gt;tolist(): method that converts a set to list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example:&lt;br&gt;
[ "us-east-1", "us-west-2", "eu-west-1" ]&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Use a &lt;code&gt;set(string)&lt;/code&gt; to define a collection of unique, unordered values, typically for validation purposes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
# Allowed regions
variable "allowed_region" {
    type = set(string)
    default = [ "us-east-1", "us-west-2", "eu-west-1" ]

}

// providers.tf
provider "aws" {
  region = var.config.region
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Map:&lt;/strong&gt;&lt;br&gt;
Map in terraform is the collection of key-value pairs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accessed using keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example code:&lt;br&gt;
&lt;strong&gt;Objective:&lt;/strong&gt; Use a &lt;code&gt;map(string)&lt;/code&gt; to pass dynamic key-value pairs, primarily for resource metadata and cost allocation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
# tags variable
variable "tags" {
    type = map(string)
    default = {
        Environment = "dev", 
        Name = "dev-Instance", 
        created_by = "terraform"
    }
}

//main.tf
resource "aws_instance" "ec2_instance" {
  ami = "ami-0fa3fe0fa7920f68e"

  tags = var.tags // using map
}


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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tuple:&lt;/strong&gt;&lt;br&gt;
Tuple is an ordered collection of elements where each element can be of different type&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accessed through index&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example code:&lt;br&gt;
&lt;strong&gt;Objective:&lt;/strong&gt; Use a &lt;code&gt;tuple&lt;/code&gt; to enforce a rigid structure where the position and type of elements are strictly defined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
# Ingress values
variable "ingress_values" {
    type = tuple([ number, string, number ])
    default = [ 443, "tcp", 443 ]

}

//main.tf
# Create Security Group to allow TLS traffic

resource "aws_security_group" "allow_tls" {
  name        = "allow_tls"
  description = "Allow TLS inbound traffic and all outbound traffic"
  vpc_id      = aws_vpc.myvpc.id

  tags = {
    Name = "allow_tls"
  }
}

resource "aws_vpc_security_group_ingress_rule" "allow_tls_ipv4" {
  security_group_id = aws_security_group.allow_tls.id
  cidr_ipv4         = var.cidr_block[1]
  from_port         = var.ingress_values[0]
  ip_protocol       = var.ingress_values[1]
  to_port           = var.ingress_values[2]
  description       = "Allow TLS inbound traffic from specific CIDR block"
}


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

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Object:&lt;/strong&gt;&lt;br&gt;
Object is a collection of named attributes, where each attribute has a defined type.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accessed via dot notation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example code:&lt;br&gt;
&lt;strong&gt;Objective:&lt;/strong&gt; Use an &lt;code&gt;object&lt;/code&gt; to group multiple configuration values of different types under a single variable, improving code organization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// variables.tf
variable "config" {
    type = object({
      region = string
      monitoring = bool
      instance_count = number
    })
    default = {
      region = "us-east-1"
      monitoring = true
      instance_count = 1
    }
}

// main.tf
resource "aws_instance" "ec2_instance" {
  ami = "ami-0fa3fe0fa7920f68e"
  count = var.config.instance_count
  monitoring = var.config.monitoring
  region = var.config.region
}

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

&lt;/div&gt;



&lt;p&gt;In this way we use the type constraints in different use cases.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/gu2oCJ9DQiQ"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-06: AWS Terraform Project Structure Best practices</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Sat, 29 Nov 2025 17:58:07 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-06-aws-terraform-project-structure-best-practices-2a76</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-06-aws-terraform-project-structure-best-practices-2a76</guid>
      <description>&lt;p&gt;&lt;strong&gt;File Structure&lt;/strong&gt;&lt;br&gt;
Keeping everything such as variables, locals, providers, backend, outputs, resources related code in one file isn't a best practice and becomes an overhead as infrastructure grows and unmanageable.&lt;/p&gt;

&lt;p&gt;There is a standard structure that needs to be followed by every DevOps engineer which is essential for scalability and maintainability and one of the recommended project structure is:&lt;/p&gt;

&lt;p&gt;project-root/&lt;br&gt;
├── backend.tf           # Backend configuration&lt;br&gt;
├── provider.tf          # Provider configurations&lt;br&gt;
├── variables.tf         # Input variable definitions&lt;br&gt;
├── locals.tf           # Local value definitions&lt;br&gt;
├── main.tf             # Main resource definitions&lt;br&gt;
├── vpc.tf              # VPC-related resources&lt;br&gt;
├── security.tf         # Security groups, NACLs&lt;br&gt;
├── compute.tf          # EC2, Auto Scaling, etc.&lt;br&gt;
├── storage.tf          # S3, EBS, EFS resources&lt;br&gt;
├── database.tf         # RDS, DynamoDB resources&lt;br&gt;
├── outputs.tf          # Output definitions&lt;br&gt;
├── terraform.tfvars   # Variable values&lt;br&gt;
└── README.md           # Documentation&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform File Loading&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform loads all the files with .tf extension in the current directory&lt;/li&gt;
&lt;li&gt;Terraform loads the files in lexicographical order (Alphabetical)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;File names doesn't affect any code inside them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The above file structure is just an example and recommended by Hashicorp  and this varies from organization and their use case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another approach is to separate the files based on the environments or based on the resources as well&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;File organization principles&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separation of concerns&lt;/li&gt;
&lt;li&gt;Logical Grouping&lt;/li&gt;
&lt;li&gt;Consistent naming&lt;/li&gt;
&lt;li&gt;Modular Approach&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best practices&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent naming of file names&lt;/li&gt;
&lt;li&gt;Split the files based on functionality&lt;/li&gt;
&lt;li&gt;Size management - keep files manageable (&amp;lt;500 lines)&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Logical Grouping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A well organized structure not only improves readability but also streamlines collaboration and long term maintenance &lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/QMsJholPkDY"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-05: Terraform variables in AWS</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Fri, 28 Nov 2025 15:39:40 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-05-terraform-variables-in-aws-aa1</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-05-terraform-variables-in-aws-aa1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Why do we need variables ?&lt;/strong&gt;&lt;br&gt;
To use the specific value repeatedly such as environment, tag names, bucket names etc., instead of writing the same value everywhere we just store them and use when needed which increases reusability in the code. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;br&gt;
Variables are classified into two types&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Based on purpose&lt;/li&gt;
&lt;li&gt;Based on Value&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Based on Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input&lt;/li&gt;
&lt;li&gt;Output&lt;/li&gt;
&lt;li&gt;Local&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Based on value&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primitive --&amp;gt; String, number, bool&lt;/li&gt;
&lt;li&gt;Complex --&amp;gt; list, tuple, set, map, object&lt;/li&gt;
&lt;li&gt;ANY and NULL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Input Variables&lt;/strong&gt;&lt;br&gt;
variables which are used in the code when needed&lt;br&gt;
Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "variable_name"{

     default = "dev"
     type = string  //this is not mandatory. if you don't mention the type of the variable, the terraform will autodetect and use ANY type
}

# Accessing the Variable
var.variable_name
${} // for concatenation of string

#Example:
Name = "${var.variable_name} - Bucket"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Local variables&lt;/strong&gt;&lt;br&gt;
variables declared in the locals block and accessed anywhere in the code&lt;br&gt;
Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;locals{
   env = "value"
   bucket_name="value"
}

#Accessing locals
local.local_variable_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output Variable&lt;/strong&gt;&lt;br&gt;
the variable which gives output once the resource has been provisioned and the output variables are generally printed on the console&lt;br&gt;
Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "variable_name"{
    value = value // Value of the variable you want as output
    description = "description_about_the_output_variable"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ways to declare variables&lt;/strong&gt;&lt;br&gt;
we can declare variables in many ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the default&lt;/li&gt;
&lt;li&gt;Environment variables
&lt;code&gt;export TF_VAR_variable_name="variable_value"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;using terraform.tfvars file 
&lt;code&gt;variable = "variable_value"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;using terraform.tfvars.json file (similar to terraform.tfvars file but in json format)&lt;/li&gt;
&lt;li&gt;*auto.tfvars (or) *.auto.tfvars.json files&lt;/li&gt;
&lt;li&gt;ANY -var in CLI
&lt;code&gt;terraform plan -var="variable=variable_value"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;ANY -var-file (variable files)
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In variables.tfvars
variable "variable_name"{
   default = "variable_value"
}

# Use this file in command line
terraform plan -var-file=variables.tfvars

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

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Commands&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform output  #show all outputs
terraform output variable_name      # show the output of specific variable
terraform output -json       #show the outputs in json format

# Clean up 
unset TF_VAR_variable_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way we create variables in different ways.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/V-2yC39BONc"&gt;
  &lt;/iframe&gt;


&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day-04: Terraform state file management using S3 Bucket</title>
      <dc:creator>Bhaskara teja Bulusu</dc:creator>
      <pubDate>Thu, 27 Nov 2025 13:40:24 +0000</pubDate>
      <link>https://forem.com/bhaskara_tejabulusu_b4bf/day-04-terraform-state-file-management-using-s3-bucket-1jll</link>
      <guid>https://forem.com/bhaskara_tejabulusu_b4bf/day-04-terraform-state-file-management-using-s3-bucket-1jll</guid>
      <description>&lt;h2&gt;
  
  
  How terraform updates Infrastructure ?
&lt;/h2&gt;

&lt;p&gt;When we run the terraform apply command, some files are created such as terraform.tfstate, terraform.tfstate.backup and terraform compares desired state with the actual state and provision the resources and update the infrastructure accordingly.&lt;/p&gt;

&lt;p&gt;Desired state: The infrastructure we wish to create&lt;br&gt;
Actual state: The current infrastructure we are having&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;State file management&lt;/strong&gt;&lt;br&gt;
In the terraform.tfstate, terraform.tfstate.backup files, sensitive information such as account Id's and resource names are present and in addition to that, modifying these files makes the state files corrupted. So, we shouldn't store in the production server or locally. To overcome this we store the state files in the remote backend instead of storing directly in the server&lt;/p&gt;

&lt;p&gt;Storing the state files in the remote backend such as AWS S3 secures and stores separately which is easy to manage.&lt;/p&gt;

&lt;p&gt;State file Best practices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Store file to Remote backend&lt;/li&gt;
&lt;li&gt;Don't update/delete the files&lt;/li&gt;
&lt;li&gt;State locking --&amp;gt; a process which locks the file making the file inaccessible for others&lt;/li&gt;
&lt;li&gt;Isolation of state file --&amp;gt; separate state files for different environments&lt;/li&gt;
&lt;li&gt;Regular backup&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Code for storing state files in the Remote backend (S3 Bucket)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" {
    bucket = "bhaskaratejabulusu-state-files-day04"
    key = "dev/terraform.tfstate"
    region = "us-east-1"
    encrypt = true
    use_lockfile = true

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

&lt;/div&gt;



&lt;p&gt;Make sure that the remote backend in this case S3 bucket is already created/available before running the terraform commands.&lt;br&gt;
Usually this is done by CI/CD pipeline before terraform provisions resources&lt;/p&gt;

&lt;p&gt;Security in S3 bucket:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;S3 versioning enable&lt;/li&gt;
&lt;li&gt;IAM minimal to S3&lt;/li&gt;
&lt;li&gt;S3 Bucket Policy&lt;/li&gt;
&lt;li&gt;Encryption (Server Side Encryption)&lt;/li&gt;
&lt;li&gt;Access Logging&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;terraform state list&lt;/code&gt;&lt;br&gt;
You can use the above command to list resources in state&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/YsEdrl9O5os"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/piyushsachdeva"&gt;@piyushsachdeva&lt;/a&gt; &lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
