Skip to content

Commit

Permalink
Fix bug with --ignore-parent-terragrunt (#37)
Browse files Browse the repository at this point in the history
Co-authored-by: dmattia <david@transcend.io>
  • Loading branch information
dmattia and dmattia authored Jul 8, 2020
1 parent 24eb466 commit 32719c2
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION=0.4.5
VERSION=0.5.0
PATH_BUILD=build/
FILE_COMMAND=terragrunt-atlantis-config
FILE_ARCH=darwin_amd64
Expand Down
26 changes: 15 additions & 11 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,30 +87,34 @@ func makePathAbsolute(path string, parentPath string) string {

// Parses the terragrunt config at <path> to find all modules it depends on
func getDependencies(path string) ([]string, error) {
decodeTypes := []config.PartialDecodeSectionType{
config.DependencyBlock,
config.DependenciesBlock,
config.TerraformBlock,
}

options, err := options.NewTerragruntOptions(path)
if err != nil {
return nil, err
}
options.RunTerragrunt = cli.RunTerragrunt
options.Env = getEnvs()

parsedConfig, err := config.PartialParseConfigFile(path, options, nil, decodeTypes)
// if theres no terraform source and we're ignoring parent terragrunt configs
// return nils to indicate we should skip this project
isParent, err := isParentModule(path, options)
if err != nil {
return nil, err
}

// if theres no terraform source and we're ignoring parent terragrunt configs
// return nils to indicate we should skip this project
if (parsedConfig.Terraform == nil || parsedConfig.Terraform.Source == nil) && ignoreParentTerragrunt == true {
if ignoreParentTerragrunt && isParent {
return nil, nil
}

decodeTypes := []config.PartialDecodeSectionType{
config.DependencyBlock,
config.DependenciesBlock,
config.TerraformBlock,
}

parsedConfig, err := config.PartialParseConfigFile(path, options, nil, decodeTypes)
if err != nil {
return nil, err
}

dependencies, err := parseLocalDependencies(path)
if err != nil {
return nil, err
Expand Down
11 changes: 11 additions & 0 deletions cmd/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,14 @@ func TestTerragruntDependencies(t *testing.T) {
filepath.Join("..", "test_examples", "terragrunt_dependency"),
})
}

// This test covers parent Terragrunt files that are not runnable as modules themselves.
// Sometimes it is possible to have parent files that only are runnable when included
// into child modules.
func TestUnparseableParent(t *testing.T) {
runTest(t, filepath.Join("golden", "invalid_parent_module.yaml"), []string{
"--root",
filepath.Join("..", "test_examples", "invalid_parent_module"),
"--ignore-parent-terragrunt",
})
}
11 changes: 11 additions & 0 deletions cmd/golden/invalid_parent_module.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
automerge: false
parallel_apply: true
parallel_plan: true
projects:
- autoplan:
enabled: false
when_modified:
- '*.hcl'
- '*.tf*'
dir: child/deep
version: 3
48 changes: 48 additions & 0 deletions cmd/parse_hcl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cmd

import (
"github.com/gruntwork-io/terragrunt/config"
"github.com/gruntwork-io/terragrunt/options"
"github.com/gruntwork-io/terragrunt/util"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/hcl/v2/hclparse"
"github.com/zclconf/go-cty/cty/function"
)

type parsedHcl struct {
Terraform *terraformConfig `hcl:"terraform,block"`
}

type terraformConfig struct {
Source *string `hcl:"source,attr"`
}

func isParentModule(path string, terragruntOptions *options.TerragruntOptions) (bool, error) {
configString, err := util.ReadFileAsString(path)
if err != nil {
return false, err
}

parser := hclparse.NewParser()
file, err := parseHcl(parser, configString, path)
if err != nil {
return false, err
}

extensions := config.EvalContextExtensions{}
evalContext := config.CreateTerragruntEvalContext(path, terragruntOptions, extensions)

// Mock all the functions out so they don't do anything. Otherwise they may throw errors that we don't care about
evalContext.Functions = map[string]function.Function{}

// We don't need to check the errors/diagnostics coming from `DecodeBody`, as when errors come up,
// it will leave the partially parsed result in the output object.
var parsed parsedHcl
gohcl.DecodeBody(file.Body, evalContext, &parsed)

if parsed.Terraform == nil || parsed.Terraform.Source == nil {
return true, nil
}

return false, nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/hashicorp/go-version v1.2.1 // indirect
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/hcl/v2 v2.6.0
github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80
github.com/hashicorp/terraform v0.12.28 // indirect
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import "github.com/transcend-io/terragrunt-atlantis-config/cmd"

var (
VERSION = "0.4.4"
VERSION = "0.5.0"
)

func main() {
Expand Down
5 changes: 5 additions & 0 deletions test_examples/invalid_parent_module/child/account.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
locals {
account_name = "prod"
aws_account_id = "000000000"
aws_profile = "prod"
}
11 changes: 11 additions & 0 deletions test_examples/invalid_parent_module/child/deep/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
include {
path = find_in_parent_folders()
}

terraform {
source = "git::git@github.com:transcend-io/terraform-aws-fargate-container?ref=v0.0.4"
}

inputs = {
foo = "bar"
}
3 changes: 3 additions & 0 deletions test_examples/invalid_parent_module/child/env.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
environment = "prod"
}
3 changes: 3 additions & 0 deletions test_examples/invalid_parent_module/child/region.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
aws_region = "eu-west-1"
}
56 changes: 56 additions & 0 deletions test_examples/invalid_parent_module/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
######################################################################################################################
# This file (and test directory) is a fork of https://github.com/gruntwork-io/terragrunt-infrastructure-live-example #
######################################################################################################################

locals {
account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))
region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
account_name = local.account_vars.locals.account_name
account_id = local.account_vars.locals.aws_account_id
aws_region = local.region_vars.locals.aws_region
}

# Generate an AWS provider block
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "aws" {
region = "${local.aws_region}"
# Only these AWS Account IDs may be operated on by this template
allowed_account_ids = ["${local.account_id}"]
}
EOF
}

# Configure Terragrunt to automatically store tfstate files in an S3 bucket
remote_state {
backend = "s3"
config = {
encrypt = true
bucket = "${get_env("TG_BUCKET_PREFIX", "")}terragrunt-example-terraform-state-${local.account_name}-${local.aws_region}"
key = "${path_relative_to_include()}/terraform.tfstate"
region = local.aws_region
dynamodb_table = "terraform-locks"
}
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
}


# ---------------------------------------------------------------------------------------------------------------------
# GLOBAL PARAMETERS
# These variables apply to all configurations in this subfolder. These are automatically merged into the child
# `terragrunt.hcl` config via the include block.
# ---------------------------------------------------------------------------------------------------------------------

# Configure root level variables that all resources can inherit. This is especially helpful with multi-account configs
# where terraform_remote_state data sources are placed directly into the modules.
inputs = merge(
local.account_vars.locals,
local.region_vars.locals,
local.environment_vars.locals,
)
3 changes: 3 additions & 0 deletions test_examples/with_parent/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
ahhhhhh = "pst"
}

0 comments on commit 32719c2

Please sign in to comment.