diff --git a/docs/_docs/01_getting-started/overview.md b/docs/_docs/01_getting-started/overview.md index dc4e301c5..847ae6cc1 100644 --- a/docs/_docs/01_getting-started/overview.md +++ b/docs/_docs/01_getting-started/overview.md @@ -9,8 +9,6 @@ nav_title: Documentation nav_title_link: /docs/ --- -## Overview - The following is a simple overview of the main features in Terragrunt. It includes configurations that are a bit more complex than the ones found in the [Quick Start](/docs/getting-started/overview), but don't panic! @@ -19,10 +17,21 @@ We'll walk you through each one, and you don't need to understand everything rig This guide is geared towards users who have either already gone through the [Quick Start](/docs/getting-started/overview) or are joining a team of users that are already using Terragrunt. As a consequence, we'll be using more complex configurations, discussing more advanced features, and showing how to use Terragrunt to manage real AWS infrastructure. -If you don't have an AWS account, you can either sign up for a free tier account at [aws.amazon.com](https://aws.amazon.com/) or adapt the examples to use a different cloud provider. - If you are unfamiliar with OpenTofu/Terraform, you may want to also read [OpenTofu](https://opentofu.org/docs/intro/) or [Terraform](https://developer.hashicorp.com/terraform/intro) documentation after reading this guide. +## Following Along + +What follows isn't a tutorial in the same sense as the [Quick Start](/docs/getting-started/overview), but more of a guided tour of some of the more commonly used features of Terragrunt. You don't need to follow along to understand the concepts, but if you want to, you can. + +The code samples provided here are available as individual "steps" [here](https://github.com/gruntwork-io/terragrunt/tree/main/test/fixtures/docs/02-overview). + + +If you would prefer it, you can clone the [Terragrunt repository](https://github.com/gruntwork-io/terragrunt.git), and follow along with the examples in your own environment without any copy + paste. + +Just make sure to replace the values prefixed `__FILL_IN_` with values relevant to your AWS account. + +If you don't have an AWS account, you can either sign up for a free tier account at [aws.amazon.com](https://aws.amazon.com/) or adapt the examples to use a different cloud provider. + ## Example Here is a typical `terragrunt.hcl` file you might find in a Terragrunt project\*: @@ -81,7 +90,7 @@ inputs = { private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] - enable_nat_gateway = true + enable_nat_gateway = false enable_vpn_gateway = false tags = { @@ -172,7 +181,7 @@ You'll notice that in the examples above, we were using `find` to locate the `.t Over the years supporting customers managing IaC at scale, the patterns that we've seen emerge for really successful organizations is to treat OpenTofu/Terraform modules as versioned, generic, well tested patterns of infrastructure, and to deploy them in as close to the exact same way as possible across all uses of them. -Terragrunt supports this pattern by treating each unit of Terragrunt configuration (a directory with a `terragrunt.hcl` file in it) as a hermetic container of infrastructure that can be reasoned about in isolation, and then composed together to form a larger system of one or more stacks (each stack being a collection of units). +Terragrunt supports this pattern by treating each [unit](/docs/getting-started/terminology/#unit) of Terragrunt configuration (a directory with a `terragrunt.hcl` file in it) as a hermetic container of infrastructure that can be reasoned about in isolation, and then composed together to form a larger system of one or more [stacks](/docs/getting-started/terminology/#stack) (each stack being a collection of units). To that end, the way that Terragrunt loads OpenTofu/Terraform configurations is to download them into a subdirectory of the `.terragrunt-cache` directory, and then to orchestrate OpenTofu/Terraform commands from that directory. This ensures that the OpenTofu/Terraform modules are treated as immutable, versioned, and hermetic, and that the OpenTofu/Terraform runs are reliably reproducible. @@ -218,9 +227,9 @@ This statement above is kind of a lie: \* Here is a typical `terragrunt.hcl` file you might find in a Terragrunt project. -The truth is, you'll almost never see configuration like that outside of some tests or examples. The reason for this is that one of the main responsibilities Terragrunt has is to scale IaC, and the configuration above would result in quite a lot of code duplication across a project. In an AWS project for example, you will probably use the same (or very similar) `provider` configuration across all your modules, and you'll probably use the same `backend` configuration across all your modules (with the only exception being the `key` for where in S3 your state should be stored). +The truth is, you'll almost never see configuration like that outside of some tests or examples. The reason for this is that one of the main responsibilities Terragrunt has is to scale IaC, and the configuration above would result in quite a lot of code duplication across a project. In an AWS project for example, you will probably use the same (or very similar) `provider` configuration across all your units, and you'll probably use the same `backend` configuration across all your units (with the only exception being the `key` for where in S3 your state should be stored). -Aware of this pattern, Terragrunt is designed to leverage a hierarchy of reusable configurations so that your code can be DRY (Don't Repeat Yourself). +Aware of this pattern, Terragrunt is designed to leverage a hierarchy of reusable configurations so that your code can be [DRY (Don't Repeat Yourself)](/docs/getting-started/terminology#dont-repeat-yourself-dry). ### The `include` block @@ -287,7 +296,7 @@ inputs = { private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] - enable_nat_gateway = true + enable_nat_gateway = false enable_vpn_gateway = false tags = { @@ -303,6 +312,8 @@ When you see `include` blocks in Terragrunt, remember that they result in the co The exception to this is when you are using directives that explicitly leverage the fact that configurations are being included. +### Building out the stack + For example, say you wanted to add another unit of infrastructure into the _stack_ that you're building out here. You could create a new directory named `ec2`, and add a `terragrunt.hcl` file to it like this: ```hcl @@ -333,6 +344,8 @@ inputs = { } ``` +### Key Collisions + If you tried to run `terragrunt plan` in that new `ec2` directory, you'd get an error that looked like this: ```bash @@ -373,6 +386,8 @@ terraform { } ``` +### Dynamic keys + What most folks would really prefer here is to have the state for the `ec2` unit stored in a different, but predictable, location relative to the `vpc` unit. The pattern that we've found to be most effective is to store state so that the location in the remote backend, like S3 mirrors the location of the unit on the filesystem. @@ -433,6 +448,12 @@ EOF What this does is set the `key` attribute of the generated `backend.tf` file to be the relative path from the `root.hcl` file to the `terragrunt.hcl` file that is being processed. +### Migrating state + +You have to be careful when adjusting the `key` attribute of units (including when moving units around in the filesystem, if you use something like `path_relative_to_include` to drive the value of the `key` attribute) because it can result in state being stored in a different location in the remote backend. + +There's native tooling in OpenTofu/Terraform to support these procedures, but you want to be confident you know what you're doing when you run them. By default, Terragrunt will provision a remote backend that uses versioning, so you can always roll back to a previous state if you need to. + ```bash # First, we'll migrate state to the new location $ terragrunt init -migrate-state @@ -471,7 +492,11 @@ terraform { Following this pattern, you can create as many units of infrastructure in your project as you like without worrying about collisions in remote state keys. -Note that while this is the idiomatic approach for defining the `key` attribute for your `backend` configuration, it is not a requirement. You can set the `key` attribute to any value you like, and you can use any Terragrunt HCL function to generate that value dynamically such that you avoid collisions in your remote state. Just make sure to test your configuration carefully, and document your approach so that others can understand what you're doing. +Note that while this is the idiomatic approach for defining the `key` attribute for your `backend` configuration, it is not a requirement. You can set the `key` attribute to any value you like, and you can use any Terragrunt HCL function to generate that value dynamically such that you avoid collisions in your remote state. + +Another completely valid approach, for example, is to utilize [get_repo_root](/docs/reference/built-in-functions/#get_repo_root), which returns a path relative to the root of the git repository. This, of course, has the drawback that it will not work if you are not using git. + +Just make sure to test your configuration carefully, and document your approach so that others can understand what you're doing. ### The `dependency` block @@ -504,7 +529,9 @@ When Terragrunt is performing a run for a dependency, it will first run `terragr This is a very useful mechanism, as it keeps each unit isolated, while allowing for message passing between units when they need to interact. -Dependencies also give Terragrunt a way to reason about the order in which units of infrastructure should be run. It uses what's called a Directed Acyclic Graph (DAG) to determine the order in which units should be run, and then runs them in that order. +### The Directed Acyclic Graph (DAG) + +Dependencies also give Terragrunt a way to reason about the order in which units of infrastructure should be run. It uses what's called a [Directed Acyclic Graph (DAG)](/docs/getting-started/terminology/#directed-acyclic-graph-dag) to determine the order in which units should be run, and then runs them in that order. For example, let's go ahead and destroy all the infrastructure that we've created so far: @@ -684,7 +711,7 @@ remote_state { config = { bucket = "my-tofu-state" - key = "${path_relative_to_include()}/tofu.tfstate" + key = "${path_relative_to_include()}/tofu.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "my-lock-table" @@ -709,6 +736,8 @@ Now, when the configurations in the `us-east-1` directory include the `root.hcl` **ALSO NOTE** The `remote_state` block is still storing all state in the `us-east-1` region by design. We don't have to do this, and you could easily set it to store state in multiple regions. For the sake of simplicity, and demonstration, we're keeping it in one region. +### Exposed includes + Before moving on, take note of one thing, the `azs` attribute in the `vpc` unit of the `us-east-1` stack is hardcoded to `["us-east-1a", "us-east-1b", "us-east-1c"]`. This would cause issues if we were to try to deploy the `vpc` unit in the `us-west-2` stack, as those availability zones don't exist in the `us-west-2` region. What we need to do is make the `azs` attribute dynamic and use the resolved region to determine the correct availability zones. @@ -743,7 +772,7 @@ inputs = { private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] - enable_nat_gateway = true + enable_nat_gateway = false enable_vpn_gateway = false tags = { @@ -770,7 +799,9 @@ locals { } ``` -Then run the `terragrunt run-all apply` command in the `us-west-2` directory. +### Tightening the blast radius + +Run the `terragrunt run-all apply` command after changing your current working directory to the `us-west-2` directory: ```bash cd us-west-2 @@ -781,9 +812,9 @@ You should see the VPC and EC2 instances being provisioned in the `us-west-2` re This showcases three superpowers you gain when you leverage Terragrunt: -1. **Automatic DAG Resolution**: No configuration file needed to be updated or modified to ensure that the `ec2` unit was run after the `vpc` unit when provisioning the `us-west-2` stack. Terragrunt automatically resolved the dependency graph and ran the units in the correct order. +1. **Automatic DAG Resolution**: No configuration file had to be updated or modified to ensure that the `ec2` unit was run after the `vpc` unit when provisioning the `us-west-2` stack. Terragrunt automatically resolved the dependency graph and ran the units in the correct order. 2. **Dynamic Configuration**: The code you copied from the `us-east-1` directory to the `us-west-2` directory didn't need to be modified at all to provision resources in a different region (with the exception of naming the region in the `region.hcl` file). Terragrunt was able to dynamically resolve the correct configuration based on context, and apply it to the OpenTofu/Terraform modules as generic patterns of infrastructure. -3. **Reduced Blast Radius**: By applying Terragrunt within the `us-west-2` directory, you were able to confidently target only the resources in that region, without affecting the resources in the `us-east-1` region. This is a powerful tool for safely managing multiple environments, regions, or accounts with a single codebase. Your current working directory when using Terragrunt is your blast radius, and Terragrunt makes it easy to manage that blast radius effectively. +3. **Reduced Blast Radius**: By applying Terragrunt within the `us-west-2` directory, you were able to confidently target only the resources in that region, without affecting the resources in the `us-east-1` region. This is a powerful tool for safely managing multiple environments, regions, or accounts with a single codebase. Your current working directory when using Terragrunt is your [blast radius](/docs/getting-started/terminology/#blast-radius), and Terragrunt makes it easy to manage that blast radius effectively. ### Cleanup @@ -803,6 +834,8 @@ In real-world scenarios, it's generally advised that you plan your destroys firs $ terragrunt run-all plan -destroy ``` +You won't need to run any more Terragrunt commands for the rest of this guide. + ### Recommended Repository Patterns Outside of the patterns used for setting up Terragrunt configurations within a project, there are are also some patterns that we recommend for managing one or more repositories used to manage infrastructure. At Gruntwork, we refer to this as your "Infrastructure Estate". @@ -907,6 +940,70 @@ If at any point during this process a change is found to be problematic, the tea That's the power of reducing your blast radius with Terragrunt! +### Keep It Simple, Silly + +One last pattern to internalize is the general tendency to prefer simple configurations over complex ones when possible. + +Terragrunt provides a lot of power and flexibility, but it's generally best to use that power to make your configurations more readable and maintainable. Keep in mind that you're writing code that will be read by other humans, and that you might not be around to explain any complexity you introduce. + +As an example, consider one potential solution to a step outlined in the [Exposed includes](#exposed-includes) section, the requirement to update the `region` local in the `region.hcl` file: + +```hcl +# us-west-2/region.hcl +locals { + region = "us-west-2" +} +``` + +You might think to yourself "Hey, I know a lot about Terragrunt functionality, I can make this more dynamic, such that I don't even need to create a `region.hcl` file!" and come up with a solution like this: + +```hcl +# root.hcl +locals { + region = split("/", path_relative_to_include())[0] +} + +# Configure the remote backend +remote_state { + backend = "s3" + generate = { + path = "backend.tf" + if_exists = "overwrite_terragrunt" + } + config = { + bucket = "my-tofu-state" + + key = "${path_relative_to_include()}/tofu.tfstate" + region = "us-east-1" + encrypt = true + dynamodb_table = "my-lock-table" + } +} + +# Configure the AWS provider +generate "provider" { + path = "provider.tf" + if_exists = "overwrite_terragrunt" + contents = < + ### Step 1: Create a new Terragrunt project Let's say you have the following `main.tf` in directory `foo`: @@ -154,7 +161,7 @@ resource "local_file" "file" { Now, just like when using `tofu` alone, you can pass in the value for the `content` variable using the `-var` flag: ```bash -terragrunt apply -auto-approve -var 'content=Hello, Terragrunt!' +terragrunt apply -auto-approve -var content='Hello, Terragrunt!' ``` This is a common pattern when working with Infrastructure as Code (IaC). You typically create IaC that is relatively static, and then as you need to make configurations dynamic, you add variables to your configuration files to introduce dynamicity. diff --git a/docs/_docs/01_getting-started/terminology.md b/docs/_docs/01_getting-started/terminology.md index 5d4f29805..3546f30f3 100644 --- a/docs/_docs/01_getting-started/terminology.md +++ b/docs/_docs/01_getting-started/terminology.md @@ -109,6 +109,28 @@ This is still true even when working with multiple units in a stack. Terragrunt Note that DAGs are _Acyclic_, meaning that there are no loops in the graph. This is because loops would create circular dependencies, which would make it impossible to determine the correct order to resolve resources. +### Don't Repeat Yourself (DRY) + +The [Don't Repeat Yourself (DRY)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) principle is a software development principle that states that duplication in code should be avoided. + +Early on, a lot of Terragrunt functionality was designed to make it easier to follow the DRY principle. This was because Terraform users at the time found that they were often repeating the same, or very similar code across multiple configurations. Examples of this included the limitation that remote state and provider configurations needed to be repeated in every root module, and that there were limitations in the dynamicity of these configurations. + +Over time, Terragrunt has evolved to provide more features that make it easier to manage infrastructure at scale, and the focus has shifted to offering more tooling for _orchestrating_ infrastructure, rather than simply making it easier to avoid repeating yourself. Many of the features still serve to make it easier to follow the DRY principle, but this is no longer the primary focus of the tool. + +Much of the marketing around Terragrunt still emphasizes the DRY principle, as it is a useful way to explain the value of Terragrunt to new users. However, you might miss the forest for the trees if you focus too much on the DRY principle when evaluating Terragrunt. Terragrunt is a powerful tool that can be used to manage infrastructure at scale, and it is worth evaluating it based on its capabilities to do so. + +### Blast Radius + +[Blast Radius](https://en.wikipedia.org/wiki/Blast_radius) is a term used in software development to describe the potential impact of a change, derived from the term used to describe the potential impact of an explosion. + +In the context of infrastructure management, blast radius is used to describe the potential impact (negative or positive) of a change to infrastructure. The larger the blast radius, the more potential impact a change has. + +Terragrunt was born out of a need to reduce the blast radii of infrastructure changes. By making it easier to segment state in infrastructure, and to manage dependencies between units, Terragrunt makes it easier to reason about the impact of changes to infrastructure, and to ensure that changes can be made safely. + +When using Terragrunt, there is very frequently a mapping between your filesystem and the infrastructure you have provisioned with OpenTofu/Terraform. As such, when changing your current working directory in a Terragrunt project, you end up implicitly changing the blast radius of Terragrunt commands. The more units you have as children of your current working directory (the units in your stack), the more infrastructure you are likely to impact with a Terragrunt command. + +As an adage, you can generally think of this property as: "Your current working directory is your blast radius". + ### Run A run is a single invocation of OpenTofu/Terraform by Terragrunt. @@ -200,9 +222,9 @@ Like all good feature flags, you are encouraged to use them with good judgement ### IaC Engine -[IaC Engines](/docs/features/engine/) (typically appreviated "Engine") are a way to extend the capabilities of Terragrunt by allowing users to control exactly how Terragrunt performs runs. +[IaC Engines](/docs/features/engine/) (typically abbreviated "Engines") are a way to extend the capabilities of Terragrunt by allowing users to control exactly how Terragrunt performs runs. -Engines allow Terragrunt users to define custom logic for how runs are to be executed, including defining exactly how OpenTofu/Terraform is to be invoked, where OpenTofu/Terraform is to be invoked, etc. +Engines allow Terragrunt users to author custom logic for how runs are to be executed in plugins, including defining exactly how OpenTofu/Terraform is to be invoked, where OpenTofu/Terraform is to be invoked, etc. ### Infrastructure Estate diff --git a/docs/_docs/04_reference/cli-options.md b/docs/_docs/04_reference/cli-options.md index d29a456bb..2938b355a 100644 --- a/docs/_docs/04_reference/cli-options.md +++ b/docs/_docs/04_reference/cli-options.md @@ -839,9 +839,16 @@ explanation). This argument is not used with the `run-all` commands. **CLI Arg**: `--terragrunt-tfpath`
**Environment Variable**: `TERRAGRUNT_TFPATH`
-**Requires an argument**: `--terragrunt-tfpath /path/to/terraform-binary`
+**Requires an argument**: `--terragrunt-tfpath /path/to/tofu-or-terraform-binary`
+**Default**: `tofu`
-A custom path to the OpenTofu/Terraform binary. The default is `tofu` in a directory on your PATH. +An explicit path to the `tofu` or `terraform` binary you wish to have Terragrunt use. + +Note that if you _only_ have `terraform` installed, and available in your PATH, Terragrunt will automatically use that binary. + +If you have _both_ `terraform` and `tofu` installed, and you want to use `terraform`, you can set the `TERRAGRUNT_TFPATH` to `terraform`. + +If you have _multiple_ versions of `tofu` and/or `terraform` available, or you have a custom wrapper for `tofu` or `terraform`, you can set the `TERRAGRUNT_TFPATH` to the absolute path of the executable you want to use. **NOTE**: This will override the `terraform` binary that is used by `terragrunt` in all instances, including `dependency` lookups. This setting will also override any [terraform_binary]({{site.baseurl}}/docs/reference/config-blocks-and-attributes/#terraform_binary) diff --git a/test/fixtures/docs/01-quick-start/step-01.1/foo/main.tf b/test/fixtures/docs/01-quick-start/step-01.1/foo/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-01.1/foo/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-01.1/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-01.1/foo/terragrunt.hcl new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/docs/01-quick-start/step-01/foo/main.tf b/test/fixtures/docs/01-quick-start/step-01/foo/main.tf new file mode 100644 index 000000000..2f66a507b --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-01/foo/main.tf @@ -0,0 +1,4 @@ +resource "local_file" "file" { + content = "Hello, World!" + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-01/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-01/foo/terragrunt.hcl new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/docs/01-quick-start/step-02/bar/main.tf b/test/fixtures/docs/01-quick-start/step-02/bar/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-02/bar/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-02/bar/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-02/bar/terragrunt.hcl new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/docs/01-quick-start/step-02/foo/main.tf b/test/fixtures/docs/01-quick-start/step-02/foo/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-02/foo/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-02/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-02/foo/terragrunt.hcl new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/docs/01-quick-start/step-03/bar/main.tf b/test/fixtures/docs/01-quick-start/step-03/bar/main.tf new file mode 100644 index 000000000..b0c69c513 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-03/bar/main.tf @@ -0,0 +1,7 @@ +variable "content" {} + +module "shared" { + source = "../shared" + + content = var.content +} diff --git a/test/fixtures/docs/01-quick-start/step-03/bar/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-03/bar/terragrunt.hcl new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/docs/01-quick-start/step-03/foo/main.tf b/test/fixtures/docs/01-quick-start/step-03/foo/main.tf new file mode 100644 index 000000000..b0c69c513 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-03/foo/main.tf @@ -0,0 +1,7 @@ +variable "content" {} + +module "shared" { + source = "../shared" + + content = var.content +} diff --git a/test/fixtures/docs/01-quick-start/step-03/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-03/foo/terragrunt.hcl new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/docs/01-quick-start/step-03/shared/main.tf b/test/fixtures/docs/01-quick-start/step-03/shared/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-03/shared/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-04/.gitignore b/test/fixtures/docs/01-quick-start/step-04/.gitignore new file mode 100644 index 000000000..d46b47942 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-04/.gitignore @@ -0,0 +1 @@ +.terragrunt-cache diff --git a/test/fixtures/docs/01-quick-start/step-04/bar/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-04/bar/terragrunt.hcl new file mode 100644 index 000000000..25248e7c1 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-04/bar/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + source = "../shared" +} + +inputs = { + content = "Hello from bar, Terragrunt!" +} diff --git a/test/fixtures/docs/01-quick-start/step-04/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-04/foo/terragrunt.hcl new file mode 100644 index 000000000..a818ff8fc --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-04/foo/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + source = "../shared" +} + +inputs = { + content = "Hello from foo, Terragrunt!" +} diff --git a/test/fixtures/docs/01-quick-start/step-04/shared/main.tf b/test/fixtures/docs/01-quick-start/step-04/shared/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-04/shared/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-05/.gitignore b/test/fixtures/docs/01-quick-start/step-05/.gitignore new file mode 100644 index 000000000..d46b47942 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-05/.gitignore @@ -0,0 +1 @@ +.terragrunt-cache diff --git a/test/fixtures/docs/01-quick-start/step-05/README.md b/test/fixtures/docs/01-quick-start/step-05/README.md new file mode 100644 index 000000000..b1e81e486 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-05/README.md @@ -0,0 +1 @@ +Note that this step is the same as the previous step. diff --git a/test/fixtures/docs/01-quick-start/step-05/bar/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-05/bar/terragrunt.hcl new file mode 100644 index 000000000..25248e7c1 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-05/bar/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + source = "../shared" +} + +inputs = { + content = "Hello from bar, Terragrunt!" +} diff --git a/test/fixtures/docs/01-quick-start/step-05/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-05/foo/terragrunt.hcl new file mode 100644 index 000000000..a818ff8fc --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-05/foo/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + source = "../shared" +} + +inputs = { + content = "Hello from foo, Terragrunt!" +} diff --git a/test/fixtures/docs/01-quick-start/step-05/shared/main.tf b/test/fixtures/docs/01-quick-start/step-05/shared/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-05/shared/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-06/.gitignore b/test/fixtures/docs/01-quick-start/step-06/.gitignore new file mode 100644 index 000000000..d46b47942 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-06/.gitignore @@ -0,0 +1 @@ +.terragrunt-cache diff --git a/test/fixtures/docs/01-quick-start/step-06/bar/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-06/bar/terragrunt.hcl new file mode 100644 index 000000000..e5411a03d --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-06/bar/terragrunt.hcl @@ -0,0 +1,11 @@ +terraform { + source = "../shared" +} + +dependency "foo" { + config_path = "../foo" +} + +inputs = { + content = "Foo content: ${dependency.foo.outputs.content}" +} diff --git a/test/fixtures/docs/01-quick-start/step-06/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-06/foo/terragrunt.hcl new file mode 100644 index 000000000..a818ff8fc --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-06/foo/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + source = "../shared" +} + +inputs = { + content = "Hello from foo, Terragrunt!" +} diff --git a/test/fixtures/docs/01-quick-start/step-06/shared/main.tf b/test/fixtures/docs/01-quick-start/step-06/shared/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-06/shared/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-06/shared/output.tf b/test/fixtures/docs/01-quick-start/step-06/shared/output.tf new file mode 100644 index 000000000..968795bda --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-06/shared/output.tf @@ -0,0 +1,3 @@ +output "content" { + value = local_file.file.content +} diff --git a/test/fixtures/docs/01-quick-start/step-07.1/.gitignore b/test/fixtures/docs/01-quick-start/step-07.1/.gitignore new file mode 100644 index 000000000..d46b47942 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07.1/.gitignore @@ -0,0 +1 @@ +.terragrunt-cache diff --git a/test/fixtures/docs/01-quick-start/step-07.1/bar/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-07.1/bar/terragrunt.hcl new file mode 100644 index 000000000..c35bd0756 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07.1/bar/terragrunt.hcl @@ -0,0 +1,17 @@ +terraform { + source = "../shared" +} + +dependency "foo" { + config_path = "../foo" + + mock_outputs = { + content = "Mocked content from foo" + } + + mock_outputs_allowed_terraform_commands = ["plan"] +} + +inputs = { + content = "Foo content: ${dependency.foo.outputs.content}" +} diff --git a/test/fixtures/docs/01-quick-start/step-07.1/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-07.1/foo/terragrunt.hcl new file mode 100644 index 000000000..a818ff8fc --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07.1/foo/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + source = "../shared" +} + +inputs = { + content = "Hello from foo, Terragrunt!" +} diff --git a/test/fixtures/docs/01-quick-start/step-07.1/shared/main.tf b/test/fixtures/docs/01-quick-start/step-07.1/shared/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07.1/shared/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-07.1/shared/output.tf b/test/fixtures/docs/01-quick-start/step-07.1/shared/output.tf new file mode 100644 index 000000000..968795bda --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07.1/shared/output.tf @@ -0,0 +1,3 @@ +output "content" { + value = local_file.file.content +} diff --git a/test/fixtures/docs/01-quick-start/step-07/.gitignore b/test/fixtures/docs/01-quick-start/step-07/.gitignore new file mode 100644 index 000000000..d46b47942 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07/.gitignore @@ -0,0 +1 @@ +.terragrunt-cache diff --git a/test/fixtures/docs/01-quick-start/step-07/bar/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-07/bar/terragrunt.hcl new file mode 100644 index 000000000..d18b33649 --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07/bar/terragrunt.hcl @@ -0,0 +1,15 @@ +terraform { + source = "../shared" +} + +dependency "foo" { + config_path = "../foo" + + mock_outputs = { + content = "Mocked content from foo" + } +} + +inputs = { + content = "Foo content: ${dependency.foo.outputs.content}" +} diff --git a/test/fixtures/docs/01-quick-start/step-07/foo/terragrunt.hcl b/test/fixtures/docs/01-quick-start/step-07/foo/terragrunt.hcl new file mode 100644 index 000000000..a818ff8fc --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07/foo/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + source = "../shared" +} + +inputs = { + content = "Hello from foo, Terragrunt!" +} diff --git a/test/fixtures/docs/01-quick-start/step-07/shared/main.tf b/test/fixtures/docs/01-quick-start/step-07/shared/main.tf new file mode 100644 index 000000000..e3ca9643e --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07/shared/main.tf @@ -0,0 +1,6 @@ +variable "content" {} + +resource "local_file" "file" { + content = var.content + filename = "${path.module}/hi.txt" +} diff --git a/test/fixtures/docs/01-quick-start/step-07/shared/output.tf b/test/fixtures/docs/01-quick-start/step-07/shared/output.tf new file mode 100644 index 000000000..968795bda --- /dev/null +++ b/test/fixtures/docs/01-quick-start/step-07/shared/output.tf @@ -0,0 +1,3 @@ +output "content" { + value = local_file.file.content +} diff --git a/test/fixtures/docs/02-overview/step-01-terragrunt.hcl/terragrunt.hcl b/test/fixtures/docs/02-overview/step-01-terragrunt.hcl/terragrunt.hcl new file mode 100644 index 000000000..d63b324dc --- /dev/null +++ b/test/fixtures/docs/02-overview/step-01-terragrunt.hcl/terragrunt.hcl @@ -0,0 +1,62 @@ +# Configure the remote backend +remote_state { + backend = "s3" + + generate = { + path = "backend.tf" + if_exists = "overwrite_terragrunt" + } + + config = { + bucket = "__FILL_IN_BUCKET_NAME__" + + key = "tofu.tfstate" + region = "__FILL_IN_REGION__" + encrypt = true + dynamodb_table = "__FILL_IN_LOCK_TABLE_NAME__" + } +} + +# Configure the AWS provider +generate "provider" { + path = "provider.tf" + if_exists = "overwrite_terragrunt" + contents = <