Files
odo/cmd/root.go
Chris Laprun 2e91e59bff Factor out creation of contextual information (project, application, component) to make it easier to manage and facilitate refactoring of commands (#949)
* Use constants for flag names.

* Introduce Context struct and use it to replace util.GetComponent

* Remove redundant break statements.

* Do not exit when attempting to access a possibly not defined flag.

* Fix improper logic.

* Add ComponentAllowingEmpty to make it more useful and use it.

* Start removing usage of util.GetAppName

* Remove unneeded check for error (no error can occur there).

* Deprecate GetAppName in favor of Context.Application.
Will need to use Context in completion infrastructure as well but this
will be part of a later PR.

* Remove unneeded (and invalid) GetOrCreateAppName function.

* Deprecate GetAndSetNamespace and remove it where possible.
Can't currently touch the completion handlers.

* Make completion handlers use Context and allow
them to access the current command.
This allows removal of GetAppName and GetAndSetNamespace.

* Replace GetOcClient function by genericclioptions.Client and ClientWithConnectionCheck

* Remove now unneeded global variables and GetOcClient function.

* Fix improper check if component flag has been set.

* Polish and add comments.

* Update FileCompletionHandler.

* Fix formatting.

* Fix AppCompletionHandler.

* Rename existsOrExit to be more explicit.

* Change error code.

* Replace todo by TODO.
2018-11-13 16:51:11 +01:00

157 lines
5.6 KiB
Go

package cmd
import (
"flag"
"fmt"
"github.com/golang/glog"
"github.com/redhat-developer/odo/pkg/config"
"github.com/redhat-developer/odo/pkg/notify"
"github.com/redhat-developer/odo/pkg/odo/util"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
// Templates
var rootUsageTemplate = `Usage:{{if .Runnable}}
{{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
{{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
Aliases:
{{.NameAndAliases}}{{end}}{{if .HasExample}}
Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Component Commands:{{range .Commands}}{{if eq .Annotations.command "component"}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Other Commands:{{range .Commands}}{{if eq .Annotations.command "other"}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Utility Commands:{{range .Commands}}{{if or (eq .Annotations.command "utility") (eq .Name "help") }}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}
Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}
Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
var cmdUsageTemplate = `Usage:{{if .Runnable}}
{{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
{{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
Aliases:
{{.NameAndAliases}}{{end}}{{if .HasExample}}
Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}
Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}
Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: util.RootCommandName,
Short: "Odo (Openshift Do)",
Long: `Odo (OpenShift Do) is a CLI tool for running OpenShift applications in a fast and automated matter. Odo reduces the complexity of deployment by adding iterative development without the worry of deploying your source code.
Find more information at https://github.com/redhat-developer/odo`,
Example: ` # Creating and deploying a Node.js project
git clone https://github.com/openshift/nodejs-ex && cd nodejs-ex
odo create nodejs
odo push
# Accessing your Node.js component
odo url create`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
},
}
// RootCmd exposes the root command to main package to allow inspection by completion code
func RootCmd() *cobra.Command {
return rootCmd
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
// checking the value of updatenotification in config
// before proceeding with fetching the latest version
cfg, err := config.New()
if err != nil {
util.CheckError(err, "")
}
if cfg.GetUpdateNotification() == true {
updateInfo := make(chan string)
go getLatestReleaseInfo(updateInfo)
util.CheckError(rootCmd.Execute(), "")
select {
case message := <-updateInfo:
fmt.Println(message)
default:
glog.V(4).Info("Could not get the latest release information in time. Never mind, exiting gracefully :)")
}
} else {
util.CheckError(rootCmd.Execute(), "")
}
}
func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.odo.yaml)")
rootCmd.PersistentFlags().Bool(util.SkipConnectionCheckFlagName, false, "Skip cluster check")
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.CommandLine.Set("logtostderr", "true")
// Override the verbosity flag description
verbosity := pflag.Lookup("v")
verbosity.Usage += ". Level varies from 0 to 9 (default 0)."
rootCmd.SetUsageTemplate(rootUsageTemplate)
flag.CommandLine.Parse([]string{})
}
func getLatestReleaseInfo(info chan<- string) {
newTag, err := notify.CheckLatestReleaseTag(VERSION)
if err != nil {
// The error is intentionally not being handled because we don't want
// to stop the execution of the program because of this failure
glog.V(4).Infof("Error checking if newer odo release is available: %v", err)
}
if len(newTag) > 0 {
info <- "---\n" +
"A newer version of odo (version: " + fmt.Sprint(newTag) + ") is available.\n" +
"Update using your package manager, or run\n" +
"curl " + notify.InstallScriptURL + " | sh\n" +
"to update manually, or visit https://github.com/redhat-developer/odo/releases\n" +
"---\n" +
"If you wish to disable the update notifications, you can disable it by running\n" +
"'odo utils config set UpdateNotification false'\n"
}
}