Pin go.mod dependencies for different k8s api versions - go

My golang service uses k8s go api to communicate with Kubernetes clusters. Some of them are v1.9.6, while some clusters of v1.17.0 were recently added.
I am using go.mod to manage dependencies. However I am having trouble combining dependencies of different versions.
For example using dependencies for the old API look like this:
module k8sOld
go 1.13
replace k8s.io/api => k8s.io/api v0.0.0-20180127130940-acf347b865f2
require (
k8s.io/api v0.0.0-20180127130940-acf347b865f2
k8s.io/apimachinery v0.0.0-20180126010752-19e3f5aa3adc
k8s.io/client-go v6.0.1-0.20180321184741-e56f95336983+incompatible
k8s.io/kube-openapi v0.0.0-20200615155156-dffdd1682719
)
When I added newer version of Kubernetes API I tried it like this:
module k8sOld
go 1.13
replace k8s.io/api => k8s.io/api v0.0.0-20180127130940-acf347b865f2
replace k8s.io/api/new => k8s.io/api v0.17.0
require (
k8s.io/api v0.0.0-20180127130940-acf347b865f2
k8s.io/apimachinery v0.0.0-20180126010752-19e3f5aa3adc
k8s.io/client-go v6.0.1-0.20180321184741-e56f95336983+incompatible
k8s.io/kube-openapi v0.0.0-20200615155156-dffdd1682719
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
)
I named the package for new packages "k8s.io/{subpackage}/new" and used replace to point to the newer version.
I am not sure if this is ok and that is the first question.
The second and most basic one is ,supposing I find a way to refer to newer version, how can I refer subpackages of packages?
For example how can I use k8s.io/api/core/v1?
I tried naming it like this:
"k8s.io/api/{VERSION NAMING CONVENTION}/core/v1"
But it does not seem to work.
I also tried adding k8s.io/api/core/v1 {version number} to the require part of go.mod, but it cannot be used this way.
Any ideas on how I can use different versions of k8s go api under the same hood?

Related

ReadAll not declared by package iocompiler - Golang

I am using golang in my project.
The code is as follows
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"sync"
"time"
)
....
if response.StatusCode != 200 {
respBdy, _ := io.ReadAll(response.Body)
return fmt.Errorf("%v response from client: %v", response.StatusCode, respBdy)
}
When i run the project using make run, i am getting the following error
go-tools#v0.0.0-20220528203058-9108e3643722/messengers/client.go:133:17: undefined: io.ReadAll
On debugging, i can understand the problem is ReadAll not declared by package iocompiler
Any idea on how to fix this?
Edit: The go version i am using is
go version
go version go1.15.6 darwin/amd64
As Manjeet and Emile stated, starting from go1.16's release, the functions from io/ioutil are moved to io package.
Discard => io.Discard
NopCloser => io.NopCloser
ReadAll => io.ReadAll
ReadDir => os.ReadDir
ReadFile => os.ReadFile
TempDir => os.MkdirTemp
TempFile => os.CreateTemp
WriteFile => os.WriteFile
Linking release notes of go1.16 for reference.
About the mismatch of go versions: go1.13 in go.mod and go1.15 in terminal, the go version in go.mod gets added depending on the version when it was initialised using go mod init [module-path]. GoDoc page for go mod init doesn't clear your doubt but attaching for ref.
In other words, the go.mod doesn't denote your local go version. Rather, it gives the minimal go version and imported package's versions that will let your project (as module) run hassle-free.
I found a sample from an old project. Will try to explain on it.
module project-name
go 1.14
require (
github.com/go-redis/redis/v7 v7.4.0
github.com/stretchr/testify v1.6.1
github.com/vektra/mockery v1.1.2 // indirect
)
This means the project requires go1.14, along with redis#v7.4.0, testify#v1.6.1 and mockery#v1.1.2 at the very least. Lower than these versions "might" still work. Not recommended. Higher than those versions are expected to be better, but there is a possibility of change of names or package name like above. More details at gomod-ref.
Just another bit of info: the io and io/util are part of Go's standard library. This means that in order to use the function as io.ReadAll, you would need higher version of standard library, and so, higher version of Go (1.16 at least).
Conclusion: You can still keep go1.13 in go.mod. Just upgrade the go version in local. And if other devs are kind enough to let you upgrade in go.mod too, do it!
Opinion: I personally recommend go1.17's latest for now until all external packages implement go1.18 and generics.

Go Module Import - Invalid version: go.mod has malformed module path

I have looked all over for an answer for "go.mod has malformed module path" but I have not found an answer to why I can't get a library I am writing to import. To simplify I have made a tiny library repo: https://github.com/buphmin/test-go-pkg
Note: I am using the stripe api library for structure inspiration. https://github.com/stripe/stripe-go
Problem:
I create a library, go mod init , push code and tag to github. Then try to import package to use the library elsewhere and I get an error message: 'go get: github.com/buphmin/test-go-pkg#v1.0.0: invalid version: go.mod has malformed module path "github.com/buphmin/test-go-pkg/v1" at revision v1.0.0'
I have no idea why this is an issue and I have not found an answer thus far.
Steps to Reproduce
Assuming you have go installed.
Create local folder
go mod init <your_mod>
go get github.com/buphmin/test-go-pkg/v1
error occurs
Other info
go v1.16
ubuntu 18 LTS
go mod file
Copied from the source of truth listed above: https://github.com/buphmin/test-go-pkg
module github.com/buphmin/test-go-pkg/v1
go 1.16
Edit - Answer:
My understand now with the help of #Steven Penny is that v1, v2, etc has more significance than just organization. This article explains how go treats that versioning https://www.honeybadger.io/blog/golang-go-package-management.
This:
module github.com/buphmin/test-go-pkg/v1
is not valid. Should be this:
module github.com/buphmin/test-go-pkg

Go mod replace and github forks of /vN repositories

I've just sent a pull request to http://periph.io/x/devices/v3; it's already been merged, but something about the process was suboptimal:
First I cloned the repository (which is actually http://github.com/periph/devices; the module is named periph.io/x/devices/v3 though), so my fork is automatically called http://github.com/lutzky/devices. I wanted to test a separate piece of code I'm working on with the modified library, call it testclient; adding this to testclient/go.mod works:
replace periph.io/x/devices/v3 v3.6.9 => ../devices
However, this should also work (and would be useful if the pull request took longer to be accepted), and doesn't:
replace periph.io/x/devices/v3 v3.6.9 => github.com/lutzky/devices main
That gives this error:
testclient/go.mod:15: replace github.com/lutzky/devices:
version "v0.0.0-20210508194004-cae0146d8900" invalid:
go.mod has post-v0 module path "periph.io/x/devices/v3" at revision cae0146d8900
On a hunch, I figured I'd create a tag v3.6.9-newfeature and push that to my fork, and point the replace command at that. That doesn't work either:
testclient/go.mod:15: replace github.com/lutzky/devices:
version "v3.6.9-newfeature" invalid:
module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v3
So I can't use a v0 tag because go.mod says it's v3, but I can't use a v3 tag because the URL doesn't have /v3. I don't think I should modify go.mod in my forked repository (for one thing, that'd make the pull request silly). What's the intended way to go about this?
Here's the fix that you are looking for, I tested the following go.mod file and it works,
module test
go 1.14
replace periph.io/x/devices/v3 => github.com/lutzky/devices/v3 v3.6.9-newfeature
require (
periph.io/x/devices/v3 v3.6.9 // indirect
)
I first installed periph.io/x/devices/v3,
go get periph.io/x/devices/v3
Then I inserted the replace in go.mod,
replace periph.io/x/devices/v3 => github.com/lutzky/devices/v3 main
Format: replace <original_module> => <forked_repo> <branch>
Then I ran just go get. After that, the main in the replace instruction got swapped with v3.6.9-newfeature which is the latest tag on the forked repo's main branch, thus giving you the content that you see above.
Thanks to ramaraja-ramanujan#'s answer and a bit more debugging, I found the answer.
TL;DR - the correct answer is:
replace periph.io/x/devices/v3 v3.6.9 => github.com/lutzky/devices/v3 main
// this part was missing ^^^
This will work immediately when building, and go mod tidy (or go get) will change main to a specific tag. There are a couple of interesting side-notes to this:
The go proxy
The v3.6.9-newfeature tag was my own; I had created it as part of trying to get this to work. I've deleted it, and yet go mod tidy kept replacing main with v3.6.9-newfeature - no matter how many caches I cleared! Running strace it turned out that go was contacting http://proxy.golang.org. To disable this, I ran GOPROXY=direct go get. This replaced the line with the pseudo version v3.6.10-0.20210508194004-cae0146d8900. Note that this matches the current main commit in my fork, and neither my fork nor the original repo have v3.6.10 - it appears to have started with the existing v3.6.9 and incremented it.
The /v3 is not a subdirectory
Indeed, the source repo (https://github.com/periph/devices) does not have a v3 subdirectory. I thought what was going on is that the periph.io domain is doing some trickery - indeed going to http://periph.io/x/devices/v3 with a browser does work. However, it would appear that Go's resolution takes the final /v3 in the module path not to indicate, in this case, a subdirectory (but indeed a restriction on tag names). This is apparently allowed, and is discussed in https://golang.org/ref/mod, but it isn't entirely straightforward.

missing go.sum entry for module providing package <package_name>

Using the buffalo framework,
after bootstraping it via buffalo new <project_name>
I am trying to run buffalo dev
Expecting to see:
project running on port 3000
But I am getting those error messages instead
actions/app.go:4:2: missing go.sum entry for module providing package github.com/gobuffalo/buffalo (imported by sc_api/actions); to add:go get sc_api/actions
actions/app.go:13:2: missing go.sum entry for module providing package github.com/gobuffalo/mw-csrf (imported by sc_api/actions); to add: go get sc_api/actions
actions/app.go has been generated by buffalo, but in case you are wondering the error does match the import statement in this file.
// app.go
package actions
import (
"github.com/gobuffalo/buffalo" // 1rst line
"github.com/gobuffalo/envy"
forcessl "github.com/gobuffalo/mw-forcessl"
paramlogger "github.com/gobuffalo/mw-paramlogger"
"github.com/unrolled/secure"
"sc_api/models"
"github.com/gobuffalo/buffalo-pop/v2/pop/popmw"
csrf "github.com/gobuffalo/mw-csrf" // 2nd line
i18n "github.com/gobuffalo/mw-i18n"
"github.com/gobuffalo/packr/v2"
)
What does it mean ? How do I fix it ?
It seems the issue has nothing to do with Buffalo and more with my lack of understanding of Go in general.
running go mod tidy solved the issue
This command goes through the go.mod file to resolve dependencies:
delete the packages that are not needed
download those needed
update the go.sum
I am still unsure which of those actions did the trick... but the project runs now.
ps: I'll let the in-depth explanation/correction to the Go wizard out here.
i got the same issue when building a docker image. i tried go mod tidy and
also go get -t . as suggested here https://github.com/golang/go/issues/44129. both didnt worked for me though but updating my docker builder to version 1.18 worked.
I use go mod tidy -e solved the problem. The -e flag (added in Go 1.16) causes go mod tidy to attempt to proceed despite errors encountered while loading packages.The more about mod tidy: https://go.dev/ref/mod#go-mod-tidy

Kubernetes client go couldn't find module

I'm trying to connect to my local Kubernetes cluster hosted on minikube, here's the code for the same, now when I do go run minikube.go, it gives me an error saying:
../../../pkg/mod/k8s.io/client-go#v11.0.0+incompatible/kubernetes/scheme/register.go:26:2: module k8s.io/api#latest found (v0.19.0), but does not contain package k8s.io/api/auditregistration/v1alpha1`.
Now, I tried to manually install the package using go get then I found out that this package does not exist.
How can I make it work and fix this?.
My go.mod file in case anyone wants to see that.
Always specify matching versions of all three k8s.io/... components in your go.mod file
require (
...
k8s.io/api v0.19.0
k8s.io/apimachinery v0.19.0
k8s.io/client-go v0.19.0
...
)

Resources