Skip to content

Commit ca970e5

Browse files
authored
fix: fix early destroy on wrong path (#57)
1 parent ad5f38d commit ca970e5

File tree

1 file changed

+65
-32
lines changed

1 file changed

+65
-32
lines changed

validor.go

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"slices"
1515
"sort"
1616
"strings"
17+
"sync"
1718
"testing"
1819

1920
"github.com/gruntwork-io/terratest/modules/terraform"
@@ -425,6 +426,10 @@ func runParityTest(t *testing.T, modules []*Module, config *Config) {
425426
}
426427
// Destroy all modules
427428
for _, module := range modules {
429+
terraform.WithDefaultRetryableErrors(t, module.Options)
430+
if _, err := terraform.InitE(t, module.Options); err != nil {
431+
t.Logf("cleanup init error for %s: %v", module.Name, err)
432+
}
428433
if err := module.Destroy(ctx, t); err != nil {
429434
t.Logf("cleanup error for %s: %v", module.Name, err)
430435
}
@@ -435,59 +440,87 @@ func runParityTest(t *testing.T, modules []*Module, config *Config) {
435440
var (
436441
modulesWithMajor []string
437442
modulesWithMinor []string
443+
planErrors []string
438444
)
445+
var mu sync.Mutex
439446

440447
for _, module := range modules {
441-
if slices.Contains(config.ExceptionList, module.Name) {
442-
t.Logf("Skipping parity check for %s as it is in the exception list", module.Name)
443-
continue
444-
}
448+
mod := module
449+
t.Run(mod.Name+"_parity", func(t *testing.T) {
450+
t.Parallel()
445451

446-
if module.ApplyFailed {
447-
t.Logf("Skipping parity check for %s as registry apply failed", module.Name)
448-
continue
449-
}
450-
451-
planStruct, err := module.PlanWithStruct(t)
452-
if err != nil {
453-
t.Fatalf("failed to plan %s with local paths: %v", module.Name, err)
454-
}
452+
if slices.Contains(config.ExceptionList, mod.Name) {
453+
t.Logf("Skipping parity check for %s as it is in the exception list", mod.Name)
454+
return
455+
}
455456

456-
summary := summarizePlanChanges(planStruct)
457-
moduleSummaries[module.Name] = summary
457+
if mod.ApplyFailed {
458+
t.Logf("Skipping parity check for %s as registry apply failed", mod.Name)
459+
return
460+
}
458461

459-
switch {
460-
case summary.hasMajorDrift():
461-
t.Logf("parity major drift: %s triggers replacements/destroys", module.Name)
462-
if len(summary.ReplaceAddresses) > 0 {
463-
t.Logf(" replacements: %v", summary.ReplaceAddresses)
462+
planStruct, err := mod.PlanWithStruct(t)
463+
if err != nil {
464+
t.Logf("parity error: failed to plan %s with local paths: %v", mod.Name, err)
465+
mu.Lock()
466+
planErrors = append(planErrors, fmt.Sprintf("%s: %v", mod.Name, err))
467+
mu.Unlock()
468+
return
464469
}
465-
if len(summary.DestroyAddresses) > 0 {
466-
t.Logf(" destroys: %v", summary.DestroyAddresses)
470+
471+
summary := summarizePlanChanges(planStruct)
472+
473+
mu.Lock()
474+
moduleSummaries[mod.Name] = summary
475+
switch {
476+
case summary.hasMajorDrift():
477+
modulesWithMajor = append(modulesWithMajor, mod.Name)
478+
case summary.hasChanges():
479+
modulesWithMinor = append(modulesWithMinor, mod.Name)
467480
}
468-
if len(summary.OtherAddresses) > 0 {
469-
t.Logf(" other actions: %v", summary.OtherAddresses)
481+
mu.Unlock()
482+
483+
switch {
484+
case summary.hasMajorDrift():
485+
t.Logf("parity major drift: %s triggers replacements/destroys", mod.Name)
486+
if len(summary.ReplaceAddresses) > 0 {
487+
t.Logf(" replacements: %v", summary.ReplaceAddresses)
488+
}
489+
if len(summary.DestroyAddresses) > 0 {
490+
t.Logf(" destroys: %v", summary.DestroyAddresses)
491+
}
492+
if len(summary.OtherAddresses) > 0 {
493+
t.Logf(" other actions: %v", summary.OtherAddresses)
494+
}
495+
case summary.hasChanges():
496+
t.Logf("parity drift detected: %s has additions/updates only (adds=%d, updates=%d)", mod.Name, summary.Adds, summary.Updates)
497+
default:
498+
t.Logf("parity confirmed: %s produces identical infrastructure with local paths", mod.Name)
470499
}
471-
modulesWithMajor = append(modulesWithMajor, module.Name)
472-
case summary.hasChanges():
473-
t.Logf("parity drift detected: %s has additions/updates only (adds=%d, updates=%d)", module.Name, summary.Adds, summary.Updates)
474-
modulesWithMinor = append(modulesWithMinor, module.Name)
475-
default:
476-
t.Logf("parity confirmed: %s produces identical infrastructure with local paths", module.Name)
500+
})
501+
}
502+
503+
if len(planErrors) > 0 {
504+
sort.Strings(planErrors)
505+
t.Logf("parity check initialization errors:")
506+
for _, errMsg := range planErrors {
507+
t.Logf("- %s", errMsg)
477508
}
509+
t.Fatalf("registry and local modules failed to re-initialize for %d module(s)", len(planErrors))
478510
}
479511

480512
if len(modulesWithMajor) > 0 {
481-
t.Logf("parity check summary (major drift):")
513+
sort.Strings(modulesWithMajor)
482514
for _, moduleName := range modulesWithMajor {
483515
summary := moduleSummaries[moduleName]
484-
t.Logf("- %s: %d replacements, %d destroys", moduleName, summary.Replaces, summary.Deletes)
516+
t.Logf("parity major drift: %s requires %d replacements and %d destroys", moduleName, summary.Replaces, summary.Deletes)
485517
}
486518
t.Logf("these changes will force resource recreation and require a major version bump")
487519
t.Fatalf("registry and local modules are out of parity for %d module(s)", len(modulesWithMajor))
488520
}
489521

490522
if len(modulesWithMinor) > 0 {
523+
sort.Strings(modulesWithMinor)
491524
t.Logf("parity drift summary (non-breaking): %v", modulesWithMinor)
492525
}
493526

0 commit comments

Comments
 (0)