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

Fix root path lookup in validate-all #1376

Merged
merged 2 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions modules/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package git

import (
"os"
"os/exec"
"strings"

Expand Down Expand Up @@ -106,7 +107,24 @@ func GetRepoRoot(t testing.TestingT) string {

// GetRepoRootE retrieves the path to the root directory of the repo.
func GetRepoRootE(t testing.TestingT) (string, error) {
dir, err := os.Getwd()
if err != nil {
return "", err
}
return GetRepoRootForDirE(t, dir)
}

// GetRepoRootForDir retrieves the path to the root directory of the repo in which dir resides
func GetRepoRootForDir(t testing.TestingT, dir string) string {
out, err := GetRepoRootForDirE(t, dir)
require.NoError(t, err)
return out
}

// GetRepoRootForDirE retrieves the path to the root directory of the repo in which dir resides
func GetRepoRootForDirE(t testing.TestingT, dir string) (string, error) {
cmd := exec.Command("git", "rev-parse", "--show-toplevel")
cmd.Dir = dir
bytes, err := cmd.Output()
if err != nil {
return "", err
Expand Down
42 changes: 24 additions & 18 deletions modules/test-structure/test_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"path/filepath"
"strings"

"github.com/gruntwork-io/terratest/modules/git"

go_test "testing"

"github.com/gruntwork-io/terratest/modules/files"
Expand Down Expand Up @@ -192,29 +194,33 @@ func runValidateOnAllTerraformModules(
opts *ValidationOptions,
validationFunc func(t *go_test.T, fileType ValidateFileType, tfOps *terraform.Options),
) {
dirsToValidate, readErr := FindTerraformModulePathsInRootE(opts)
// Find the Git root
gitRoot, err := git.GetRepoRootForDirE(t, opts.RootDir)
require.NoError(t, err)

// Find the relative path between the root dir and the git root
relPath, err := filepath.Rel(gitRoot, opts.RootDir)
require.NoError(t, err)

// Copy git root to tmp
testFolder := CopyTerraformFolderToTemp(t, gitRoot, relPath)
require.NotNil(t, testFolder)

// Clone opts and override the root dir to the temp folder
clonedOpts, err := CloneWithNewRootDir(opts, testFolder)
require.NoError(t, err)

// Find TF modules
dirsToValidate, readErr := FindTerraformModulePathsInRootE(clonedOpts)
require.NoError(t, readErr)

for _, dir := range dirsToValidate {
dir := dir
t.Run(strings.TrimLeft(dir, "/"), func(t *go_test.T) {
// Determine the absolute path to the git repository root
cwd, cwdErr := os.Getwd()
require.NoError(t, cwdErr)
gitRoot, gitRootErr := filepath.Abs(filepath.Join(cwd, "../../"))
require.NoError(t, gitRootErr)

// Determine the relative path to the example, module, etc that is currently being considered
relativePath, pathErr := filepath.Rel(gitRoot, dir)
require.NoError(t, pathErr)
// Copy git root to tmp and supply the path to the current module to run init and validate on
testFolder := CopyTerraformFolderToTemp(t, gitRoot, relativePath)
require.NotNil(t, testFolder)

// Run Terraform init and terraform validate on the test folder that was copied to /tmp
// to avoid any potential conflicts with tests that may not use the same copy to /tmp behavior
tfOpts := &terraform.Options{TerraformDir: testFolder}
validationFunc(t, opts.FileType, tfOpts)
// Run the validation function on the test folder that was copied to /tmp to avoid any potential conflicts
// with tests that may not use the same copy to /tmp behavior
tfOpts := &terraform.Options{TerraformDir: dir}
validationFunc(t, clonedOpts.FileType, tfOpts)
})
}
}
36 changes: 36 additions & 0 deletions modules/test-structure/validate_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ type ValidationOptions struct {
ExcludeDirs []string
}

// CloneWithNewRootDir clones the given opts with a new root dir. Updates all include and exclude dirs to be relative
// to the new root dir.
func CloneWithNewRootDir(opts *ValidationOptions, newRootDir string) (*ValidationOptions, error) {
includeDirs, err := buildRelPathsFromFull(opts.RootDir, opts.IncludeDirs)
if err != nil {
return nil, err
}
excludeDirs, err := buildRelPathsFromFull(opts.RootDir, opts.ExcludeDirs)
if err != nil {
return nil, err
}

out, err := NewValidationOptions(newRootDir, includeDirs, excludeDirs)
if err != nil {
return nil, err
}
out.FileType = opts.FileType
return out, nil
}

// configureBaseValidationOptions returns a pointer to a ValidationOptions struct configured with sane, override-able defaults
// Note that the ValidationOptions's fields IncludeDirs and ExcludeDirs must be absolute paths, but this method will accept relative paths
// and build the absolute paths when instantiating the ValidationOptions struct, making it the preferred means of configuring
Expand Down Expand Up @@ -104,6 +124,22 @@ func NewTerragruntValidationOptions(rootDir string, includeDirs, excludeDirs []s
return opts, nil
}

func buildRelPathsFromFull(rootDir string, fullPaths []string) ([]string, error) {
var relPaths []string
for _, maybeFullPath := range fullPaths {
if filepath.IsAbs(maybeFullPath) {
relPath, err := filepath.Rel(rootDir, maybeFullPath)
if err != nil {
return nil, err
}
relPaths = append(relPaths, relPath)
} else {
relPaths = append(relPaths, maybeFullPath)
}
}
return relPaths, nil
}

func buildFullPathsFromRelative(rootDir string, relativePaths []string) []string {
var fullPaths []string
for _, maybeRelativePath := range relativePaths {
Expand Down