Define Cobra library and make an application from it

Define Cobra library and make an application from it

Build an application without caring about the frontend

ยท

6 min read

Cobra is a CLI framework for Go. It is a powerful library and tool in Golang used to create CLI (Command-Line Interface) applications. Cobra does this by providing tools that automate the process and provide key abstractions that increase developer productivity.

It is used in many Go projects such as Kubernetes, Hugo, and GitHub CLI and much more. This list contains a more extensive list of projects using Cobra.

Why use Cobraโ“

Among the many benefits of using Cobra, here are some to consider:

  • Easy to create subcommand-based CLIs and use nested subcommands.
  • Automatic help generation for commands and flags.
  • Increased productivity because of commands such as cobra init appname & cobra add cmdname.
  • Helpful, intelligent suggestions (app srverโ€ฆ did you mean app server?).

The Pattern ๐Ÿ“

Cobra is built on a structure of commands, arguments & flags.

  • Commands represent the actions.
  • Args are the things.
  • Flags are the modifiers for those actions.

The basic structure will be like a simple sentence.

The pattern to follow is APPNAME Command Args --Flags or APPNAME Command --Flags Args

Examples:

  • git clone URL -bare
  • go get -u URL
  • npm install package --save
  • docker run image -d

In the following example, 'hugo' is a root command, 'server' is a command, and 'port' is a flag:

hugo server --port=1313

Similarly in one of the above examples, 'go' is a root command, 'get' is a command, '-u' is a flag and the 'URL' is an argument.

go get -u URL

Commands

A command is the central point of the application. Each interaction that the application supports will be contained in a Command. A command can have children's commands and optionally run an action.

In the example above, 'server' and 'get' are the commands.

Flags

A flag is a way to modify the behavior of a command. A Cobra command can define flags that persist through to children's commands and flags that are only available to that command.

In the example above, 'port' and '-u' are the flags.

Usage ๐Ÿซ 

First, create a directory in your GOPATH by the name of example, and inside it run the below command to initialize the modules.

go mod init example

You will notice that it created a go.mod file in the project.

Installation

Using Cobra is easy. Before going any further, first, use go get to install the latest version of the library.

go get -u github.com/spf13/cobra@latest

Once the module is created and the cobra is installed, write the following command.

cobra init

File structure

After running the above command, it will create a cmd directory, License, and the main.go file. Following is the file structure.

Screenshot from 2022-09-02 15-14-44.png

main.go

Here is the data inside main.go file that is created by default after initializing the cobra.

package main

import "github.com/ibilalkayy/example/cmd"

func main() {
    cmd.Execute()
}

root.go

Here is the data inside the root.go file

package cmd

import (
    "os"
    "github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
    Use:   "example",
    Short: "A brief description of your application",
    Long: `A brief description of your application.`,
}

func Execute() {
    err := rootCmd.Execute()
    if err != nil {
        os.Exit(1)
    }
}

func init() {
    rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
  • rootCmd represents the base command when called without any subcommand. It contains the root command example, a short description, and the long description.

  • Execute() adds all child commands to the root command and sets flags appropriately. It only needs to happen once to the rootCmd.

  • Init() will define your flags and configuration settings.

Running the command

  • Type go build to create a test file inside the test directory.

  • Type go install to access the GOPATH so that it runs the application.

  • Type example to see the result of the application. You will see that the long description is printed out.

Add sub-commands to a project ๐ŸŠ

  • Once a cobra application is initialized you can continue to use the Cobra generator to add additional commands to your application.

  • The command to do this is cobra add [any-name].

  • By writing the above command, a file will be created inside the cmd directory by the name that you have given.

  • In my case, I have given the name first and created another file also that is called second. The creation is the same as given above and the file contains the following code by default.

first.go

package cmd

import (
    "fmt"
    "github.com/spf13/cobra"
)

var firstCmd = &cobra.Command{
    Use:   "first",
    Short: "A brief description of your command",
    Long: `A longer description of your command`,
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("first called")
    },
}

func init() {
    rootCmd.AddCommand(firstCmd)
}
  • firstCmd represents the first command. It contains the sub-command that is called first, short and long description.

  • init() will define your flags and configuration settings.

  • Type go install to access the GOPATH again with this updated command so that it runs the application.

Result

After executing the go install, type example --help in the command prompt, and you will see the following result in which all the sub-commands are generated.

Screenshot from 2022-09-02 15-57-33.png

After the creation of the sub-commands, if you type

example first

OR

example second

you will see the relevant result like first called and second called. The result is printed out in each file. You can check them out.

Add flags ๐Ÿšฉ

  • Here I will just add a flag to the first file. The second one is your homework.

  • In this first file, there are two players. Each of them will be given an order by showing them a flag. If the flag is correct then they will perform a functionality otherwise there will be an error message.

Below is the updated code in the first.go file.

first.go

package cmd

import (
    "fmt"
    "github.com/spf13/cobra"
)

var Run, Cook string

var firstCmd = &cobra.Command{
    Use:   "first",
    Short: "A brief description of your command",
    Long: `A longer description of you command`,
    Run: func(cmd *cobra.Command, args []string) {
        var option [2]string

        option[0], _ = cmd.Flags().GetString("run")
        option[1], _ = cmd.Flags().GetString("cook")

        if option[0] == "run" {
            fmt.Println("The player started running")
        } else if option[1] == "cook" {
            fmt.Println("The cook started cooking")
        } else {
            fmt.Println("No participants got an order. Try again!!")
        }
    },
}

func init() {
    rootCmd.AddCommand(firstCmd)
    firstCmd.PersistentFlags().StringVarP(&Run, "run", "r", "", "It is an order to a player to run")
    firstCmd.PersistentFlags().StringVarP(&Cook, "cook", "c", "", "It is an order to a cook to cook")
}
  • In the init() function, two flags are added. The first one is the run and the second one is the cook. Each of them has a description with -r and -c flags.

  • Run and Cook are the variables that are defined above.

  • Inside a function, an array is defined by the name of the option.

  • cmd.Flags().GetString() will get the string values of the flags that are written below in the init() function.

  • If the first option is equal to run, then the player will start running. If the second option is equal to cook, then the cook will start cooking. Otherwise, there will be a message that No participants got an order. Try again!!

  • Now let's run the go install in the command prompt again.

  • After that, type example first -r run. You will see that the player started running. Similarly type example first -c cook. Now the cook started cooking. If you typed something else instead of run or cook, you will get an else message.

That's it.

Follow me on Hashnode, Twitter, and LinkedIn.

Thank you.

ย