Skip to content

test(terraform): test to demonstrate 'count' meta argument incorrectl… #8479

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Emyrk
Copy link
Contributor

@Emyrk Emyrk commented Mar 3, 2025

Description

count meta argument is incorrectly handled when referencing a submodule's output. It does work when referencing within the same scope.

This is being caused because expandBlockCounts defaults to a count = 1 for unknown values. Secondly, unknown values are returned as cty.Nil, so that information is not easily available at this step.

ExpandingBlocks happens before submodule evaluation:
https://github.com/aquasecurity/trivy/blob/main/pkg/iac/scanners/terraform/parser/evaluator.go#L139-L142

So expanded blocks cannot reference submodule exports. This is inconsistent with terraform plan/apply which renders 0 data blocks in this unit test.

I feel a bit iffy trying to solve this without consulting @simar7 and @nikpivkin. My quick solution is presented, however I admit it was done rather quickly and is not correct.

Checklist

  • I've read the guidelines for contributing to this repository.
  • I've followed the conventions in the PR title.
  • I've added tests that prove my fix is effective or that my feature works.
  • I've updated the documentation with the relevant information (if needed).
  • I've added usage information (if the PR introduces new options)
  • I've included a "before" and "after" example to the description (if the PR is a user interface change).

@Emyrk
Copy link
Contributor Author

Emyrk commented Mar 5, 2025

@nikpivkin and @simar7, what are your thoughts on this bug? The unit test is a good example and self description. It fails on the latest main.

The test only passes because I added in e.blocks = e.expandBlocks(e.blocks), but that solution is incomplete. It was added just to demonstrate the problem.

I don't have a good solution for a more robust fix.

@nikpivkin
Copy link
Contributor

Hi @Emyrk !

Thanks. I'll look into it.

@Emyrk
Copy link
Contributor Author

Emyrk commented Mar 13, 2025

@nikpivkin any updates on your thoughts?

@Emyrk Emyrk force-pushed the stevenmasley/module_output_count branch from 29a795b to 6b58370 Compare March 19, 2025 17:48
Comment on lines +143 to +156
// A pointer for this module is needed up front to correctly set the module parent hierarchy.
// The actual instance is created at the end, when all terraform blocks
// are evaluated.
rootModule := new(terraform.Module)

submodules := e.evaluateSubmodules(ctx, rootModule, fsMap)

e.logger.Debug("Starting post-submodules evaluation...")
e.evaluateSteps()

e.logger.Debug("Module evaluation complete.")
// terraform.NewModule must be called at the end, as `e.blocks` can be
// changed up until the last moment.
*rootModule = *terraform.NewModule(e.projectRootPath, e.modulePath, e.blocks, e.ignores)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels really unfortunate 😢

Comment on lines 415 to 421
if countAttrVal.IsNull() {
// Defer to the next pass when the count might be known
countFiltered = append(countFiltered, block)
continue
}

count := 1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defering expansion when count is unknown.

Copy link
Contributor Author

@Emyrk Emyrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR currently only solves this for count, but the same problem exists for other expansion block types. If this solution is satisfactory, I can write some tests for the other meta arguments.

Comment on lines +263 to +265
// Always attempt to expand any blocks that might now be expandable
// due to new context being set.
e.blocks = e.expandBlocks(e.blocks)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the biggest change. It allows expandBlocks to occur in evaluateSteps.

From my understanding of expandBlocks this should be a safe operation. Is there a reason it is currently called outside this context? @nikpivkin ?

@Emyrk Emyrk marked this pull request as ready for review March 19, 2025 18:04
@Emyrk Emyrk requested review from simar7 and nikpivkin as code owners March 19, 2025 18:04
Comment on lines +1803 to +1827
func TestBlockCountModules(t *testing.T) {
t.Skip("This test is currently failing, the 'count = 0' module 'bar' is still loaded")
// `count` meta attributes are incorrectly handled when referencing
// a module output.
files := map[string]string{
"main.tf": `
module "foo" {
source = "./modules/foo"
}

module "bar" {
source = "./modules/foo"
count = module.foo.staticZero
}
`,
"modules/foo/main.tf": `
output "staticZero" {
value = 0
}
`,
}

modules := parse(t, files)
require.Len(t, modules, 2)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does evaluating sub-modules also need to occur in the inner loop? Defering them if their count is unknown?

@Emyrk Emyrk mentioned this pull request Apr 8, 2025
Emyrk added 6 commits April 9, 2025 10:00
Do not expand unknown `count` blocks. Run `expandBlocks` in eval to
allow submodule returns to affect the `count` when using module
outputs.
The depth of submodule evalutation is still limited
Module counts are incorrectly being handled
@Emyrk Emyrk force-pushed the stevenmasley/module_output_count branch from 80e01d1 to 6eb6063 Compare April 9, 2025 15:07
This was referenced Apr 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants