This is technically the first post on my blog so I’m pretty excited to write this one 😄
For the last few months, I’ve been working on depstat, which is a command-line tool to analyze dependencies, as part of my CNCF Internship. I’ve had a blast working on this especially because of the welcoming community. depstat is going to be used to evaluate dependency updates to Kubernetes and has been written in Go so I thought about sharing some stuff I learned :D
The Tools
We’re going to use Cobra to create our CLI. If you want to create a CLI in Golang, trust me, Cobra is the way to GO. The fact that it is used in the Kubernetes codebase should be enough proof of its awesomeness.
The simplest way to get started with Cobra is using the Cobra Generator. You can simply run
go get github.com/spf13/cobra/cobra
to get the cobra binary in your $GOPATH/bin
directory.
Run cobra help
from your terminal to verify that it was installed correctly. A common error you might get is:
zsh: command not found: cobra
This might be happening because zsh is not picking up the cobra binary from $GOPATH/bin
. To fix that open your .zshrc
file and add the following line:
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
Note if you’re using bash instead of zsh you might need to edit the
.bash_profile
file instead
You should now be good to go!
For the sake of this tutorial, we’re going to create a very simple sound
CLI. This will take either “dog” or “cat” as an argument and print the sound they make as the result.
Pretty useless but extremely simple for learning the basics. So let’s get started!
Cobra Basics
We can start our cobra project using:
mkdir sound
cd sound
cobra init --pkg-name=sound
This will set up a cobra project for us. The two important things which this sets up for us are:
main.go
: There isn’t a lot going on in this file. All it does is call theexecute
method in thecmd
package.cmd/root.go
: For the sake of simplification replace the contents of yourroot.go
file with these:
package cmd
import (
"github.com/spf13/cobra"
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "sound",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
// Run: func(cmd *cobra.Command, args []string) { },
}
func Execute() {
cobra.CheckErr(rootCmd.Execute())
}
Now, this is much easier to explain :)
In Use
we specify the name of the command/sub-command. Currently, we only have our base command, sound
without any subcommands. The Short
and Long
fields are used by cobra to generate help
for our commands.
Let’s now try this out!
Running The CLI
Before installing, run go mod init sound
to initialize go modules for the project. Then run go mod tidy
to generate the go.sum
file. Once this is done simply run,
go install
to install your CLI.
To test it out, run
sound
and you should see the following output:
A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.
If you haven’t already noticed, this is the same text present by default in the Long
field. Currently, the base command does nothing so running it just prints the help for it. Let’s change this behavior now.
Adding Some Logic
We now want our command to take an argument from the user and then print something based on that. For that functionality, the code is pretty simple:
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "sound",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
log.Fatal("please provide a pet")
}
if args[0] == "dog" {
fmt.Println("wooooof!")
} else if args[0] == "cat" {
fmt.Println("meoooow!")
} else {
fmt.Println("sorry your pet is currently not supported :(")
}
},
}
What we have done should be pretty straightforward to understand. Basically, Cobra gives us access to anything the user entered after the command (or subcommand) in form of the args
slice. We can then check the animal type and print our result accordingly. Pretty simple! :)
To see each change you make take place in effect, you’ll have to run go install
again to update your binary. Do that and test out your sound CLI!
Well, that was it folks! I know there is a lot to cover when it comes to Cobra but I just wanted to show you how easy it is to create a simple command-line tool with it. If you’re interested in learning more about it, I highly recommend you go check out the official docs.