warrensbox/terraform-switcher

Search parent directories for Terraform version

Opened this issue · 2 comments

Is your feature request related to a problem? Please describe.

At my company, we have a bunch of Terraform repos. Within each of those repos, we have hundreds of different Terraform root modules. Currently, we have a .terraform-version at the root of each of those repos and use tfenv to search the parent directories looking for those .terraform-version files and switch the version automatically.

We would like to switch to use tfswitch because it is more performant than tfenv with certain IDEs and Terraform auto-formatting plugins, but it would currently require us to go from specifying the Terraform version in a handful of spots at the root of each repo, to specifying it thousands of times in each of our Terraform root modules.

Describe the solution you'd like

Instead of the current behavior of only looking in the current directory for a file that specifies the Terraform version, we would like for tfswitch to automatically search upwards through the parent directories until it finds a .terraform-version (or other) file and switch based on that, or if no match is found, drop into the interactive Select Terraform version prompt.

Additional context

The issue is not simply with adjusting the hooks that are provided by https://github.com/warrensbox/terraform-switcher#automation, even explicitly running tfswitch does not consider the .terraform-version file in a parent directory. Whenever this feature is implemented, we should also adjust the hook recommendations, maybe to automatically trigger any time that the current directory has .tf files?

@joe-a-t @warrensbox is this as simple as updating the current filepath.Join use at

TFVersionFile := filepath.Join(*chDirPath, tfvFilename) //settings for .terraform-version file in current directory (tfenv compatible)
RCFile := filepath.Join(*chDirPath, rcFilename) //settings for .tfswitchrc file in current directory (backward compatible purpose)
TOMLConfigFile := filepath.Join(*chDirPath, tomlFilename) //settings for .tfswitch.toml file in current directory (option to specify bin directory)
HomeTOMLConfigFile := filepath.Join(homedir, tomlFilename) //settings for .tfswitch.toml file in home directory (option to specify bin directory)
TGHACLFile := filepath.Join(*chDirPath, tgHclFilename) //settings for terragrunt.hcl file in current directory (option to specify bin directory)
to instead use a function that makes use of something like https://pkg.go.dev/path/filepath#WalkDir but just on each directory going up the tree? Would chDirPath behaviour need to be maintained if this change was made?

I'm happy to have an attempt at a PR for this if no one else has touched it yet.

Something along the lines of this, if chDirPath isn't required?

func findSettingsFile(file string) (string, error) {
	workingDir, _ := os.Getwd()
	var path string

	for {
		path = fmt.Sprintf("%v/%v", workingDir, file)
		if _, err := os.Stat(path); err == nil {
			break
		} else {
			workingDir = filepath.Dir(workingDir)
		}
		if workingDir == "/" {
			return "", errors.New("file_not_found")
		}
	}

	return path, nil
}