Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ronelliott/snek

Cobra and zerolog setup for go.
https://github.com/ronelliott/snek

cli cobra command-line go golang zerolog

Last synced: about 2 months ago
JSON representation

Cobra and zerolog setup for go.

Awesome Lists containing this project

README

        

# snek

![Build Status](https://github.com/ronelliott/snek/actions/workflows/master.yml/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/ronelliott/snek)](https://goreportcard.com/report/github.com/ronelliott/snek)
[![Coverage Status](https://coveralls.io/repos/github/ronelliott/snek/badge.svg?branch=master)](https://coveralls.io/github/ronelliott/snek?branch=master)
[![Go Reference](https://pkg.go.dev/badge/github.com/ronelliott/snek.svg)](https://pkg.go.dev/github.com/ronelliott/snek)

Snek is a lite wrapper around both [cobra](https://github.com/spf13/cobra) and [zerolog](https://github.com/rs/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.

## Generating Options

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. |

### Example

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_`

```go
cfg := snek.NewConfig(
snek.WithDefaultLogFormat("json"),
snek.WithDefaultLogLevel("debug"),
snek.WithEnvironmentVariablePrefix("MY_AWESOME_APP_"),
)
```

## Generating Commands

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.

### Example

```go
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
})
)
```

## Generating Flags

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. |

### Example

```go
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"),
),
// ...
)
```

## Complete Example

```go
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)
}),
)
}
```