<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Moncif TOUBOUH on Medium]]></title>
        <description><![CDATA[Stories by Moncif TOUBOUH on Medium]]></description>
        <link>https://medium.com/@toubouhmoncif?source=rss-58fbf080b3d8------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*LAAMDXvbk2OXnjEKd3NDig.jpeg</url>
            <title>Stories by Moncif TOUBOUH on Medium</title>
            <link>https://medium.com/@toubouhmoncif?source=rss-58fbf080b3d8------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 07 Jul 2026 03:54:20 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@toubouhmoncif/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Keep Terraform DRY]]></title>
            <link>https://medium.com/devoteam-g-cloud/keep-terraform-dry-93c7b417e272?source=rss-58fbf080b3d8------2</link>
            <guid isPermaLink="false">https://medium.com/p/93c7b417e272</guid>
            <category><![CDATA[terraform]]></category>
            <category><![CDATA[gcp]]></category>
            <category><![CDATA[terragrunt]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[sre]]></category>
            <dc:creator><![CDATA[Moncif TOUBOUH]]></dc:creator>
            <pubDate>Mon, 07 Oct 2024 09:07:20 GMT</pubDate>
            <atom:updated>2024-10-17T15:01:37.673Z</atom:updated>
            <content:encoded><![CDATA[<p>How to Keep Your Infrastructure Code Clean and Efficient?</p><p><strong><em>Introduction</em></strong></p><p>In this article, I will introduce <strong>Terragrunt </strong>a widely-used tool that enhances Terraform by promoting DRY practices. I will also show you how to deploy resources on the Google Cloud Platform (GCP) using Terragrunt.</p><p>By walking through a practical example, you’ll learn how to streamline your Terraform configurations, improve code maintainability, and efficiently manage your cloud infrastructure in GCP.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9i5JxlnWC_6pWnmJ8XUiCw.png" /></figure><p>Notice: Before proceeding with this article, ensure you have a basic understanding of <strong>Terraform</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/890/1*KDa27RsEfeCSkpQ7bIXyZw.png" /></figure><p>Terraform is an Infrastructure as Code (IAC) tool that provisions and manages infrastructure (resources) in any cloud or data center. It’s a powerful tool for IAC, but it can encounter many challenges as projects grow. For example, Terraform configurations can become repetitive and duplicated, especially when handling multiple environments and components, leading to maintenance difficulties.</p><p>Additionally, Terraform modules can depend on each other, complicating management and increasing the risk of errors due to manual oversight.</p><p>Managing a remote state can also become complex and challenging in large projects, especially when working with multiple environments and different teams. Similarly, provisioning and managing resources across multiple environments and reusing the same components can be tedious and difficult.</p><p>Terragrunt offers solutions to all of these challenges.</p><blockquote><strong><em>key features</em></strong></blockquote><h4>Keep Terraform DRY</h4><p>Abstractions, or the “Don’t Repeat Yourself” (DRY) principle, is a well-known software engineering pattern that aims to reduce duplicated code to avoid managing extra configurations and to simplify making changes across the system, which can otherwise be error-prone.</p><p>Terragrunt allows you to share configurations across multiple Terraform modules or environments by defining for example the backend configurations, provider configurations, and variables at the root level. This way, all child modules can inherit these settings, eliminating repetition and promoting reusability.</p><h4>State Management:</h4><p>Terragrunt stores state files remotely, automatically creating and enabling locking resources (bucket) automatically to manage states. It helps to avoid some manual errors, state overwrites, and shares states across teams. As a result, you can be sure that you are using the correct state configuration without any manual configuration of your modules.</p><h4>Dependency Management</h4><p>Usually terraform modules depend on each other; for example, a database or computer instance may depend on the network, requiring you to manage the order in which modules are deployed. Terragrunt allows you to manage dependencies between modules explicitly, ensuring resources are provisioned in the correct order. Additionally, the outputs of modules can be passed to others, streamlining the process.</p><h4>Environment Management</h4><p>Managing multiple environments with Terraform requires additional configuration and management through workspaces and variables, which can be tedious and error-prone. Terragrunt simplifies this process by allowing you to define separate configuration files for each environment, reducing code duplication and minimizing errors.</p><h4>Clarity and Workflow</h4><p>In large projects with many teams, modules, and resources, Terraform can make it challenging to manage the workflow (init, plan, apply, etc.) across different environments, teams, and modules. Additionally, the configuration files can become cluttered and difficult to maintain. Terragrunt simplifies this by automatically running Terraform commands in the correct order across modules, eliminating the need for manual executing and keeping files organized.</p><h3>Uses Case</h3><p>This example is not intended for production use; it demonstrates key features of Terragrunt. It helps keep your terraform code DRY, remote state configuration DRY, and Terragrunt architecture DRY.</p><p>This project deploys (a GCE, a MySQL database, an Instance Template, and a VPC) in three environments (dev, stage, and prod)</p><p>This project utilizes public Terraform modules for GCP and is inspired by the official Terragrunt documentation.</p><h4><strong><em>Source </em></strong>Code<strong><em>:</em></strong></h4><p><a href="https://github.com/Moncif1/hello_terragrunt">GitHub - Moncif1/hello_terragrunt</a></p><p>This project organizes and manages different environments and modules, leveraging Terragrunt’s capabilities to simplify the configuration and promote DRY (Don’t Repeat Yourself) principles.</p><p>The configuration is designed to be modular and reusable, with a central configuration inherited across different environments or modules.</p><p>This setup allows for centralizing configurations, making managing and maintaining common settings across multiple environments and modules easier. Any variables, remote state configurations, or other settings defined in the parent `terragrunt.hcl` will be applied to the module.</p><h3>Keep Your Terraform DRY</h3><pre>├── development<br>│   ├── db<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   ├── gce<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   ├── template<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   ├── vpc<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   └── env-vars.hcl<br>│    ...   <br>├── production<br>│   ├── db<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   ├── gce<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   ├── template<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   ├── vpc<br>│   │   └── terragrunt.hcl<br>│   │   └── module-vars.hcl<br>│   │   └── Readme.md<br>│   └── env-vars.hcl<br>└── terragrunt.hcl<br>└── Readme.md       <br>└── common-vars.hcl</pre><p>This architecture manages different environments (development, stageand production) and various components (db, gce, template, vpc).</p><ul><li>terragrunt.hcl at the root level is used for setting global configurations applicable across all environments and modules.</li><li>common-vars.hcl contains common variable definitions shared among different modules and environments.</li><li>env-vars.hcl contains environment-specific variable definitions.</li></ul><p>In each environment, you have different components (e.g., db, gce, template, vpc). Each component directory contains its own terragrunt.hcl and module-vars.hcl files.</p><h4>Notes:</h4><p>This Terragrunt Project does the following:</p><ol><li><strong>Loads Configuration Variables</strong>:</li></ol><ul><li><strong>Common Variables</strong>: Loads common infrastructure variables from common-vars.hcl.</li><li><strong>Environment Variables</strong>: Loads environment-specific variables from env-vars.hcl.</li><li><strong>Module Variables</strong>: Loads module-specific variables from module-vars.hcl.</li></ul><pre>locals {<br>  # Load Hello World Infra variables<br>  common_vars = read_terragrunt_config(find_in_parent_folders(&quot;common-vars.hcl&quot;))<br><br>  # Load Env variables<br>  env_vars = read_terragrunt_config(find_in_parent_folders(&quot;env-vars.hcl&quot;))<br><br>  # Load Module variables<br>  module_vars = read_terragrunt_config(&quot;./module-vars.hcl&quot;)<br>  env            = local.env_vars.locals.env<br>  project_id = local.env_vars.locals.project_id<br>  module_name    = local.module_vars.locals.module_name<br>  module_source  = local.common_vars.locals[&quot;${local.module_name}_base_url&quot;]<br>  module_version = local.common_vars.locals[&quot;${local.module_name}_base_version&quot;]<br>}</pre><p><strong>2. Remote State</strong></p><ul><li>Creates Remote State for each component</li><li>every component state will be managed in a different state file</li><li>Google Cloud Storage (GCS) is the backend for storing Terraform state files.</li></ul><pre>remote_state {<br>  backend = &quot;gcs&quot;<br><br>  config = {<br>    project = &quot;${local.project_id}&quot;<br>    location = &quot;eu&quot;<br>    bucket   = &quot;hw-tf-backend-${local.env}&quot;<br>    prefix   = &quot;hw/dsi/${local.module_name}&quot;<br>    credentials = &quot;${get_env(&quot;GOOGLE_APPLICATION_CREDENTIALS&quot;)}&quot;<br>  }<br><br>  generate = {<br>    path      = &quot;backend.tf&quot;<br>    if_exists = &quot;overwrite_terragrunt&quot;<br>  }<br>}</pre><p><strong>3. Inputs</strong></p><ul><li>Merges the variables from the common, environment, and module-specific configurations. (Pay attention to the order, the last value is the module value)</li></ul><pre>inputs = merge(<br>  local.common_vars.locals,<br>  local.env_vars.locals,<br>  local.module_vars.locals<br>)</pre><p><strong>4. Terraform Source</strong></p><ul><li>Specifies the source and version of the Terraform module to be used, which may vary across environments.</li></ul><pre>terraform {<br>  source  = &quot;${local.module_source}=${local.module_version}&quot;<br>}</pre><h4>5. Component</h4><p>Each component (such as DB or GCE) makes use of Terragrunt’s features, including inheriting parent configurations, managing dependencies, and dynamically passing inputs.</p><pre>include &quot;root&quot; {<br>  path = find_in_parent_folders()<br>}<br><br><br>dependency &quot;vpc&quot; {<br>  config_path = &quot;../vpc&quot;<br>  mock_outputs_merge_with_state = true<br>    mock_outputs        = {<br>      subnetwork = &quot;hw-network-self-link&quot;<br>    }<br><br>}<br><br><br>inputs = {<br>  subnetwork = dependency.vpc.outputs.subnetwork,<br>}</pre><p>Terragrunt configuration file does the following:</p><ol><li><strong>Includes Parent Configuration</strong>: Inherits configurations from a parent terragrunt.hcl file, enabling consistent settings across environments and avoiding duplication.</li><li><strong>Manages Dependencies</strong>: Defines a dependency to vpc</li><li><strong>Passes Inputs</strong>: Uses the outputs from dependencies as inputs to other modules, allowing dynamic infrastructure management.</li></ol><p>By following this setup, you can manage your Terraform infrastructure dynamically and efficiently across different environments and modules, keeping it modular and maintainable.</p><p><strong>For more details about the project, please refer to the README file.</strong></p><h4>Usage:</h4><h4><strong>Basic command:</strong></h4><p>Most Terragrunt commands use the Terraform command.</p><ul><li>Terragrunt will automatically call Terragrunt init during other commands (e.g. terragrunt plan).</li></ul><pre>Terragrunt init ===&gt; creates automatically the bucket for remote state<br>Terragrunt plan <br>Terragrunt apply<br>Terragrunt destroy<br># for multiples modules at ones<br>Terrragrunt run-all plan<br>Terrragrunt run-all apply <br>Terrragrunt run-all destroy</pre><ul><li>You can deploy the project (Hello World), by component or at once.</li></ul><h3><strong>Conclusion:</strong></h3><p>Through this article, we’ve explored an example of how to use Terragrunt to deploy resources on the Google Cloud Platform with different environments, illustrating the practical benefits of adopting DRY practices in Terraform.</p><p>By integrating Terragrunt into your workflow, you can streamline your infrastructure management, making your codebase cleaner, more organized, and easier to maintain over the long term.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=93c7b417e272" width="1" height="1" alt=""><hr><p><a href="https://medium.com/devoteam-g-cloud/keep-terraform-dry-93c7b417e272">Keep Terraform DRY</a> was originally published in <a href="https://medium.com/devoteam-g-cloud">Devoteam I Google Cloud Partner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>