Skip to content

Commit

Permalink
Updates the help usage of odo (#2242)
Browse files Browse the repository at this point in the history
* Updates the help usage of odo

This PR:
  - Modifies the output of running JUST `odo` similar to how `oc` does
  it.
  - There is now a difference between running `odo` and running `odo
  --help`
  - Removes "Normalize" for the long description since it was messing up
  newline formatting
  - Adds integration tests for help usage

Closes #1672

Example of running JUST `odo`:

```sh
(OpenShift Do) odo is a CLI tool for running OpenShift applications in a fast and automated manner.
Reducing the complexity of deployment, odo adds iterative development without the worry of deploying your source code.

Find more information at https://github.com/openshift/odo

Get started by creating a new application:

 git clone https://github.com/openshift/nodejs-ex && cd nodejs-ex
 odo create nodejs
 odo push

Your nodejs application has now been deployed. odo has pushed the source code, built the application and deployed it on OpenShift.
You can now edit your code in real time and watch as odo automatically deploys your application.

 odo watch

To access your application, create a URL:

 odo url create myurl
 odo push

More information such as logs or what components you've deployed can be accessed with these commands:

 odo describe
 odo list
 odo log

To see a full list of commands, run 'odo --help'
```

* Update order
  • Loading branch information
cdrage authored and openshift-merge-robot committed Oct 5, 2019
1 parent f569be9 commit 7c2bea3
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 12 deletions.
62 changes: 56 additions & 6 deletions pkg/odo/cli/cli.go
Expand Up @@ -31,17 +31,20 @@ import (
const OdoRecommendedName = "odo"

var (
odoLong = ktemplates.LongDesc(`
(OpenShift Do) odo is a CLI tool for running OpenShift applications in a fast and automated manner. Reducing the complexity of deployment, odo adds iterative development without the worry of deploying your source code.
// We do not use ktemplates.Normalize here as it messed up the newlines..
odoLong = `(OpenShift Do) odo is a CLI tool for running OpenShift applications in a fast and automated manner.
Reducing the complexity of deployment, odo adds iterative development without the worry of deploying your source code.
Find more information at https://github.com/openshift/odo`

Find more information at https://github.com/openshift/odo`)
odoExample = ktemplates.Examples(` # Creating and deploying a Node.js project
git clone https://github.com/openshift/nodejs-ex && cd nodejs-ex
%[1]s create nodejs
%[1]s push
# Accessing your Node.js component
%[1]s url create`)

rootUsageTemplate = `Usage:{{if .Runnable}}
{{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
{{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
Expand All @@ -52,15 +55,15 @@ Aliases:
Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Shortcuts:{{range .Commands}}{{if eq .Annotations.command "component"}}
{{rpad .Name .NamePadding }} {{.Short}} (shortcut for "component {{.Name}}") {{end}}{{end}}{{end}}
Commands:{{range .Commands}}{{if eq .Annotations.command "main"}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}
Utility Commands:{{range .Commands}}{{if or (eq .Annotations.command "utility") (eq .Name "help") }}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Component Shortcuts:{{range .Commands}}{{if eq .Annotations.command "component"}}
{{rpad .Name .NamePadding }} {{.Short}} {{end}}{{end}}{{end}}
Flags:
{{CapitalizeFlagDescriptions .LocalFlags | trimRightSpace }}{{end}}{{ if .HasAvailableInheritedFlags}}
Expand All @@ -72,6 +75,32 @@ Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`

rootDefaultHelp = odoLong + `
Get started by creating a new application:
git clone https://github.com/openshift/nodejs-ex && cd nodejs-ex
odo create nodejs
odo push
Your nodejs application has now been deployed. odo has pushed the source code, built the application and deployed it on OpenShift.
You can now edit your code in real time and watch as odo automatically deploys your application.
odo watch
To access your application, create a URL:
odo url create myurl
odo push
More information such as logs or what components you've deployed can be accessed with these commands:
odo describe
odo list
odo log
To see a full list of commands, run 'odo --help'`
)

// NewCmdOdo creates a new root command for odo
Expand All @@ -81,6 +110,7 @@ func NewCmdOdo(name, fullName string) *cobra.Command {
Use: name,
Short: "odo (OpenShift Do)",
Long: odoLong,
RunE: ShowHelp,
Example: fmt.Sprintf(odoExample, fullName),
}
// Here you will define your flags and configuration settings.
Expand Down Expand Up @@ -179,3 +209,23 @@ func ShowSubcommands(cmd *cobra.Command, args []string) error {
}
return fmt.Errorf("Subcommand not found, use one of the available commands: %s", strings.Join(strs, ", "))
}

// ShowHelp will show the help correctly (and whether or not the command is invalid...)
// Taken from: https://github.com/cppforlife/knctl/blob/612840d3c9729b1c57b20ca0450acab0d6eceeeb/pkg/knctl/cmd/knctl.go#L71
func ShowHelp(cmd *cobra.Command, args []string) error {

if len(args) == 0 {

// We will show a custom help when typing JUST `odo`, directing the user to use `odo --help` for a full help.
// Thus we will set cmd.SilenceUsage and cmd.SilenceErrors both to true so we do not output the usage or error out.
cmd.SilenceUsage = true
cmd.SilenceErrors = true

// Print out the default "help" usage
fmt.Println(rootDefaultHelp)
return nil
}

cmd.Help()
return fmt.Errorf("Invalid command - see available commands/subcommands above")
}
2 changes: 1 addition & 1 deletion pkg/odo/cli/component/component.go
Expand Up @@ -58,7 +58,7 @@ func NewCmdComponent(name, fullName string) *cobra.Command {
// componentCmd represents the component command
var componentCmd = &cobra.Command{
Use: name,
Short: "Components of an application",
Short: "Manage components",
Example: fmt.Sprintf("%s\n%s\n\n See sub-commands individually for more examples",
fullName, CreateRecommendedCommandName),
// `odo component set/get` and `odo get/set` are respectively deprecated as per the new workflow
Expand Down
4 changes: 2 additions & 2 deletions pkg/odo/cli/component/delete.go
Expand Up @@ -120,8 +120,8 @@ func NewCmdDelete(name, fullName string) *cobra.Command {

var componentDeleteCmd = &cobra.Command{
Use: fmt.Sprintf("%s <component_name>", name),
Short: "Delete an existing component",
Long: "Delete an existing component.",
Short: "Delete component",
Long: "Delete component.",
Example: fmt.Sprintf(deleteExample, fullName),
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/odo/cli/component/describe.go
Expand Up @@ -89,8 +89,8 @@ func NewCmdDescribe(name, fullName string) *cobra.Command {

var describeCmd = &cobra.Command{
Use: fmt.Sprintf("%s [component_name]", name),
Short: "Describe the given component",
Long: `Describe the given component.`,
Short: "Describe component",
Long: `Describe component.`,
Example: fmt.Sprintf(describeExample, fullName),
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/odo/cli/config/config.go
Expand Up @@ -25,7 +25,7 @@ func NewCmdConfiguration(name, fullName string) *cobra.Command {
configurationUnsetCmd := NewCmdUnset(unsetCommandName, util.GetFullName(fullName, unsetCommandName))
configurationCmd := &cobra.Command{
Use: name,
Short: "Modifies configuration settings",
Short: "Change or view configuration",
Long: fmt.Sprintf(configLongDesc, config.FormatLocallySupportedParameters()),
Example: fmt.Sprintf("%s\n%s\n%s",
configurationViewCmd.Example,
Expand Down
19 changes: 19 additions & 0 deletions tests/integration/generic_test.go
Expand Up @@ -28,6 +28,25 @@ var _ = Describe("odo generic", func() {
SetDefaultConsistentlyDuration(30 * time.Second)
})

Context("Check the help usage for odo", func() {

It("Makes sure that we have the long-description when running odo and we dont error", func() {
output := helper.CmdShouldPass("odo")
Expect(output).To(ContainSubstring("To see a full list of commands, run 'odo --help'"))
})

It("Make sure we have the full description when performing odo --help", func() {
output := helper.CmdShouldPass("odo", "--help")
Expect(output).To(ContainSubstring("Use \"odo [command] --help\" for more information about a command."))
})

It("Fail when entering an incorrect name for a component", func() {
output := helper.CmdShouldFail("odo", "component", "foobar")
Expect(output).To(ContainSubstring("Subcommand not found, use one of the available commands"))
})

})

Context("When executing catalog list without component directory", func() {
It("should list all component catalogs", func() {
stdOut := helper.CmdShouldPass("odo", "catalog", "list", "components")
Expand Down

0 comments on commit 7c2bea3

Please sign in to comment.