From d76ed7b49e67ff390e525b6e531df73843bacbc0 Mon Sep 17 00:00:00 2001 From: Justin Nauman Date: Wed, 6 Sep 2017 23:10:31 -0500 Subject: [PATCH 1/2] Adding in customized user-agent Signed-off-by: Justin Nauman --- pkg/client/client.go | 21 ++++++++++++++++++++- pkg/client/factory.go | 8 +++++--- pkg/cmd/ark/ark.go | 4 ++-- pkg/cmd/server/server.go | 8 ++++---- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index 7e76da1ee..7db58b3ff 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -17,18 +17,37 @@ limitations under the License. package client import ( + "fmt" + "runtime" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + + "github.com/heptio/ark/pkg/buildinfo" ) // Config returns a *rest.Config, using either the kubeconfig (if specified) or an in-cluster // configuration. -func Config(kubeconfig string) (*rest.Config, error) { +func Config(kubeconfig, baseName string) (*rest.Config, error) { loader := clientcmd.NewDefaultClientConfigLoadingRules() loader.ExplicitPath = kubeconfig clientConfig, err := clientcmd.BuildConfigFromKubeconfigGetter("", loader.Load) if err != nil { return nil, err } + + clientConfig.UserAgent = buildUserAgent( + baseName, + buildinfo.Version, + runtime.GOOS, + runtime.GOARCH, + buildinfo.GitSHA) + return clientConfig, nil } + +// buildUserAgent builds a User-Agent string from given args. +func buildUserAgent(command, version, os, arch, commit string) string { + return fmt.Sprintf( + "%s/%s (%s/%s) %s", command, version, os, arch, commit) +} diff --git a/pkg/client/factory.go b/pkg/client/factory.go index c52297248..a84a2b866 100644 --- a/pkg/client/factory.go +++ b/pkg/client/factory.go @@ -34,12 +34,14 @@ type Factory interface { type factory struct { flags *pflag.FlagSet kubeconfig string + baseName string } // NewFactory returns a Factory. -func NewFactory() Factory { +func NewFactory(baseName string) Factory { f := &factory{ - flags: pflag.NewFlagSet("", pflag.ContinueOnError), + flags: pflag.NewFlagSet("", pflag.ContinueOnError), + baseName: baseName, } f.flags.StringVar(&f.kubeconfig, "kubeconfig", "", "Path to the kubeconfig file to use to talk to the Kubernetes apiserver. If unset, try the environment variable KUBECONFIG, as well as in-cluster configuration") @@ -51,7 +53,7 @@ func (f *factory) BindFlags(flags *pflag.FlagSet) { } func (f *factory) Client() (clientset.Interface, error) { - clientConfig, err := Config(f.kubeconfig) + clientConfig, err := Config(f.kubeconfig, f.baseName) if err != nil { return nil, err } diff --git a/pkg/cmd/ark/ark.go b/pkg/cmd/ark/ark.go index 2580cd821..e99c18014 100644 --- a/pkg/cmd/ark/ark.go +++ b/pkg/cmd/ark/ark.go @@ -39,14 +39,14 @@ and operationally robust way to back up your application state and associated data.`, } - f := client.NewFactory() + f := client.NewFactory(name) f.BindFlags(c.PersistentFlags()) c.AddCommand( backup.NewCommand(f), schedule.NewCommand(f), restore.NewCommand(f), - server.NewCommand(), + server.NewCommand(name), version.NewCommand(), ) diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index 78c34402e..4a742e982 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -57,7 +57,7 @@ import ( "github.com/heptio/ark/pkg/util/kube" ) -func NewCommand() *cobra.Command { +func NewCommand(baseName string) *cobra.Command { var kubeconfig string var command = &cobra.Command{ @@ -65,7 +65,7 @@ func NewCommand() *cobra.Command { Short: "Run the ark server", Long: "Run the ark server", Run: func(c *cobra.Command, args []string) { - s, err := newServer(kubeconfig) + s, err := newServer(kubeconfig, baseName+"-server") cmd.CheckError(err) cmd.CheckError(s.run()) @@ -89,8 +89,8 @@ type server struct { cancelFunc context.CancelFunc } -func newServer(kubeconfig string) (*server, error) { - clientConfig, err := client.Config(kubeconfig) +func newServer(kubeconfig, baseName string) (*server, error) { + clientConfig, err := client.Config(kubeconfig, baseName) if err != nil { return nil, err } From 97f8f2426f9a24014dce39df66083394895e81d7 Mon Sep 17 00:00:00 2001 From: Justin Nauman Date: Mon, 18 Sep 2017 17:30:12 -0500 Subject: [PATCH 2/2] Addressing PR feedback and adding tests Signed-off-by: Justin Nauman --- pkg/buildinfo/version.go | 10 +++++++++ pkg/buildinfo/version_test.go | 38 +++++++++++++++++++++++++++++++++++ pkg/client/client.go | 7 ++++--- pkg/client/client_test.go | 36 +++++++++++++++++++++++++++++++++ pkg/cmd/ark/ark.go | 2 +- pkg/cmd/server/server.go | 4 ++-- 6 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 pkg/buildinfo/version_test.go create mode 100644 pkg/client/client_test.go diff --git a/pkg/buildinfo/version.go b/pkg/buildinfo/version.go index e23470db0..1c1c2e9cb 100644 --- a/pkg/buildinfo/version.go +++ b/pkg/buildinfo/version.go @@ -19,6 +19,8 @@ limitations under the License. // worrying about introducing circular dependencies. package buildinfo +import "fmt" + var ( // Version is the current version of Ark, set by the go linker's -X flag at build time. Version string @@ -34,3 +36,11 @@ var ( // time. GitTreeState string ) + +// FormattedGitSHA renders the Git SHA with an indicator of the tree state. +func FormattedGitSHA() string { + if GitTreeState != "clean" { + return fmt.Sprintf("%s-%s", GitSHA, GitTreeState) + } + return GitSHA +} diff --git a/pkg/buildinfo/version_test.go b/pkg/buildinfo/version_test.go new file mode 100644 index 000000000..5f4479991 --- /dev/null +++ b/pkg/buildinfo/version_test.go @@ -0,0 +1,38 @@ +package buildinfo + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFormattedGitSHA(t *testing.T) { + tests := []struct { + name string + sha string + state string + expected string + }{ + { + "Clean git state has no suffix", + "abc123", + "clean", + "abc123", + }, + { + "Dirty git status includes suffix", + "abc123", + "dirty", + "abc123-dirty", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + GitSHA = test.sha + GitTreeState = test.state + assert.Equal(t, FormattedGitSHA(), test.expected) + }) + } + +} diff --git a/pkg/client/client.go b/pkg/client/client.go index 7db58b3ff..10a363205 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -39,15 +39,16 @@ func Config(kubeconfig, baseName string) (*rest.Config, error) { clientConfig.UserAgent = buildUserAgent( baseName, buildinfo.Version, + buildinfo.FormattedGitSHA(), runtime.GOOS, runtime.GOARCH, - buildinfo.GitSHA) + ) return clientConfig, nil } // buildUserAgent builds a User-Agent string from given args. -func buildUserAgent(command, version, os, arch, commit string) string { +func buildUserAgent(command, version, formattedSha, os, arch string) string { return fmt.Sprintf( - "%s/%s (%s/%s) %s", command, version, os, arch, commit) + "%s/%s (%s/%s) %s", command, version, os, arch, formattedSha) } diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go new file mode 100644 index 000000000..4ab5107d0 --- /dev/null +++ b/pkg/client/client_test.go @@ -0,0 +1,36 @@ +package client + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBuildUserAgent(t *testing.T) { + tests := []struct { + name string + command string + os string + arch string + gitSha string + version string + expected string + }{ + { + name: "Test general interpolation in correct order", + command: "ark", + os: "darwin", + arch: "amd64", + gitSha: "abc123", + version: "v0.1.1", + expected: "ark/v0.1.1 (darwin/amd64) abc123", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + resp := buildUserAgent(test.command, test.version, test.gitSha, test.os, test.arch) + assert.Equal(t, resp, test.expected) + }) + } +} diff --git a/pkg/cmd/ark/ark.go b/pkg/cmd/ark/ark.go index e99c18014..26a7e0707 100644 --- a/pkg/cmd/ark/ark.go +++ b/pkg/cmd/ark/ark.go @@ -46,7 +46,7 @@ associated data.`, backup.NewCommand(f), schedule.NewCommand(f), restore.NewCommand(f), - server.NewCommand(name), + server.NewCommand(), version.NewCommand(), ) diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index 4a742e982..fb3326e80 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -57,7 +57,7 @@ import ( "github.com/heptio/ark/pkg/util/kube" ) -func NewCommand(baseName string) *cobra.Command { +func NewCommand() *cobra.Command { var kubeconfig string var command = &cobra.Command{ @@ -65,7 +65,7 @@ func NewCommand(baseName string) *cobra.Command { Short: "Run the ark server", Long: "Run the ark server", Run: func(c *cobra.Command, args []string) { - s, err := newServer(kubeconfig, baseName+"-server") + s, err := newServer(kubeconfig, fmt.Sprintf("%s-%s", c.Parent().Name(), c.Name())) cmd.CheckError(err) cmd.CheckError(s.run())