Commit fd619b04 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #48572 from alexandercampbell/kubectl-follow-options-pattern-in-version

Automatic merge from submit-queue cmd/version: refactor to use the -Options pattern Refactor `kubectl version` to use the prescribed pattern in [kubectl-conventions.md](https://github.com/kubernetes/community/blob/49d65710b3ef8f4326df79706daf1e59c2e4a465/contributors/devel/kubectl-conventions.md#command-implementation-conventions). ```release-note NONE ``` /assign @mengqiy
parents 9e97b524 43c83d47
...@@ -37,6 +37,14 @@ type Version struct { ...@@ -37,6 +37,14 @@ type Version struct {
ServerVersion *apimachineryversion.Info `json:"serverVersion,omitempty" yaml:"serverVersion,omitempty"` ServerVersion *apimachineryversion.Info `json:"serverVersion,omitempty" yaml:"serverVersion,omitempty"`
} }
// VersionOptions: describe the options available to users of the "kubectl
// version" command.
type VersionOptions struct {
clientOnly bool
short bool
output string
}
var ( var (
versionExample = templates.Examples(i18n.T(` versionExample = templates.Examples(i18n.T(`
# Print the client and server versions for the current context # Print the client and server versions for the current context
...@@ -50,73 +58,90 @@ func NewCmdVersion(f cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -50,73 +58,90 @@ func NewCmdVersion(f cmdutil.Factory, out io.Writer) *cobra.Command {
Long: "Print the client and server version information for the current context", Long: "Print the client and server version information for the current context",
Example: versionExample, Example: versionExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := RunVersion(f, out, cmd) options := new(VersionOptions)
cmdutil.CheckErr(err) cmdutil.CheckErr(options.Complete(cmd))
cmdutil.CheckErr(options.Validate())
cmdutil.CheckErr(options.Run(f, out))
}, },
} }
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).") cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
cmd.Flags().BoolP("short", "", false, "Print just the version number.") cmd.Flags().BoolP("short", "", false, "Print just the version number.")
cmd.Flags().String("output", "", "output format, options available are yaml and json") cmd.Flags().String("output", "", "one of 'yaml' or 'json'")
cmd.Flags().MarkShorthandDeprecated("client", "please use --client instead.") cmd.Flags().MarkShorthandDeprecated("client", "please use --client instead.")
return cmd return cmd
} }
func RunVersion(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { func retrieveServerVersion(f cmdutil.Factory) (*apimachineryversion.Info, error) {
var serverVersion *apimachineryversion.Info = nil discoveryClient, err := f.DiscoveryClient()
var serverErr error = nil if err != nil {
vo := Version{nil, nil} return nil, err
}
// Always request fresh data from the server
discoveryClient.Invalidate()
return discoveryClient.ServerVersion()
}
func (o *VersionOptions) Run(f cmdutil.Factory, out io.Writer) error {
var (
serverVersion *apimachineryversion.Info
serverErr error
versionInfo Version
)
clientVersion := version.Get() clientVersion := version.Get()
vo.ClientVersion = &clientVersion versionInfo.ClientVersion = &clientVersion
if !cmdutil.GetFlagBool(cmd, "client") { if !o.clientOnly {
serverVersion, serverErr = retrieveServerVersion(f) serverVersion, serverErr = retrieveServerVersion(f)
vo.ServerVersion = serverVersion versionInfo.ServerVersion = serverVersion
} }
switch of := cmdutil.GetFlagString(cmd, "output"); of { switch o.output {
case "": case "":
if cmdutil.GetFlagBool(cmd, "short") { if o.short {
fmt.Fprintf(out, "Client Version: %s\n", clientVersion.GitVersion) fmt.Fprintf(out, "Client Version: %s\n", clientVersion.GitVersion)
if serverVersion != nil { if serverVersion != nil {
fmt.Fprintf(out, "Server Version: %s\n", serverVersion.GitVersion) fmt.Fprintf(out, "Server Version: %s\n", serverVersion.GitVersion)
} }
} else { } else {
fmt.Fprintf(out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion)) fmt.Fprintf(out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion))
if serverVersion != nil { if serverVersion != nil {
fmt.Fprintf(out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion)) fmt.Fprintf(out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion))
} }
} }
case "yaml": case "yaml":
y, err := yaml.Marshal(&vo) marshalled, err := yaml.Marshal(&versionInfo)
if err != nil { if err != nil {
return err return err
} }
fmt.Fprintln(out, string(marshalled))
fmt.Fprintln(out, string(y))
case "json": case "json":
y, err := json.Marshal(&vo) marshalled, err := json.Marshal(&versionInfo)
if err != nil { if err != nil {
return err return err
} }
fmt.Fprintln(out, string(y)) fmt.Fprintln(out, string(marshalled))
default: default:
return errors.New("invalid output format: " + of) // There is a bug in the program if we hit this case.
// However, we follow a policy of never panicking.
return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.output)
} }
return serverErr return serverErr
} }
func retrieveServerVersion(f cmdutil.Factory) (*apimachineryversion.Info, error) { func (o *VersionOptions) Complete(cmd *cobra.Command) error {
discoveryClient, err := f.DiscoveryClient() o.clientOnly = cmdutil.GetFlagBool(cmd, "client")
if err != nil { o.short = cmdutil.GetFlagBool(cmd, "short")
return nil, err o.output = cmdutil.GetFlagString(cmd, "output")
return nil
}
func (o *VersionOptions) Validate() error {
if o.output != "" && o.output != "yaml" && o.output != "json" {
return errors.New(`--output must be 'yaml' or 'json'`)
} }
// Always request fresh data from the server return nil
discoveryClient.Invalidate()
return discoveryClient.ServerVersion()
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment