Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement]: Fetch data sources from nested modules during plan #32146

Closed
njtrettel opened this issue Jun 21, 2023 · 5 comments
Closed

[Enhancement]: Fetch data sources from nested modules during plan #32146

njtrettel opened this issue Jun 21, 2023 · 5 comments
Labels
enhancement Requests to existing resources that expand the functionality or scope. service/ec2 Issues and PRs that pertain to the ec2 service. service/vpc Issues and PRs that pertain to the vpc service.

Comments

@njtrettel
Copy link

Description

First of all, I apologize if this is a duplicate or is documented elsewhere. I tried finding existing info on this but could not. It's kinda complex and I think it is a bit niche. Also, I considered labelling this a bug but I think it's actually working as-designed and is just a weird complexity with nested modules.

Background

I have a use case where I'm creating a submodule (module within a root module). The root module creates a VPC and then the submodule calculates subnet CIDRs and creates them. The consumer can use the module as-is, or they can "side-car" the subnet submodule (i.e. they skip subnet creation in the root module and declare the subnet submodule themselves).

The subnet submodule needs the list of all AWS availability zones for a variety of reasons. I would like to put the data.aws_availability_zones data source inside of the subnet submodule only (not the root). Doing so would allow the consumer to just say "give me 2 subnets" when side-carring; in this case the AZs are derived from the data source. If the subnet submodule did not have this data source, the consumer would have to explicitly provide a list of AZs when side-carring (not ideal). Note that the consumer is still allowed to provide a list of AZs (var.availability_zone_ids), which would override the list from the data source, but it should not be required to do so.

The problem

TL;DR - data sources in the nested submodule are "known after apply" whereas the data sources in the root module are calculated during plan

I've noticed a few different problems, but they're all related and I think they could all be explained with 1 example. The subnet submodule is validating the (optionally) provided var.availability_zone_ids override variable against the list of AZs from the data source to make sure it doesn't contain invalid AZ IDs. When I let the root VPC module create the subnet submodule, this validation does not work. Let's say I provide var.availability_zone_ids = ["use1-az1", "some-bs"] to the root VPC module. This is passed on to the submodule which should validate the AZs are incorrect. However, it doesn't validate, and would attempt to create a subnet in the some-bs region. When I side-car the subnet submodule and provide the same var.availability_zone_ids to the submodule, it is able to validate just fine.

According to the plan output, it is able to pull a root module's data sources during the initial state read, but it is only able to pull a submodule's data sources during apply. I'm sure this would be a pretty involved change/enhancement, but it looks to me that there is no reason that the nested module's data sources cannot be read during the plan. Below is an example.

Examples

The subnets submodule is outputting its data.aws_availability_zones.available_zones.zone_ids.

submodule side-car can validate just fine

# has an 
module "vpc" {
  source = "../.."
  # ...OMITTED...
}

module "subnets" {
  source = "../../submodules/subnets"

  vpc_id = module.vpc.id
  availability_zone_ids = ["use1-az1", "some-bs"]
  # ...OMITTED...
}

output "azs_from_sidecar" {
  value = module.subnets.azs
}

Output (truncated):

module.subnets.data.aws_availability_zones.available_zones: Read complete after 1s [id=us-east-1]

Changes to Outputs:
  + azs_from_sidecar = [
      + "use1-az1",
      + "use1-az2",
      + "use1-az4",
      + "use1-az6",
      + "use1-az3",
      + "use1-az5",
    ]

│ Error: Resource precondition failed
│ 
│   on ../../submodules/subnets/_validation.tf line 4, in resource "terraform_data" "availability_zone_validation":
│    4:       condition     = var.availability_zone_ids == null ? true : alltrue([for az in var.availability_zone_ids : contains(data.aws_availability_zones.available_zones.zone_ids, az)])
│     ├────────────────
│     │ data.aws_availability_zones.available_zones.zone_ids is list of string with 6 elements
│     │ var.availability_zone_ids is list of string with 2 elements
│ 
│ An invalid availability zone ID was provided in the availabilty_zone_ids variable. Valid values are:
│ ["use1-az1","use1-az2","use1-az4","use1-az6","use1-az3","use1-az5"]
│         
│ You provided:
│ ["use1-az1","some-bs"]

submodule within the root module cannot validate

The root module is re-outputting the data.aws_availability_zones.available_zones.zone_ids.

# has an 
module "vpc" {
  source = "../.."

  availability_zone_ids = ["use1-az1", "some-bs"]
  # ...OMITTED...
}

output "azs_from_root" {
  value = module.vpc.azs
}

Output (truncated):

  # module.vpc.module.subnets_routable["10.0.0.0/25"].data.aws_availability_zones.available_zones will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "aws_availability_zones" "available_zones" {

...

 module.vpc.module.subnets_routable["10.0.0.0/25"].aws_subnet.subnets[0] will be created
  + resource "aws_subnet" "subnets" {
      + availability_zone_id                           = "some-bs"

...

Changes to Outputs:
  + azs_from_root   = (known after apply)

Affected Resource(s) and/or Data Source(s)

All data sources within a nested module

Potential Terraform Configuration

The enhancement wouldn't involve any updates to a terraform configuration. It would be a modification to the way terraform calculates the dependency tree.

References

No response

Would you like to implement a fix?

Yes

@njtrettel njtrettel added enhancement Requests to existing resources that expand the functionality or scope. needs-triage Waiting for first response or review from a maintainer. labels Jun 21, 2023
@github-actions github-actions bot added the service/ec2 Issues and PRs that pertain to the ec2 service. label Jun 21, 2023
@github-actions
Copy link

Community Note

Voting for Prioritization

  • Please vote on this issue by adding a 👍 reaction to the original post to help the community and maintainers prioritize this request.
  • Please see our prioritization guide for information on how we prioritize.
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request.

Volunteering to Work on This Issue

  • If you are interested in working on this issue, please leave a comment.
  • If this would be your first contribution, please review the contribution guide.

@github-actions github-actions bot added the service/vpc Issues and PRs that pertain to the vpc service. label Jun 21, 2023
@justinretzolk
Copy link
Member

Hey @njtrettel 👋 Thank you for taking the time to raise this! Admittedly, this probably falls closer to a question for the Terraform Core team, and given the nature of it, I suspect that they would likely ask that you raise this somewhere like our Discuss forums. That said, if you've got the module configuration somewhere that I could take a look, I might be able to deduce what's happening here. I fear I'm missing some of the key details that are preventing me from fully understanding exactly what's happening in this case (though I initially suspect it's related to data resource behavior).

@justinretzolk justinretzolk added waiting-response Maintainers are waiting on response from community or contributor. and removed needs-triage Waiting for first response or review from a maintainer. labels Jun 23, 2023
@github-actions github-actions bot removed the waiting-response Maintainers are waiting on response from community or contributor. label Jun 23, 2023
@njtrettel
Copy link
Author

njtrettel commented Jun 23, 2023

@justinretzolk thanks for the response!

yea i did notice after already opening this issue that it probably should have been opened in the terraform language repo instead. my bad!

it's definitely related to the data source behavior, and it does state that it's deferring because it's dependent on other resources... however the question is whether or not that can be changed. the aws_availability_zones data source in my nested submodule is relying only on static string values. so, while the nested submodule does take variables that are not known until apply, the data source itself within the nested submodule does not. i.e. it seems like it's marking the entire nested submodule as "deferred"

the module is currently in an internal repo that i can't share. let me open an issue over in the terraform core repo and post something in the forum, and then put it somewhere personal to share it if necessary. but like i said, i think i have an explanation for why, just trying to see if there's any wiggle room in that behavior.

@justinretzolk
Copy link
Member

That totally makes sense @njtrettel! Since we're on the same page that this is more of a Terraform Core issue, I'll go ahead and close this issue out, but I wish you luck in finding more information!

@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Requests to existing resources that expand the functionality or scope. service/ec2 Issues and PRs that pertain to the ec2 service. service/vpc Issues and PRs that pertain to the vpc service.
Projects
None yet
Development

No branches or pull requests

2 participants