From f64bf1988bc8ef5866c09897aeafe7456938bcf6 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Mon, 13 Nov 2023 16:22:27 +0100 Subject: [PATCH 1/3] cmd/*: Add -version flag to executables This sets the version to `git describe --always --dirty` using the `-X github.com/containers/gvisor-tap-vsock/pkg/types.ModuleVersion` linker flag. This adds a -version flag to all binaries which currently have command-line flags. Correct versioning when installing from tarballs, and through `go install` will be addressed in the next commits. This fixes https://github.com/containers/gvisor-tap-vsock/issues/295 Signed-off-by: Christophe Fergeau --- Makefile | 4 +++- cmd/gvproxy/main.go | 8 ++++++++ cmd/ssh-over-vsock/main.go | 9 +++++++++ cmd/vm/main_linux.go | 7 +++++++ cmd/win-sshproxy/main.go | 10 ++++++++-- pkg/types/version.go | 34 ++++++++++++++++++++++++++++++++++ rpm/gvisor-tap-vsock.spec | 4 ++-- 7 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 pkg/types/version.go diff --git a/Makefile b/Makefile index e2203d2f4..fb0118e93 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ TAG ?= $(shell git describe --match=NeVeRmAtCh --always --abbrev=40 --dirty) +GIT_VERSION ?= $(shell git describe --always --dirty) CONTAINER_RUNTIME ?= podman .PHONY: build @@ -7,7 +8,8 @@ build: gvproxy qemu-wrapper vm TOOLS_DIR := tools include tools/tools.mk -LDFLAGS = -s -w +VERSION_LDFLAGS=-X github.com/containers/gvisor-tap-vsock/pkg/types.gitVersion=$(GIT_VERSION) +LDFLAGS = -s -w $(VERSION_LDFLAGS) .PHONY: gvproxy gvproxy: diff --git a/cmd/gvproxy/main.go b/cmd/gvproxy/main.go index 8e6977513..cc5a5187d 100644 --- a/cmd/gvproxy/main.go +++ b/cmd/gvproxy/main.go @@ -56,6 +56,8 @@ const ( ) func main() { + version := types.NewVersion("gvproxy") + version.AddFlag() flag.Var(&endpoints, "listen", "control endpoint") flag.BoolVar(&debug, "debug", false, "Print debug info") flag.IntVar(&mtu, "mtu", 1500, "Set the MTU") @@ -72,6 +74,12 @@ func main() { flag.StringVar(&pidFile, "pid-file", "", "Generate a file with the PID in it") flag.Parse() + if version.ShowVersion() { + fmt.Println(version.String()) + os.Exit(0) + } + + log.Infof(version.String()) ctx, cancel := context.WithCancel(context.Background()) // Make this the last defer statement in the stack defer os.Exit(exitCode) diff --git a/cmd/ssh-over-vsock/main.go b/cmd/ssh-over-vsock/main.go index 2dbcca113..f94ed01eb 100644 --- a/cmd/ssh-over-vsock/main.go +++ b/cmd/ssh-over-vsock/main.go @@ -4,8 +4,10 @@ import ( "flag" "fmt" "net" + "os" "github.com/containers/gvisor-tap-vsock/pkg/transport" + "github.com/containers/gvisor-tap-vsock/pkg/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -19,6 +21,8 @@ var ( ) func main() { + version := types.NewVersion("ssh-over-vsock") + version.AddFlag() flag.StringVar(&ip, "ip", "192.168.127.2", "ip of the host") flag.IntVar(&port, "port", 22, "port of the host") flag.StringVar(&user, "user", "", "ssh user") @@ -26,6 +30,11 @@ func main() { flag.StringVar(&endpoint, "url", "/tmp/network.sock", "url of the daemon") flag.Parse() + if version.ShowVersion() { + fmt.Println(version.String()) + os.Exit(0) + } + if err := run(); err != nil { logrus.Fatal(err) } diff --git a/cmd/vm/main_linux.go b/cmd/vm/main_linux.go index 882cffe8f..71e2106b9 100644 --- a/cmd/vm/main_linux.go +++ b/cmd/vm/main_linux.go @@ -35,6 +35,8 @@ var ( ) func main() { + version := types.NewVersion("gvforwarder") + version.AddFlag() flag.StringVar(&endpoint, "url", fmt.Sprintf("vsock://2:1024%s", types.ConnectPath), "url where the tap send packets") flag.StringVar(&iface, "iface", "tap0", "tap interface name") flag.StringVar(&stopIfIfaceExist, "stop-if-exist", "eth0,ens3,enp0s1", "stop if one of these interfaces exists at startup") @@ -44,6 +46,11 @@ func main() { flag.BoolVar(&tapPreexists, "preexisting", false, "use preexisting/preconfigured TAP interface") flag.Parse() + if version.ShowVersion() { + fmt.Println(version.String()) + os.Exit(0) + } + expected := strings.Split(stopIfIfaceExist, ",") links, err := netlink.LinkList() if err != nil { diff --git a/cmd/win-sshproxy/main.go b/cmd/win-sshproxy/main.go index b29332eaf..73d1fdd75 100644 --- a/cmd/win-sshproxy/main.go +++ b/cmd/win-sshproxy/main.go @@ -14,6 +14,7 @@ import ( "unsafe" "github.com/containers/gvisor-tap-vsock/pkg/sshclient" + "github.com/containers/gvisor-tap-vsock/pkg/types" "github.com/containers/winquit/pkg/winquit" "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" @@ -33,10 +34,15 @@ var ( func main() { args := os.Args if len(args) > 1 { - if args[1] == "-debug" { + switch args[1] { + case "-version": + version := types.NewVersion("win-sshproxy") + fmt.Println(version.String()) + os.Exit(0) + case "-debug": debug = true args = args[2:] - } else { + default: args = args[1:] } } diff --git a/pkg/types/version.go b/pkg/types/version.go new file mode 100644 index 000000000..109007e37 --- /dev/null +++ b/pkg/types/version.go @@ -0,0 +1,34 @@ +package types + +import ( + "flag" + "fmt" +) + +var ( + // set using the '-X github.com/containers/gvisor-tap-vsock/pkg/types.gitVersion' linker flag + gitVersion = "" +) + +type version struct { + binaryName string + showVersion bool +} + +func NewVersion(binaryName string) *version { //nolint:revive + return &version{ + binaryName: binaryName, + } +} + +func (ver *version) String() string { + return fmt.Sprintf("%s version %s", ver.binaryName, gitVersion) +} + +func (ver *version) AddFlag() { + flag.BoolVar(&ver.showVersion, "version", false, "Print version information") +} + +func (ver *version) ShowVersion() bool { + return ver.showVersion +} diff --git a/rpm/gvisor-tap-vsock.spec b/rpm/gvisor-tap-vsock.spec index c691daebf..e9cc2bfb1 100644 --- a/rpm/gvisor-tap-vsock.spec +++ b/rpm/gvisor-tap-vsock.spec @@ -92,8 +92,8 @@ CGO_CFLAGS=$(echo $CGO_CFLAGS | sed 's/-specs=\/usr\/lib\/rpm\/redhat\/redhat-an export CGO_CFLAGS+=" -m64 -mtune=generic -fcf-protection=full" %endif -# reset LDFLAGS for plugins and gvisor binaries -LDFLAGS='' +# reset LDFLAGS for plugins and gvisor binaries, but ensure gvproxy --version and such is set +LDFLAGS="-X github.com/containers/gvisor-tap-vsock/pkg/types.gitVersion=%{version}" # build gvisor-tap-vsock binaries %gobuild -o bin/gvproxy ./cmd/gvproxy From b61aa3acd80b2a3e83ffaf4e5dd45786e68abb08 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Wed, 15 Nov 2023 12:06:52 +0100 Subject: [PATCH 2/3] version: Add moduleVersionFromBuildInfo This adds correct version information for `gvproxy -version` when it's installed using: ``` go install github.com/containers/gvisor-tap-vsock/cmd/gvproxy ``` Signed-off-by: Christophe Fergeau --- pkg/types/version.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/pkg/types/version.go b/pkg/types/version.go index 109007e37..84b9252fc 100644 --- a/pkg/types/version.go +++ b/pkg/types/version.go @@ -3,6 +3,7 @@ package types import ( "flag" "fmt" + "runtime/debug" ) var ( @@ -22,7 +23,7 @@ func NewVersion(binaryName string) *version { //nolint:revive } func (ver *version) String() string { - return fmt.Sprintf("%s version %s", ver.binaryName, gitVersion) + return fmt.Sprintf("%s version %s", ver.binaryName, moduleVersion()) } func (ver *version) AddFlag() { @@ -32,3 +33,25 @@ func (ver *version) AddFlag() { func (ver *version) ShowVersion() bool { return ver.showVersion } + +func moduleVersion() string { + switch { + // This will be set when building from git using make + case gitVersion != "": + return gitVersion + // moduleVersionFromBuildInfo() will be set when using `go install` + default: + return moduleVersionFromBuildInfo() + } +} + +func moduleVersionFromBuildInfo() string { + info, ok := debug.ReadBuildInfo() + if !ok { + return "" + } + if info.Main.Version == "(devel)" { + return "" + } + return info.Main.Version +} From e13e93c3af874bad01a303a1212f625136923a72 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Wed, 15 Nov 2023 12:08:10 +0100 Subject: [PATCH 3/3] version: Add versioning for github tarballs When building from github tarballs, getting the version from `git describe` won't work, or worse, will be irrelevant [1] However, we can make use of $Format$ and .gitattributes as described in [2] to automatically substitute the correct version in a go variable when `git archive` is used. In particular, the correct version number will automatically be substituted when GitHub creates release tarballs. [1] rpms/gvisor-tap-vsock.spec uses `%autosetup -Sgit -n %{name}-%{version}` which unpacks the release tarball in a newly created git repository. [2] https://icinga.com/blog/2022/05/25/embedding-git-commit-information-in-go-binaries/ Signed-off-by: Christophe Fergeau --- .gitattributes | 1 + pkg/types/version.go | 7 +++++++ rpm/gvisor-tap-vsock.spec | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..d1273eaf9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +/pkg/types/version.go export-subst diff --git a/pkg/types/version.go b/pkg/types/version.go index 84b9252fc..845ba439b 100644 --- a/pkg/types/version.go +++ b/pkg/types/version.go @@ -4,11 +4,15 @@ import ( "flag" "fmt" "runtime/debug" + "strings" ) var ( // set using the '-X github.com/containers/gvisor-tap-vsock/pkg/types.gitVersion' linker flag gitVersion = "" + // set through .gitattributes when `git archive` is used + // see https://icinga.com/blog/2022/05/25/embedding-git-commit-information-in-go-binaries/ + gitArchiveVersion = "$Format:%(describe)$" ) type version struct { @@ -36,6 +40,9 @@ func (ver *version) ShowVersion() bool { func moduleVersion() string { switch { + // This will be substituted when building from a GitHub tarball + case !strings.HasPrefix(gitArchiveVersion, "$Format:"): + return gitArchiveVersion // This will be set when building from git using make case gitVersion != "": return gitVersion diff --git a/rpm/gvisor-tap-vsock.spec b/rpm/gvisor-tap-vsock.spec index e9cc2bfb1..c691daebf 100644 --- a/rpm/gvisor-tap-vsock.spec +++ b/rpm/gvisor-tap-vsock.spec @@ -92,8 +92,8 @@ CGO_CFLAGS=$(echo $CGO_CFLAGS | sed 's/-specs=\/usr\/lib\/rpm\/redhat\/redhat-an export CGO_CFLAGS+=" -m64 -mtune=generic -fcf-protection=full" %endif -# reset LDFLAGS for plugins and gvisor binaries, but ensure gvproxy --version and such is set -LDFLAGS="-X github.com/containers/gvisor-tap-vsock/pkg/types.gitVersion=%{version}" +# reset LDFLAGS for plugins and gvisor binaries +LDFLAGS='' # build gvisor-tap-vsock binaries %gobuild -o bin/gvproxy ./cmd/gvproxy