Snek is a lite wrapper around both cobra and zerolog. It generates a configurable root command, adds some command line arguments and environment variables to configure both the log format and level and then initialized logging prior to executing the command. Another way to look at snek is as a builder pattern for cobra.
Usage focuses mostly around the Run / RunExit functions. With these functions you define a configuration, initialize the generated command and then run the generated command.
Command configurations are generated by calling the NewConfig function with any desired configurators. A configurator is a function that accepts a *Config as a parameter and may modify the *Config in any way. You may write your own configurators, however some built-in configurators are provided:
| Name | Description |
|---|---|
| WithDefaultLogFormat | Sets the default log format. |
| WithDefaultLogLevel | Sets the default log level. |
| WithEnvironmentVariablePrefix | Sets the environment variable prefix. |
| WithLogFormatCommandLineVariableHelp | Sets the help displayed for the log format command line flag. |
| WithLogFormatCommandLineVariableLongName | Sets the long variable name for the log format command line flag. |
| WithLogFormatCommandLineVariableShortName | Sets the short variable name for the log format command line flag. |
| WithLogFormatEnvironmentVariableName | Sets the environment variable to query for the log format. |
| WithLogLevelCommandLineVariableHelp | Sets the help displayed for the log level command line flag. |
| WithLogLevelCommandLineVariableLongName | Sets the long variable name for the log level command line flag. |
| WithLogLevelCommandLineVariableShortName | Sets the short variable name for the log level command line flag. |
| WithLogLevelEnvironmentVariableName | Sets the environment variable to query for the log level. |
| WithLogOutput | Sets the log output writer to use when logging. |
The following generates a configuration with the following set:
- The default log format set to
json - The default log level set to
debug - The environment variable prefix set to
MY_AWESOME_APP_
cfg := snek.NewConfig(
snek.WithDefaultLogFormat("json"),
snek.WithDefaultLogLevel("debug"),
snek.WithEnvironmentVariablePrefix("MY_AWESOME_APP_"),
)Commands are generated by calling the NewCommand function with any desired Initializer functions. An Initializer is a function that accepts a *cobra.Command as a parameter and may modify the *cobra.Command in any way, or return an error. You may write your own Initializer, however some are built-in:
| Name | Description |
|---|---|
| WithAliases | Sets the Aliases member on the generated command. |
| WithDeprecated | Sets the Deprecated member on the generated command. |
| WithExample | Sets the Example member on the generated command. |
| WithLong | Sets the Long member on the generated command. |
| WithRun | Sets the Run member on the generated command. |
| WithRunE | Sets the RunE member on the generated command. |
| WithShort | Sets the Short member on the generated command. |
| WithSimpleRun | Sets the Run member on the generated command to a function that only accepts positional arguments and does not return an error. |
| WithSimpleRunE | Sets the RunE member on the generated command to a function that only accepts positional arguments and returns an error. |
| WithSubCommand | Adds a sub-command to the generated command. |
| WithSubCommandGenerator | Adds a sub-command to the generated command, by calling the command generator. |
| WithUse | Sets the Use member on the generated command. |
| WithValidArgs | Sets the ValidArgs member on the generated command. |
| WithVersion | Sets the Version member on the generated command. |
Initializers are also passed to the Run and RunExit functions. These initializers are used to generate the root command that is executed by snek.
cmd, err := snek.NewCommand(
snek.WithUse("my-awesome-command"),
snek.WithShort("The shortened description for my command"),
snek.WithLong("The lengthier description for my command"),
snek.WithRunE(func(cmd *cobra.Command, args []string) error {
// ...
return nil
})
)Flags can be added to a generated command by calling the WithFlags function with any desired FlagInitializer functions. A FlagInitializer is a function that accepts a *pflag.FlagSet as a parameter and may modify the *pflag.FlagSet in any way, add one or more flags, or return an error. You may write your own FlagInitializer, however some are built-in:
| Name | Description |
|---|---|
| WithBoolVar | Add a bool flag with only a long name. |
| WithBoolVarP | Add a bool flag with a long and short name. |
| WithDurationVar | Add a time.Duration flag with only a long name. |
| WithDurationVarP | Add a time.Duration flag with a long and short name. |
| WithFloat32Var | Add a float32 flag with only a long name. |
| WithFloat32VarP | Add a float32 flag with a long and short name. |
| WithFloat64Var | Add a float64 flag with only a long name. |
| WithFloat64VarP | Add a float64 flag with a long and short name. |
| WithIntVar | Add a int flag with only a long name. |
| WithIntVarP | Add a int flag with a long and short name. |
| WithStringVar | Add a string flag with only a long name. |
| WithStringVarP | Add a string flag with a long and short name. |
greeting := "hello!"
quantity := 1
cmd, err := snek.NewCommand(
snek.WithFlag(
snek.WithStringVarP(&greeting, "greeting", "g", greeting, "The greeting to use"),
snek.WithStringVarP(&quantity, "quantity", "q", quantity, "The quantity of times to greet"),
),
// ...
)package main
import (
"io"
"net/http"
"github.com/ronelliott/snek"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)
func main() {
snek.RunExit(
snek.NewConfig(
snek.WithDefaultLogFormat("json"),
snek.WithDefaultLogLevel("debug"),
snek.WithEnvironmentVariablePrefix("MY_AWESOME_APP_"),
),
snek.WithUse("my-awesome-command"),
snek.WithSubCommandGenerator(
newRunCommand,
),
)
}
func newRunCommand() (*cobra.Command, error) {
port := ":3000"
return snek.NewCommand(
snek.WithUse("run"),
snek.WithShort("Run the application"),
snek.WithFlag(
snek.WithStringVarP(&port, "port", "p", port, "The port to bind to"),
),
snek.WithSimpleRunE(func(args []string) error {
helloHandler := func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "Hello, world!\n")
}
http.HandleFunc("/hello", helloHandler)
log.Info().Str("port", port).Msg("Listening")
return http.ListenAndServe(port, nil)
}),
)
}