Bash completion not working with terraform deb install
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.
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: