Skip to content

Commit 30ff4c1

Browse files
authored
feat: Discovey false positive parsing errors (#4605)
* Reduced false positive parsing errors * Simplified discovery errors * Parsing errors simplification * Simplified errors printing * Added test for remote source runner pool * Tests cleanup * Added filtering of diagnostic errors containing outputs * source update
1 parent c4989b2 commit 30ff4c1

4 files changed

Lines changed: 61 additions & 3 deletions

File tree

internal/discovery/discovery.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"sort"
1010
"strings"
1111

12+
"github.com/gruntwork-io/terragrunt/config/hclparse"
13+
1214
"github.com/gruntwork-io/terragrunt/internal/experiment"
1315
"github.com/gruntwork-io/terragrunt/util"
1416

@@ -18,6 +20,7 @@ import (
1820
"github.com/gruntwork-io/terragrunt/internal/errors"
1921
"github.com/gruntwork-io/terragrunt/options"
2022
"github.com/gruntwork-io/terragrunt/pkg/log"
23+
"github.com/hashicorp/hcl/v2"
2124
"github.com/zclconf/go-cty/cty"
2225
)
2326

@@ -248,6 +251,26 @@ func (c *DiscoveredConfig) Parse(ctx context.Context, l log.Logger, opts *option
248251
config.ExcludeBlock,
249252
)
250253

254+
if suppressParseErrors {
255+
// If suppressing parse errors, we want to filter diagnostics that contain references to outputs,
256+
// while leaving other diagnostics as is.
257+
parseOptions := append(parsingCtx.ParserOptions, hclparse.WithDiagnosticsHandler(func(file *hcl.File, hclDiags hcl.Diagnostics) (hcl.Diagnostics, error) {
258+
filteredDiags := hcl.Diagnostics{}
259+
260+
for _, hclDiag := range hclDiags {
261+
containsOutputRef := strings.Contains(strings.ToLower(hclDiag.Summary), "output") ||
262+
strings.Contains(strings.ToLower(hclDiag.Detail), "output")
263+
264+
if !containsOutputRef {
265+
filteredDiags = append(filteredDiags, hclDiag)
266+
}
267+
}
268+
269+
return filteredDiags, nil
270+
}))
271+
parsingCtx = parsingCtx.WithParseOption(parseOptions)
272+
}
273+
251274
//nolint: contextcheck
252275
cfg, err := config.ParseConfigFile(parsingCtx, l, parseOpts.TerragruntConfigPath, nil)
253276
if err != nil {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
terraform {
2+
source = "github.com/gruntwork-io/terragrunt.git//test/fixtures/fail-fast/unit-a?ref=v0.84.1"
3+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
terraform {
2+
source = "github.com/gruntwork-io/terragrunt.git//test/fixtures/fail-fast/unit-a?ref=v0.84.1"
3+
}
4+
5+
dependency "unit-a" {
6+
config_path = "../unit-a"
7+
mock_outputs = {
8+
data = "test-data"
9+
}
10+
}
11+
12+
inputs = {
13+
data = dependency.unit-a.outputs.data
14+
}

test/integration_runner_pool_test.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ import (
1313
)
1414

1515
const (
16-
testFixtureMixedConfig = "fixtures/mixed-config"
17-
testFixtureFailFast = "fixtures/fail-fast"
16+
testFixtureMixedConfig = "fixtures/mixed-config"
17+
testFixtureFailFast = "fixtures/fail-fast"
18+
testFixtureRunnerPoolRemoteSource = "fixtures/runner-pool-remote-source"
1819
)
1920

2021
func TestRunnerPoolDiscovery(t *testing.T) {
@@ -119,9 +120,13 @@ func TestRunnerPoolDestroyFailFast(t *testing.T) {
119120
tmpEnvPath := helpers.CopyEnvironment(t, testFixtureFailFast)
120121
testPath := util.JoinPath(tmpEnvPath, testFixtureFailFast)
121122

122-
_, _, err := helpers.RunTerragruntCommandWithOutput(t, "terragrunt run --all --non-interactive --experiment runner-pool --fail-fast --working-dir "+testPath+" -- apply")
123+
_, stdout, err := helpers.RunTerragruntCommandWithOutput(t, "terragrunt run --all --non-interactive --experiment runner-pool --fail-fast --working-dir "+testPath+" -- apply")
123124
require.NoError(t, err)
124125

126+
// Verify that there are no parsing errors in the output
127+
require.NotContains(t, stdout, "Error: Unsupported block type")
128+
require.NotContains(t, stdout, "This object does not have an attribute named \"outputs\"")
129+
125130
// create fail.txt in unit-a to trigger a failure
126131
helpers.CreateFile(t, testPath, "unit-b", "fail.txt")
127132
stdout, stderr, _ := helpers.RunTerragruntCommandWithOutput(t, "terragrunt run --all --non-interactive --experiment runner-pool --fail-fast --working-dir "+testPath+" -- destroy")
@@ -147,3 +152,16 @@ func TestRunnerPoolDestroyDependencies(t *testing.T) {
147152
assert.Contains(t, stdout, "unit-a tf-path="+wrappedBinary()+" msg=Destroy complete! Resources: 1 destroyed.")
148153

149154
}
155+
156+
func TestRunnerPoolRemoteSource(t *testing.T) {
157+
t.Parallel()
158+
159+
helpers.CleanupTerraformFolder(t, testFixtureRunnerPoolRemoteSource)
160+
tmpEnvPath := helpers.CopyEnvironment(t, testFixtureRunnerPoolRemoteSource)
161+
testPath := util.JoinPath(tmpEnvPath, testFixtureRunnerPoolRemoteSource)
162+
163+
stdout, _, err := helpers.RunTerragruntCommandWithOutput(t, "terragrunt run --all --non-interactive --log-level debug --experiment runner-pool --working-dir "+testPath+" -- apply")
164+
require.NoError(t, err)
165+
// Verify that the output contains value produced from remote unit
166+
require.Contains(t, stdout, "data = \"unit-a\"")
167+
}

0 commit comments

Comments
 (0)