warrensbox/terraform-switcher

Running tfswitch as a plain user fails when root has run it before

Closed this issue · 5 comments

First time opening a bug here, so bear with me.

Issue #151 added a feature to install terraform in $HOME/bin if the executing user does not have write permissions to /usr/local/bin. This feature works if root has not run tfswitch. When root has executed tfswitch, the action fails.

Expected behavior:

tfswitch updates $HOME/bin symlinks, and does not try to update /usr/local/bin symlinks when the user does not have permissions.

Actual behavior:

root@xxx:~# tfswitch 1.5.2
Downloading to: /root/.terraform.versions
20957185 bytes downloaded
Switched terraform to version "1.5.2"
root@xxx:~# exit
logout

dwlocks@xxx:~$ tfswitch 1.5.3
Installing terraform at /home/dwlocks/bin
2024/03/15 13:11:32
                        Unable to remove symlink.
                        Maybe symlink already exist. Try removing existing symlink manually.
                        Try running "unlink /usr/local/bin/terraform" to remove existing symlink.
                        If error persist, you may not have the permission to create a symlink at /usr/local/bin/terraform.
                        Error: remove /usr/local/bin/terraform: permission denied
dwlocks@xxx:~$ tfswitch --version

Version: 0.13.1308
dwlocks@xxx:~$ echo $PATH
/home/dwlocks/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:....

I'm not sure if tfswitch should completely ignore symlinks in /usr/local/bin if the user does not have write access, or if this behavior is as intended. For me, $HOME/bin is already at the beginning of my path, so any home-dir symlink would take precedence over the system-default symlink. Effectively, tfswitch worked but returned an error to bash. The error broke docker build for my VS-Code devcontainer.

Mitigation

  • If root (more accurately, a user with write permission to /usr/local/bin) does not run tfswitch, users can run tfswitch without error.
  • If plain users have $HOME/bin before /usr/local/bin in their $PATH and run terraform after receiving this error, it works as intended.

You mixed up different stuff describing the issue you've encountered, though what you actually are looking for it this: https://github.com/warrensbox/terraform-switcher#use-tfswitchtoml-file--for-non-admin---users-with-limited-privilege-on-their-computers — either provide -b command line option or set it permanently with .tfswitch.toml file.

Thanks for responding so quickly! I'm confused about requiring -b to use the default location. This comment for the feature explicitly says otherwise:
#151 (comment)

That said, I do think this is an edge case. Here is the result of using -b:

dwlocks@xxx:~$ tfswitch -b ~/bin 1.5.4
2024/03/15 16:40:28
                        Unable to remove symlink.
                        Maybe symlink already exist. Try removing existing symlink manually.
                        Try running "unlink /usr/local/bin/terraform" to remove existing symlink.
                        If error persist, you may not have the permission to create a symlink at /usr/local/bin/terraform.
                        Error: remove /usr/local/bin/terraform: permission denied
dwlocks@xxx:~$ ls -la ~/bin
total 8
drwxr-xr-x  2 dwlocks dwlocks 4096 Mar 15 12:52 .
drwxr-x--- 15 dwlocks dwlocks 4096 Mar 15 16:39 ..

The bug appears have nothing to do with the feature I mentioned. Nor is it fixed using -b. Additionally, the symlink is not created as I previously thought. The bug is related to running tfswitch first with privileges, then without.

The bug is related to running tfswitch first with privileges, then without.

I wouldn't say this is a bug. This is more of a mixing different permissions.
What I'd suggest you to do is to remove /usr/local/bin/terraform manually under root and then use the bin parameter in ~/.tfswitch.toml.
This is what I've got in that file: bin = "$HOME/bin/terraform" — and this works for me w/o any issues (with no /usr/local/bin/terraform being either file or symlnik).

ps: unfortunately this project is sort of on halt at the moment and hence there's no option to implement any new features or have any kind of bugs fixed 😢 I you feel like missing some essential features you might want to look at other similar projects, like tfenv, tfswitcher, OpenTofu's tenv or else 🤷🏻

oof. Didn't realize the project was in hiatus. Just trying to be a good citizen. I would offer to update documentation to make this intended behavior clear, otherwise.

tfswitch works well enough; I don't think it's missing any essential features. The error message correctly identifies how to fix the issue, as well, so It's no problem for me. I definitely believe the behavior is an edge case that will rarely if ever come up in general usage.

The final conclusion is: "Either run tfswitch privileged, or run unprivileged. Never both." I can live with that. Recovery from a poor choice is easy.

Glad you've managed to solve your use case (have you? I hope so).

I love twswitch as it's the most simplest solution among its counterparts: I just cd into target dir with TF code, I run tfswitch w/o any args and it switches to the TF version that satisfies version constraint defined in the current TF code layer. This solves 90% of my use cases. The other 10% are solved by tfswitch as well (though sometimes with help of other tools) =)

Unfortunately this repo's settings prevent any changes w/o a collective decision of responsible persons and, since I'm the only active collaborator at this moment, the only what I can do is, well, post to issues and PRs 😢 Even call for collaborators, initiated by this repo's owner, got stuck since the owner has not enough availability for this project 😢