diff --git a/Makefile b/Makefile index b7b3246d..9b8c8fbc 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,41 @@ IMG ?= controller:latest export GO111MODULE=on export GOPROXY=https://proxy.golang.org +SHELL := /bin/bash -o pipefail +VERSION_PACKAGE = github.com/replicatedhq/troubleshoot/pkg/version +VERSION ?=`git describe --tags --dirty` +DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` + +GIT_TREE = $(shell git rev-parse --is-inside-work-tree 2>/dev/null) +ifneq "$(GIT_TREE)" "" +define GIT_UPDATE_INDEX_CMD +git update-index --assume-unchanged +endef +define GIT_SHA +`git rev-parse HEAD` +endef +else +define GIT_UPDATE_INDEX_CMD +echo "Not a git repo, skipping git update-index" +endef +define GIT_SHA +"" +endef +endif + +define LDFLAGS +-ldflags "\ + -X ${VERSION_PACKAGE}.version=${VERSION} \ + -X ${VERSION_PACKAGE}.gitSHA=${GIT_SHA} \ + -X ${VERSION_PACKAGE}.buildTime=${DATE} \ +" +endef + all: test manager .PHONY: ffi ffi: fmt vet - go build -o bin/troubleshoot.so -buildmode=c-shared ffi/main.go + go build ${LDFLAGS} -o bin/troubleshoot.so -buildmode=c-shared ffi/main.go # Run tests test: generate fmt vet manifests @@ -16,19 +46,19 @@ test: generate fmt vet manifests .PHONY: manager manager: generate fmt vet - go build -o bin/manager github.com/replicatedhq/troubleshoot/cmd/manager + go build ${LDFLAGS} -o bin/manager github.com/replicatedhq/troubleshoot/cmd/manager .PHONY: support-bundle support-bundle: generate fmt vet - go build -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot + go build ${LDFLAGS} -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot .PHONY: preflight preflight: generate fmt vet - go build -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight + go build ${LDFLAGS} -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight .PHONY: analyze analyze: generate fmt vet - go build -o bin/analyze github.com/replicatedhq/troubleshoot/cmd/analyze + go build ${LDFLAGS} -o bin/analyze github.com/replicatedhq/troubleshoot/cmd/analyze .PHONY: run run: generate fmt vet diff --git a/cmd/preflight/cli/root.go b/cmd/preflight/cli/root.go index caf1a5e2..79730408 100644 --- a/cmd/preflight/cli/root.go +++ b/cmd/preflight/cli/root.go @@ -18,6 +18,7 @@ var ( func RootCmd() *cobra.Command { cmd := &cobra.Command{ Use: "preflight [url]", + Args: cobra.MinimumNArgs(1), Short: "Run and retrieve preflight checks in a cluster", Long: `A preflight check is a set of validations that can and should be run to ensure that a cluster meets the requirements to run an application.`, @@ -37,6 +38,8 @@ that a cluster meets the requirements to run an application.`, cobra.OnInitialize(initConfig) + cmd.AddCommand(VersionCmd()) + cmd.Flags().Bool("interactive", true, "interactive preflights") cmd.Flags().String("format", "human", "output format, one of human, json, yaml. only used when interactive is set to false") cmd.Flags().String("preflight", "", "name of the preflight to use") diff --git a/cmd/preflight/cli/version.go b/cmd/preflight/cli/version.go new file mode 100644 index 00000000..3793847a --- /dev/null +++ b/cmd/preflight/cli/version.go @@ -0,0 +1,23 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/replicatedhq/troubleshoot/pkg/version" +) + +func VersionCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "version", + Short: "Print the current version and exit", + Long: `Print the current version and exit`, + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Printf("Replicated Preflight %s\n", version.Version()) + + return nil + }, + } + return cmd +} diff --git a/cmd/troubleshoot/cli/root.go b/cmd/troubleshoot/cli/root.go index fe7fae46..140b72ac 100644 --- a/cmd/troubleshoot/cli/root.go +++ b/cmd/troubleshoot/cli/root.go @@ -42,6 +42,7 @@ from a server that can be used to assist when troubleshooting a server.`, cobra.OnInitialize(initConfig) cmd.AddCommand(Analyze()) + cmd.AddCommand(VersionCmd()) cmd.Flags().String("collectors", "", "name of the collectors to use") cmd.Flags().String("image", "", "the full name of the collector image to use") diff --git a/cmd/troubleshoot/cli/version.go b/cmd/troubleshoot/cli/version.go index 3a029755..8e793230 100644 --- a/cmd/troubleshoot/cli/version.go +++ b/cmd/troubleshoot/cli/version.go @@ -1,12 +1,31 @@ package cli import ( - troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" - "gopkg.in/yaml.v2" + "fmt" + "io/ioutil" "path/filepath" + + troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" + "github.com/replicatedhq/troubleshoot/pkg/version" + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" ) +func VersionCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "version", + Short: "Print the current version and exit", + Long: `Print the current version and exit`, + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Printf("Replicated Preflight %s\n", version.Version()) + + return nil + }, + } + return cmd +} + const VersionFilename = "version.yaml" func writeVersionFile(path string) error { diff --git a/pkg/version/build.go b/pkg/version/build.go new file mode 100644 index 00000000..a79e72b1 --- /dev/null +++ b/pkg/version/build.go @@ -0,0 +1,7 @@ +package version + +// NOTE: these variables are injected at build time + +var ( + version, gitSHA, buildTime string +) diff --git a/pkg/version/run.go b/pkg/version/run.go new file mode 100644 index 00000000..b6a51474 --- /dev/null +++ b/pkg/version/run.go @@ -0,0 +1,12 @@ +package version + +import ( + "time" +) + +var RunAt time.Time + +func init() { + RunAt = time.Now().UTC() + initBuild() +} diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 00000000..1936f6fc --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,72 @@ +package version + +import ( + "runtime" + "time" +) + +var ( + build Build +) + +// Build holds details about this build of the binary +type Build struct { + Version string `json:"version,omitempty"` + GitSHA string `json:"git,omitempty"` + BuildTime time.Time `json:"buildTime,omitempty"` + TimeFallback string `json:"buildTimeFallback,omitempty"` + GoInfo GoInfo `json:"go,omitempty"` + RunAt *time.Time `json:"runAt,omitempty"` +} + +type GoInfo struct { + Version string `json:"version,omitempty"` + Compiler string `json:"compiler,omitempty"` + OS string `json:"os,omitempty"` + Arch string `json:"arch,omitempty"` +} + +// initBuild sets up the version info from build args +func initBuild() { + build.Version = version + if len(gitSHA) >= 7 { + build.GitSHA = gitSHA[:7] + } + var err error + build.BuildTime, err = time.Parse(time.RFC3339, buildTime) + if err != nil { + build.TimeFallback = buildTime + } + + build.GoInfo = getGoInfo() + build.RunAt = &RunAt +} + +// GetBuild gets the build +func GetBuild() Build { + return build +} + +// Version gets the version +func Version() string { + return build.Version +} + +// GitSHA gets the gitsha +func GitSHA() string { + return build.GitSHA +} + +// BuildTime gets the build time +func BuildTime() time.Time { + return build.BuildTime +} + +func getGoInfo() GoInfo { + return GoInfo{ + Version: runtime.Version(), + Compiler: runtime.Compiler, + OS: runtime.GOOS, + Arch: runtime.GOARCH, + } +}