Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v10] Provide flag to only display tsh binary version #22169

Merged
merged 4 commits into from
Feb 24, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 32 additions & 17 deletions tool/tsh/tsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,9 @@ type CLIConf struct {
// parallel.
// It shouldn't be used outside testing.
kubeConfigPath string

// Client only version display. Skips checking proxy version.
clientOnlyVersionCheck bool
}

// Stdout returns the stdout writer.
Expand Down Expand Up @@ -584,8 +587,10 @@ func Run(ctx context.Context, args []string, opts ...cliOption) error {
EnumVar(&cf.MFAMode, modes...)
app.HelpFlag.Short('h')

ver := app.Command("version", "Print the version of your tsh binary")
ver := app.Command("version", "Print the tsh client and Proxy server versions for the current context.")
ver.Flag("format", defaults.FormatFlagDescription(defaults.DefaultFormats...)).Short('f').Default(teleport.Text).EnumVar(&cf.Format, defaults.DefaultFormats...)
ver.Flag("client", "Show the client version only (no server required).").
BoolVar(&cf.clientOnlyVersionCheck)
// ssh
// Use Interspersed(false) to forward all flags to ssh.
ssh := app.Command("ssh", "Run shell or execute a command on a remote SSH node").Interspersed(false)
Expand Down Expand Up @@ -1186,9 +1191,16 @@ func newTraceProvider(cf *CLIConf, command string, ignored []string) (*tracing.P

// onVersion prints version info.
func onVersion(cf *CLIConf) error {
proxyVersion, err := fetchProxyVersion(cf)
if err != nil {
fmt.Fprintf(cf.Stderr(), "Failed to fetch proxy version: %s\n", err)
proxyVersion := ""
proxyPublicAddr := ""
// Check proxy version if not in client only mode
if !cf.clientOnlyVersionCheck {
pv, ppa, err := fetchProxyVersion(cf)
if err != nil {
fmt.Fprintf(cf.Stderr(), "Failed to fetch proxy version: %s\n", err)
}
proxyVersion = pv
proxyPublicAddr = ppa
}

format := strings.ToLower(cf.Format)
Expand All @@ -1197,9 +1209,10 @@ func onVersion(cf *CLIConf) error {
utils.PrintVersion()
if proxyVersion != "" {
fmt.Printf("Proxy version: %s\n", proxyVersion)
fmt.Printf("Proxy: %s\n", proxyPublicAddr)
}
case teleport.JSON, teleport.YAML:
out, err := serializeVersion(format, proxyVersion)
out, err := serializeVersion(format, proxyVersion, proxyPublicAddr)
if err != nil {
return trace.Wrap(err)
}
Expand All @@ -1212,45 +1225,47 @@ func onVersion(cf *CLIConf) error {
}

// fetchProxyVersion returns the current version of the Teleport Proxy.
func fetchProxyVersion(cf *CLIConf) (string, error) {
func fetchProxyVersion(cf *CLIConf) (string, string, error) {
profile, _, err := client.Status(cf.HomePath, cf.Proxy)
if err != nil {
if trace.IsNotFound(err) {
return "", nil
return "", "", nil
}
return "", trace.Wrap(err)
return "", "", trace.Wrap(err)
}

if profile == nil {
return "", nil
return "", "", nil
}

tc, err := makeClient(cf, false)
if err != nil {
return "", trace.Wrap(err)
return "", "", trace.Wrap(err)
}

ctx, cancel := context.WithTimeout(cf.Context, time.Second*5)
defer cancel()
pingRes, err := tc.Ping(ctx)
if err != nil {
return "", trace.Wrap(err)
return "", "", trace.Wrap(err)
}

return pingRes.ServerVersion, nil
return pingRes.ServerVersion, pingRes.Proxy.SSH.PublicAddr, nil
}

func serializeVersion(format string, proxyVersion string) (string, error) {
func serializeVersion(format string, proxyVersion string, proxyPublicAddress string) (string, error) {
versionInfo := struct {
Version string `json:"version"`
Gitref string `json:"gitref"`
Runtime string `json:"runtime"`
ProxyVersion string `json:"proxyVersion,omitempty"`
Version string `json:"version"`
Gitref string `json:"gitref"`
Runtime string `json:"runtime"`
ProxyVersion string `json:"proxyVersion,omitempty"`
ProxyPublicAddress string `json:"proxyPublicAddress,omitempty"`
}{
teleport.Version,
teleport.Gitref,
runtime.Version(),
proxyVersion,
proxyPublicAddress,
}
var out []byte
var err error
Expand Down
14 changes: 8 additions & 6 deletions tool/tsh/tsh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2484,7 +2484,8 @@ func TestSerializeVersion(t *testing.T) {
name string
expected string

proxyVersion string
proxyVersion string
proxyPublicAddress string
}{
{
name: "no proxy version provided",
Expand All @@ -2494,18 +2495,19 @@ func TestSerializeVersion(t *testing.T) {
),
},
{
name: "proxy version provided",
proxyVersion: "1.33.7",
name: "proxy version provided",
proxyVersion: "1.33.7",
proxyPublicAddress: "teleport.example.com:443",
expected: fmt.Sprintf(
`{"version": %q, "gitref": %q, "runtime": %q, "proxyVersion": %q}`,
teleport.Version, teleport.Gitref, runtime.Version(), "1.33.7"),
`{"version": %q, "gitref": %q, "runtime": %q, "proxyVersion": %q, "proxyPublicAddress": %q}`,
teleport.Version, teleport.Gitref, runtime.Version(), "1.33.7", "teleport.example.com:443"),
},
}

for _, tC := range testCases {
t.Run(tC.name, func(t *testing.T) {
testSerialization(t, tC.expected, func(fmt string) (string, error) {
return serializeVersion(fmt, tC.proxyVersion)
return serializeVersion(fmt, tC.proxyVersion, tC.proxyPublicAddress)
})
})
}
Expand Down