terraform icon indicating copy to clipboard operation
terraform copied to clipboard

Bash completion not working with terraform deb install

Open joe-mojo opened this issue 4 years ago • 1 comments

Terraform version : 0.15.5 debian package

When double-taping tab, the terminal display a message saying /usr/local/bin/terraform is not found.

This occurs because terraform -install-autocomplete is adding the line complete -C /usr/local/bin/terraform terraform (in .bashrc) instead of complete -C /usr/bin/terraform terraform or complete -C $(which terraform) terraform.

joe-mojo avatar Jul 15 '21 09:07 joe-mojo

Hi @joe-mojo! Thanks for reporting this.

It took a little while for me to understand what's going on here because unfortunately this autocomplete behavior is largely implemented by some upstream libraries we use in Terraform, but in the end I found the sequence of events that lead from Terraform, through the underlying CLI library, and into the autocomplete library:

https://github.com/hashicorp/terraform/blob/0729e9fdd7fa843ebeef8c5c14cab9754c3377c5/main.go#L262

https://github.com/hashicorp/terraform/blob/0729e9fdd7fa843ebeef8c5c14cab9754c3377c5/main.go#L341-L351

https://github.com/mitchellh/cli/blob/5454ffe87bc5c6d8b6b21c825617755e18a07828/cli.go#L217-L223

https://github.com/mitchellh/cli/blob/5454ffe87bc5c6d8b6b21c825617755e18a07828/autocomplete.go#L21-L23

https://github.com/posener/complete/blob/v1.2.1/cmd/install/install.go#L19-L24

https://github.com/posener/complete/blob/v1.2.1/cmd/install/bash.go#L13-L19

https://github.com/posener/complete/blob/v1.2.1/cmd/install/bash.go#L30-L32

filepath.Base("/usr/bin/terraform") should return just terraform, with no particular path prefix, and so that's what should make it all the way through to the github.com/posener/complete/cmd/install.Install function, at which point that library's getBinaryPath does its own determination of the actual executable path:

https://github.com/posener/complete/blob/v1.2.1/cmd/install/install.go#L101-L107

os.Executable uses a very different strategy for determining the executable path, varying by platform:

// We query the executable path at init time to avoid the problem of
// readlink returns a path appended with " (deleted)" when the original
// binary gets deleted.
var executablePath, executablePathErr = func() (string, error) {
	var procfn string
	switch runtime.GOOS {
	default:
		return "", errors.New("Executable not implemented for " + runtime.GOOS)
	case "linux", "android":
		procfn = "/proc/self/exe"
	case "netbsd":
		procfn = "/proc/curproc/exe"
	}
	return Readlink(procfn)
}()

func executable() (string, error) {
	return executablePath, executablePathErr
}

Since we're talking about Debian I'm going to assume we end up in the case "linux" branch here, and so the executable path that -install-autocomplete will ultimately use is the target of the symlink at /proc/self/exe.

So with all of that said, I think the question we need to answer here is how /proc/self/exe ended up referring to /usr/local/bin/terraform if on your system Terraform is at /usr/bin/terraform. Is there anything unusual about your system configuration that might make it ambiguous where the Terraform executable actually is? For example, are there any symlinks or hardlinks in the path leading to terraform that would cause there to be more than one possible path to the executable? Are you using software like Docker which uses the Linux kernel namespaces feature to give different processes each a different "view" of the virtual filesystem?

Unfortunately I think unless we can figure out why /proc/self/exe is not reflecting the correct path on your system we won't be able to find a solution to this. Even if we do, I expect we'll end up having to send a fix upstream to github.com/posener/complete because ultimately we're relying entirely on that library's logic for generating a suitable configuration for each of the different supported shells. :confused:

apparentlymart avatar Jul 22 '21 23:07 apparentlymart