Skip to content
This repository has been archived by the owner on Mar 31, 2023. It is now read-only.

Use with spf13 cobra

Yamamoto, Hirotaka edited this page Oct 22, 2018 · 2 revisions

Cobra together with pflag and viper is a toolkit to create command-line tools with sub-commands and flags very easily.

Since cobra does not cover contexts, signals, and logging, using cobra with well is a perfect combination to build great tools.

One thing that need to be resolved is how to configure logging. Well adds command-line flags to configure the default logger using the standard flag package. Well already has a built-in support for cobra/pflag/viper as described below.

A brief introduction to cobra/pflag/viper

Cobra is a library to build complex command-line with sub-commands. It uses pflag for flag parsing instead of the standard flag.

Viper is a key-value database mainly for application configurations. Viper can be configured to look up keys from many sources including configuration files in miscellaneous formats, environment variables, command-line flags, and so on.

A standard cobra application finds $HOME/.{appname}.{supported_exts} and binds it to the viper database. You can find the supported filename extensions in viper godoc.

What well does for cobra

Well adds the following command-line flags using pflag:

  • --logfile: the filename that the default logger outputs.
  • --loglevel: logging threshold for the default logger (critical, error, warning, info, debug).
  • --logformat: log format for the default logger (plain, json, logfmt).

and binds them to viper as follows:

  • --logfile flag is bound to log.file viper key.
  • --loglevel flag is bound to log.level viper key.
  • --logformat flag is bound to log.format viper key.

Your cobra application may load logging configurations from the application config file by adding these keys. A sample YAML configuration snippet looks like:

log:
  level: error
  format: json

What every cobra program need to do

It is quite handy to configure the default logger using pflag and viper.
In the root command, add PersistentPreRun as follows:

import (
        "github.com/cybozu-go/log"
        "github.com/cybozu-go/well"
        "github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
        // ...snip
        PersistentPreRun: func(cmd *cobra.Command, args []string) {
                err := well.LogConfig{}.Apply()
                if err != nil {
                        log.ErrorExit(err)
                }
        },
}