gruntwork-io / terratest

Terratest is a Go library that makes it easier to write automated tests for your infrastructure code.
https://terratest.gruntwork.io/
Apache License 2.0
7.52k stars 1.33k forks source link

Testing Terragrunt? #122

Closed kamsz closed 4 years ago

kamsz commented 6 years ago

Is it possible to swap executable that is used from terraform to terragrunt?

brikis98 commented 6 years ago

Not currently, but that's a great idea. A TerraformBinary field, which if empty defaults to terraform, would be a great addition to terraform.Options.

kamsz commented 6 years ago

@brikis98 I'd stick with a separate module to include additional functionalities of Terragrunt like apply-all.

brikis98 commented 6 years ago

I think it would be cleaner to avoid duplicating all those code paths. To handle apply-all, we could expose a RunTerraformCommand(command string, args[]string, options *terraform.Options) method.

kamsz commented 6 years ago

I'll try to work on this then.

so87 commented 5 years ago

I'm confused here: doesn't gruntwork exclusively use terragrunt to work on infrastructure? And shouldn't all "dev" "staging" and "production" folders have terratests written for them (because that is what you seem to suggest in both of your books). So how does gruntwork actually test terragrunt - do you just write terratests for modules, and use another tool to do smoke tests on terragrunt deployments? @brikis98

brikis98 commented 5 years ago

I'm confused here: doesn't gruntwork exclusively use terragrunt to work on infrastructure?

Not exclusively. All of the modules in our IaC Library, where we do the majority of our testing, are written in pure Terraform and do NOT require Terragrunt at all. Also, many of the modules are written in Go, Python, Bash, etc too, as the IaC Library is designed to solve problems across the entire infrastructure, and not just those problems that can be solved by Terraform.

So how does gruntwork actually test terragrunt

Terragrunt itself is tested in this repo. See the _test.go files.

do smoke tests on terragrunt deployments

Correct

so87 commented 5 years ago

@brikis98 Thank you for the fast response and time, you seem like an extremely busy person.
After further analyzing the terragrunt and terratest repos let me see if you think how I'm going to test my future configurations make sense. I tried looking for people using writing go tests for a terragrunt project layout, but couldn't find any - so maybe tons of people are using terragrunt but not actually writing any tests for their infrastructure?.

I want to take a docker image I have and get it running in ec2. So first I

  1. break out the necessary infrastructure pieces into a modules repository
  2. write failing tests for that terraform code using terratest. Keep working until tests pass
  3. reference that modules repository in my project repository where it has the following structure(using terragrunt). My _test.go files aren't terratest, they are just simple go tests that curl a url(I haven't written these yet but that was what I was thinking) project
    • dev
      • terraform.tfvars
    • staging
    • prod terraform.tfvars account.tfvars
    • tests
      • dev_test.go
      • staging_test.go
      • prod_test.go
  4. once I'm able to get all of this working for a simple ec2 "hello world" type image, I can now create a new folder for turning my existing Dockerfile into a container.json file that will be used by packer to build a docker image and turn it into an ami.
  5. write terratests for the container.json I made. This way any changes to this container infrastructure gets tested.
  6. write normal or python unit tests for the code that goes inside this container
  7. my ci/cd should run all terratest for the base infrastructure(aws,gcp), terratest to ensure image gets created(ami, docker image), normal unit testing for my app inside container, and go "smoke tests" to make sure that everything seems to be running after each deployment

Give me as much criticism as you feel like, I'm trying to learn the right way of doing things from you. I've been looking at your code, and half way done reading your book "hello startup". I really appreciate your work and writing.

so87 commented 5 years ago

@brikis98 does that seem right or is that overkill?

brikis98 commented 5 years ago

Sorry, been buried, will take a look when I get a chance

k3kh commented 4 years ago

@so87 Have you ever resolved unit testing (terratest) and terragrunt items mentioned above? Interested in any approach. Working through some of the same items you mentioned above.

yorinasub17 commented 4 years ago

This is OT to the terragrunt testing workflow, but circling back on the OP, we've released a few functions since the issue was opened that help with testing Terragrunt:

kihahu commented 4 years ago

I recently used the option TerraformBinary and the apply-all and plan-all functions to write tests for terraform modules which are usually used using terragrunt. I happened on them by chance while looking at some test implementations. I think some examples to illustrate the use of the option and functions would be helpful.

brikis98 commented 4 years ago

As mentioned in this comment, you can now test Terragrunt.

pandu-bhojaraj-mf commented 4 years ago

@kihahu @yorinasub17 @so87 @brikis98

Can any one of you share me piece of code which is written to invoke terragrunt(HCL) files from terratest(GO) script ?

I am getting "github.com/gruntwork-io/terratest/modules/terraform.(*TgInvalidBinary).Error" error for below code

image

Tryin hard to get some example code which helps me to invoke terragrunt files from terratest , please help

yorinasub17 commented 4 years ago

Try setting the TerraformBinary attribute on the Options struct to the path to terragrunt binary, and that should do the trick.

avishnyakov commented 3 years ago

Exploring options to swap Terraform with Terragrunt via options.TerraformDir at the moment.

This is extremely useful while testing Terraform modules on different combinations of the providers at the same time. Think about safe and scalable provider upgrade story:

Basically, you do something like that:

generate "provider" {

  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "azurerm" {
  version = "=${get_env("TG_PROVIDER_AZURERM_VERSION", "2.40.0")}"
  features {}
}

}

and the you can run your test in parallel setting different env variables for TG_PROVIDER_AZURERM_VERSION to test your module under different provider verssion:

Running such tests in parallel with different env variable setup unlocks easy and scalable upgrade story, testing and also troubleshooting should providers have funky behaviors.

All that is harder to do with native TF, not much options to override provider setup version (unless I miss something). Would be so great to have TerraTest support for TG, of course.

mrwormhole commented 3 years ago

Would be good to get sample docs for terragrunt with terratest as @pandu-bhojaraj-mf mentioned in its comments. There is literally no guide on such a simple swap out binary task

sbgillett commented 3 years ago

Here's a quick Terragrunt test I got working using the existing example terragrunt-example:

package test

import (
    "testing"

    "github.com/gruntwork-io/terratest/modules/terraform"
    "github.com/stretchr/testify/assert"
)

func TestTerragruntExample(t *testing.T) {
    // website::tag::2:: Construct the terraform options with default retryable errors to handle the most common
    // retryable errors in terraform testing.
    terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
        // website::tag::1:: Set the path to the Terraform code that will be tested.
        TerraformDir: "../examples/terragrunt-example",
        TerraformBinary: "terragrunt.exe", // ensure terragrunt is on your PATH, or provide the full path here
    })

    // website::tag::5:: Clean up resources with "terragrunt destroy" at the end of the test.
    defer terraform.Destroy(t, terraformOptions)

    // website::tag::3:: Run "terragrunt init" and "terragrunt apply". Fail the test if there are any errors.
    terraform.InitAndApply(t, terraformOptions)

    // website::tag::4:: Run `terragrunt output` to get the values of output variables and check they have the expected values.
    output := terraform.Output(t, terraformOptions, "output")
    assert.Equal(t, "one input another input", output)
}
  1. Ensure Terraform and Terragrunt are installed and on your PATH
  2. Install Golang and make sure this code is on your GOPATH
  3. cd test
  4. go test -v -run TestTerragruntExample
yorinasub17 commented 3 years ago

Hi folks, I just merged in a terragrunt example that is exposed on our site, which is going to be very similar to the one above: https://terratest.gruntwork.io/examples/ (it's unfortunately in the overflow, hidden in the dropdown)

Hopefully folks can use that going forward!

mrwormhole commented 3 years ago

still don't see it but thanks for the link. Screenshot would be good to find that dropdown

yorinasub17 commented 3 years ago

Here's a screenshot:

Screen Shot 2021-09-30 at 8 02 59 AM