operator-controller
operator-controller copied to clipboard
Switch to `go tool` for tool dependency management
There is a proposal for go to receive support for tool dependency management which might land as soon as Go 1.22: https://github.com/golang/go/issues/48429
Once it is available and our codebase is updated to the corresponding Go version we should switch to native support.
At the moment of writing we use github.com/bwplotka/bingo for tool pinning.
Can I sign up for this one?
@yuriolisa thanks for your interest in this. Unfortunately from https://github.com/golang/go/issues/48429 it looks like we will have to wait a longer. As far as I understand this feature didn't make it into Go 1.22 and will likely not be release in 1.23.
It seems like this will be released in 1.24 with chis about 2 months away: https://github.com/golang/go/issues/48429#issuecomment-2504513067
It seems like all the relevant changes got merged in Go and the issue is now closed. We should be able to use it once we upgrade to 1.24.
Removed good first issue label because it is more complicated than it seems :)
I've been experimenting with 1.24 tool management in this PR.
It seems like it is possible to achieve what we currently have with bingo:
- We can have a separate modfile for each tool so their dependencies won't conflict (as of today - our tools do have conflicts between themselves).
- Go 1.24 will handle tool installation and caching between projects (in the same way it caches modules between projects).
- We will be able to to continue using
makethe same way as we currently do
What will change:
- Instead of
bingoCLI we will have to use Go CLI. And this is where bingo is easier:
versus go 1.24:# Can just run this in the project root bingo get sigs.k8s.io/controller-tools/cmd/controller-gen@new-version
We can probably do some makefile magic for this, but still. Also - if we accidentally run# Have to specify path to to the right module go get -modfile tools/controller-gen.mod -tool sigs.k8s.io/controller-tools/cmd/controller-gen@new-versiongo mod tidyagain one of these tools modfiles -go mod tidywill add a bunch of dependencies from the main module, I think. - Go 1.24 currently doesn't support build tags for tools. I think it is currently recommended to use
go runfor tools with build tags, but I haven't tried this out yet.
It is also possible to use tool management with the main go.mod in the repo root, but in this case we will have same dependency hell as with tools.go: there will be dependency conflicts between tools themselves and our codebase as everything will be sharing the same graph.
- We can have a separate modfile for each tool so their dependencies won't conflict (as of today - our tools do have conflicts between themselves).
It is also possible to use tool management with the main
go.modin the repo root, but in this case we will have same dependency hell as withtools.go: there will be dependency conflicts between tools themselves and our codebase as everything will be sharing the same graph.
Want to clarify these bits. When I'm referring to tools.go I mean the pattern where people create a go file with blank imports and with a build tag such as tools which is excluded from the build process of the main codebase by default.
This tricks go to add these dependencies into module's mod file. This works well (with some caveats which are not important here) when there are no conflicts between the codebase and tools. When there are some dependencies shared between codebase and tools - it might be a problem because there will be a single dependency graph between tools and the codebase. Or even if the tools have shared dependencies. Go will try to resolve dependencies, but in some cases it will throw hands up in the air. At the moment of writing, It is the case for our repos where we use a lot of dependencies from k8s and some of the tools such as kustomize also use them and can't agree on the version. Last week, when I was playing with it kustomize was conflicting with some other tool.
Anyway - looking into the future, Go 1.24 will help to avoid having to use tools.go pattern by adding a new directive into mod file and tooling around it.
However, by default Go uses module's go.mod file for managing tools. This means that it also shares dependency the graph between the codebase and all the tools. And we will have the same issue as with tools.go pattern here.
It is possible to specify a custom modfile for each tool and this is what I did in my experimental PR. This way codebase doesn't share the dependency graph with tools and tools between themselves do not share the dependency graph. It works in the same way as Bingo, but UX is not as nice because:
- Requires developers to know which modfile to use for each tool or come up with tooling\scripts around it
- There is currently no support for build tags for tools. There was a suggestion to use
go runsomewhere (can't find it right now)
See the message above for examples.
Hi @m1kola
Based on the above description, I understand that it would not be a good thing. So, can we not close this one?
As of Go 1.24 - I think it is probably better to keep bingo. After Go 1.24 release there was a lot feedback for go tool from the community. I haven't followed this space very closely, but I'm hopeful that go tool will evolve to better serve more use cases (including operator-controller's).
Feel free to close this for now.
HI @m1kola
Thank you a lot for your input. So, I am moving forward with closing this one. If things evolve and we see the need for change, we can always revisit and re-open it.
Thank you for the collaboration and for checking this one.