gruntwork-io / terragrunt

Terragrunt is a flexible orchestration tool that allows Infrastructure as Code written in OpenTofu/Terraform to scale.
https://terragrunt.gruntwork.io/
MIT License
8.04k stars 975 forks source link

apply/plan behavioural differences with "--terragrunt-non-interactive" #1247

Closed esn89 closed 4 years ago

esn89 commented 4 years ago

terragrunt version v0.21.6

When I run terragrunt plan-all and enter in "yes" for each of the dependencies in the stack, I get a nice output detailing all the resources I need to create including the dependencies. In my example, it's the VPC stack which the DNS stack is dependent on:

Output:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.kafka-vpc.module.subnets.google_compute_subnetwork.subnetwork["us/vpc"] will be created
  + resource "google_compute_subnetwork" "subnetwork" {
      + creation_timestamp       = (known after apply)
      + enable_flow_logs         = (known after apply)
      + fingerprint              = (known after apply)
      + gateway_address          = (known after apply)
      + id                       = (known after apply)
      + ip_cidr_range            = "10.252.60.0/22"
      + name                     = "proj"
      + network                  = "vpc-us-dev"
      + private_ip_google_access = true
      + project                  = "222233334444"
      + region                   = "us"
      + secondary_ip_range       = []
      + self_link                = (known after apply)

      + log_config {
          + aggregation_interval = "INTERVAL_5_SEC"
          + flow_sampling        = 0.5
          + metadata             = "INCLUDE_ALL_METADATA"
        }
    }

  # module.vpc.module.vpc.google_compute_network.network will be created
  + resource "google_compute_network" "network" {
      + auto_create_subnetworks         = false
      + delete_default_routes_on_create = false
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "vpc-us-dev"
      + project                         = "222233334444"
      + routing_mode                    = "GLOBAL"
      + self_link                       = (known after apply)
    }

  # module.vpc.module.vpc.google_compute_shared_vpc_host_project.shared_vpc_host[0] will be created
  + resource "google_compute_shared_vpc_host_project" "shared_vpc_host" {
      + id      = (known after apply)
      + project = "222233334444"
    }

Plan: 3 to add, 0 to change, 0 to destroy.

......
.......
.......

  # google_dns_record_set.public_ingress_ip will be created
  + resource "google_dns_record_set" "public_ingress_ip" {
      + id           = (known after apply)
      + managed_zone = "dev=us"
      + name         = "domain2.us.dev.com."
      + project      = "dev"
      + rrdatas      = [
          + "10.250.0.3",
        ]
      + ttl          = 60
      + type         = "A"
    }

  # google_dns_record_set.a will be created
  + resource "google_dns_record_set" "spinnaker" {
      + id           = (known after apply)
      + managed_zone = "cortex-dev"
      + name         = "domain.us.dev.com."
      + project      = "cortex-mgmt-dev"
      + rrdatas      = [
          + "10.250.0.1",
        ]
      + ttl          = 60
      + type         = "A"
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Basically what I'm trying to illustrate is that with terragrunt plan-all it shows me all the dependencies which needs to be deployed too.

However, things are different when I use: terragrunt plan-all --terragrunt-non-interactive, it simply shows the DNS module's changes and not the VPC one.


With apply-all it is also very similar. terragrunt apply-all allows me to enter "yes" for all the modules which will be created and there is no problem.

With terragrunt apply-all --terragrunt-non-interactive I get this issue:

[terragrunt] 2020/07/07 18:25:11 Encountered the following errors:
dev/us/project/terragrunt.hcl is a dependency of dev/us/vpc/terragrunt.hcl but detected no outputs. Either the target module has not been applied yet, or the module has no outputs. If this is expected, set the skip_outputs flag to true on the dependency block.

This does not make sense because I expect it's behaviour to create those dependent resources when I run the terragrunt apply-all --terragrunt-non-interactive command.

brikis98 commented 4 years ago

What do your terragrunt.hcl files look like?

esn89 commented 4 years ago

Hi @brikis98

The DNS one looks like:

terraform {
  source = "../../../modules/dns"
}

include {
  path = find_in_parent_folders()
}

dependency "project" {
  config_path = "../../../../resources/dev/us/project"

  #skip_outputs = true

  mock_outputs = {
    project_id = "my-test-dev"
  }
  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}

dependency "vpc" {
  config_path = "../vpc"

  #skip_outputs = true

  mock_outputs = {
    network_self_link         = "vpc.network.test"
  }
  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}

dependency "kafka_network" {
  config_path = "../../../../services/kafka/dev/us/vpc"

  #skip_outputs = true

  mock_outputs = {
    kafka_network_self_link = "vpc.kafka_network.test"
  }
  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}

inputs = {
  network_self_link         = dependency.vpc.outputs.network_self_link
  network_url = dependency.kafka_network.outputs.kafka_network_self_link
  project_id = dependency.project.outputs.project_id
}

The VPC one looks like:

terraform {
  source = "../../../modules/vpc"

  extra_arguments "credentials" {
    commands = get_terraform_commands_that_need_vars()
  }
}

include {
  path = find_in_parent_folders()
}

dependency "project" {
  config_path = "../../../../resources/dev/us/project"

  #skip_outputs = true

  mock_outputs = {
    project_id = "my-test-dev"
  }
  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}

inputs = {
  project_id = dependency.project.outputs.project_id
}

and project:

terraform {
  source = "../../../modules/projects"

  extra_arguments "credentials" {
    commands = get_terraform_commands_that_need_vars()
  }
}

include {
  path = find_in_parent_folders()
}

dependency "folders" {
  config_path = "../folders"

  #skip_outputs = true

  mock_outputs = {
    folder_id = "123443211234"
  }
  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}

inputs = {
  folder_id = dependency.folders.outputs.folder_id
}
yorinasub17 commented 4 years ago

Which folder are you running apply-all/plan-all in? And does the folder tree contain all the dependencies, or are they outside of that folder?

esn89 commented 4 years ago

@yorinasub17

The folder where I am doing the apply-all/plan-all is in: ../../../modules/dns. This folder only contains the terragrunt.hcl for DNS.

The other ones such as VPC and Projects are located elsewhere, which is outside of the folder of ../../../modules/dns..

yorinasub17 commented 4 years ago

Try passing in --terragrunt-include-external-dependencies in addition to --terragrunt-non-interactive. Terragrunt tries to use conservative answers for non-interactive mode, and as such will not automatically include external dependencies.

esn89 commented 4 years ago

@yorinasub17

This is the flag that I'm looking for! Thanks so much!