From 3e2dcde58c74fd06257a4b7874c0150df63573d0 Mon Sep 17 00:00:00 2001 From: Srdjan Petrovic Date: Mon, 18 Sep 2023 10:14:53 -0700 Subject: [PATCH] Don't read tool version from a file. Instead, rely on the version stored inside the compiled binary. This version is automatically filled by `go install`. This change will allow us to simply tag the release and not have to also update the version manually. --- cmd/weaver-kube/deploy.go | 6 ++-- cmd/weaver-kube/version.go | 8 ++++-- internal/impl/docker.go | 56 ++++++++++++++++++++++++------------- internal/impl/version.go | 18 ++++++++++++ internal/version/version.go | 22 --------------- 5 files changed, 62 insertions(+), 48 deletions(-) create mode 100644 internal/impl/version.go delete mode 100644 internal/version/version.go diff --git a/cmd/weaver-kube/deploy.go b/cmd/weaver-kube/deploy.go index de2134a..6f868d3 100644 --- a/cmd/weaver-kube/deploy.go +++ b/cmd/weaver-kube/deploy.go @@ -36,9 +36,7 @@ const ( ) var ( - flags = flag.NewFlagSet("deploy", flag.ContinueOnError) - runInDevMode = flags.Bool("runInDevMode", false, "Whether deploy in development mode.") - + flags = flag.NewFlagSet("deploy", flag.ContinueOnError) deployCmd = tool.Command{ Name: "deploy", Description: "Deploy a Service Weaver app", @@ -141,7 +139,7 @@ func deploy(ctx context.Context, args []string) error { } // Build the docker image for the deployment. - image, err := impl.BuildAndUploadDockerImage(ctx, dep, config.LocalTag, config.Repo, *runInDevMode) + image, err := impl.BuildAndUploadDockerImage(ctx, dep, config.LocalTag, config.Repo) if err != nil { return err } diff --git a/cmd/weaver-kube/version.go b/cmd/weaver-kube/version.go index 8cf4e71..a2874ad 100644 --- a/cmd/weaver-kube/version.go +++ b/cmd/weaver-kube/version.go @@ -20,7 +20,7 @@ import ( "fmt" "runtime" - "github.com/ServiceWeaver/weaver-kube/internal/version" + "github.com/ServiceWeaver/weaver-kube/internal/impl" "github.com/ServiceWeaver/weaver/runtime/tool" ) @@ -30,7 +30,11 @@ var versionCmd = tool.Command{ Description: "Show weaver kube version", Help: "Usage:\n weaver kube version", Fn: func(context.Context, []string) error { - fmt.Printf("weaver kube v%d.%d.%d %s/%s\n", version.Major, version.Minor, version.Patch, runtime.GOOS, runtime.GOARCH) + version, _, err := impl.ToolVersion() + if err != nil { + return err + } + fmt.Printf("weaver kube %s %s/%s\n", version, runtime.GOOS, runtime.GOARCH) return nil }, } diff --git a/internal/impl/docker.go b/internal/impl/docker.go index 302b1b8..0f74787 100644 --- a/internal/impl/docker.go +++ b/internal/impl/docker.go @@ -15,6 +15,7 @@ package impl import ( + "bufio" "context" "fmt" "os" @@ -25,7 +26,6 @@ import ( "text/template" "time" - "github.com/ServiceWeaver/weaver-kube/internal/version" "github.com/ServiceWeaver/weaver/runtime/protos" "github.com/google/uuid" ) @@ -59,9 +59,9 @@ type buildSpec struct { // BuildAndUploadDockerImage builds a docker image and uploads it to a remote // repo, if one is specified. It returns the docker image tag that should // be used in the application containers. -func BuildAndUploadDockerImage(ctx context.Context, dep *protos.Deployment, buildTag, dockerRepo string, runInDevMode bool) (string, error) { +func BuildAndUploadDockerImage(ctx context.Context, dep *protos.Deployment, buildTag, dockerRepo string) (string, error) { // Create the build specifications. - spec, err := dockerBuildSpec(dep, buildTag, runInDevMode) + spec, err := dockerBuildSpec(dep, buildTag) if err != nil { return "", fmt.Errorf("unable to build image spec: %w", err) } @@ -82,32 +82,48 @@ func BuildAndUploadDockerImage(ctx context.Context, dep *protos.Deployment, buil } // dockerBuildSpec creates a build specification for an app deployment. -func dockerBuildSpec(dep *protos.Deployment, buildTag string, runInDevMode bool) (*buildSpec, error) { - files := []string{dep.App.Binary} - toolVersion := fmt.Sprintf("v%d.%d.%d", version.Major, version.Minor, version.Patch) - goInstall := []string{ - "github.com/ServiceWeaver/weaver-kube/cmd/weaver-kube@" + toolVersion, - } - if buildTag == "" { - buildTag = fmt.Sprintf("%s:%s", dep.App.Name, dep.Id[:8]) +func dockerBuildSpec(dep *protos.Deployment, buildTag string) (*buildSpec, error) { + // Figure out which tool binary will run inside the container. + toolVersion, toolIsDev, err := ToolVersion() + if err != nil { + return nil, err } - - // If we run the kube deployer in the development mode, we should copy the - // local kube binary to the image instead. - if runInDevMode && runtime.GOOS == "linux" && runtime.GOARCH == "amd64" { - // Use the running weaver-kube tool binary. + toCopy := []string{dep.App.Binary} + var toInstall []string + if runtime.GOOS == "linux" && runtime.GOARCH == "amd64" { + // The running tool binary can run inside the container: copy it. toolBinPath, err := os.Executable() if err != nil { return nil, err } - files = append(files, toolBinPath) - goInstall = []string{} + toCopy = append(toCopy, toolBinPath) + } else if toolIsDev { + // Devel tool binary that's not linux/amd64: prompt the user. + scanner := bufio.NewScanner(os.Stdin) + fmt.Print( + `The running weaver-kube binary hasn't been cross-compiled for linux/amd64 and +cannot run inside the container. Instead, the latest weaver-kube binary will be +downloaded and installed in the container. Do you want to proceed? [Y/n] `) + scanner.Scan() + text := scanner.Text() + if text != "" && text != "y" && text != "Y" { + return nil, fmt.Errorf("user bailed out") + } + toInstall = append(toInstall, "github.com/ServiceWeaver/weaver-kube/cmd/weaver-kube@latest") + } else { + // Released tool binary that's not compiled to linux/amd64. Re-install + // it inside the container. + toInstall = append(toInstall, "github.com/ServiceWeaver/weaver-kube/cmd/weaver-kube@"+toolVersion) + } + + if buildTag == "" { + buildTag = fmt.Sprintf("%s:%s", dep.App.Name, dep.Id[:8]) } return &buildSpec{ tag: buildTag, - files: files, - goInstall: goInstall, + files: toCopy, + goInstall: toInstall, }, nil } diff --git a/internal/impl/version.go b/internal/impl/version.go new file mode 100644 index 0000000..41ce928 --- /dev/null +++ b/internal/impl/version.go @@ -0,0 +1,18 @@ +package impl + +import ( + "fmt" + "runtime/debug" +) + +// ToolVersion returns the version of the running tool binary, along with +// an indication whether the tool was built manually, i.e., not via go install. +func ToolVersion() (string, bool, error) { + info, ok := debug.ReadBuildInfo() + if !ok { + // Should never happen. + return "", false, fmt.Errorf("tool binary must be built from a module") + } + dev := info.Main.Version == "(devel)" + return info.Main.Version, dev, nil +} diff --git a/internal/version/version.go b/internal/version/version.go deleted file mode 100644 index bbf0267..0000000 --- a/internal/version/version.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package version - -const ( - // weaver-kube module version (Major.Minor.Patch). - Major = 0 - Minor = 21 - Patch = 0 -)