Categorygithub.com/cpliakas/cliutil
modulepackage
0.2.6
Repository: https://github.com/cpliakas/cliutil.git
Documentation: pkg.go.dev

# README

cliutil

Tests Actions Status Go Reference Go Report Card

Helper functions that simplify writing CLI tools in Golang using the Cobra and Viper libraries.

Installation

With a correctly configured Go toolchain:

go get github.com/cpliakas/cliutil

Next, include cliutil in your application:

import "github.com/cpliakas/cliutil"

Usage

Flagger

Convenience functions that make it easier to add options to commands when using Cobra and Viper.


var myCfg *viper.Viper

func init() {

	// Assumes rootCmd and myCmd are defined. We are adding flags to myCmd.
	// See https://github.com/spf13/cobra#create-additional-commands
	rootCmd.AddCommand(myCmd)
    
	// Configure the AutomaticEnv capability to read configuration from
	// environment variables prefixed with "MYAPP_".
	// See https://github.com/spf13/viper#working-with-environment-variables
	myCfg = cliutil.InitConfig("MYAPP")

	// Add flags to myCmd. Use the myCfg.Get* methods to get the options passed
	// via command line. See https://github.com/spf13/viper for usage docs.
	flags := cliutil.NewFlagger(myCmd, myCfg)
	flags.String("log-level", "l", "info", "the minimum log level")
	flags.Int("max-num", "n", 100, "the maximum number of something")
}

Or ...


var myCfg *viper.Viper

func init() {
	var flags *cliutil.Flagger
	myCfg, flagger = cliutil.AddCommand(rootCmd, myCmd, "MYAPP")

	flags.String("log-level", "l", "info", "the minimum log level")
	flags.Int("max-num", "n", 100, "the maximum number of something")
}

Option Struct Tags

Set and read options via the cliutil struct tag, as shown with the PrintOpts struct below:

package cmd

import (
	"fmt"

	"github.com/cpliakas/cliutil"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

type PrintOpts struct {
	Text string `cliutil:"option=text short=t default='default value' usage='text printed to stdout'"`
}

var printCfg *viper.Viper

var printCmd = &cobra.Command{
	Use:   "print",
	Short: "Print text to STDOUT",
	Run: func(cmd *cobra.Command, args []string) {
		input := &PrintOpts{}
		cliutil.ReadOptions(input, printCfg)
		fmt.Println(input.Text)
	},
}

func init() {
	var flags *cliutil.Flagger
	printCfg, flags = cliutil.AddCommand(rootCmd, printCmd, "MYAPP")
	flags.SetOptions(&PrintOpts{})
}

Assuming rootCmd exists and defines the myapp command:

$> ./myapp print --text hello
hello

The func key allows for post-processing options. For example, setting func=ioreader and passing /path/to/file as the corresponding option will read the contents of the file into the field. Setting func=stdin will read STDIN into the field if the option isn't explicitly set. Setting func=boolstring will accept a string option and convert it to a boolean.

type Input struct {
	File string `cliutil:"option=file func=ioreader"   usage='read data from file/url' `
	Data string `cliutil:"option=data func=stdin"      usage='read data from STDIN'`
	Bool bool   `cliutil:"option=bool func=boolstring" usage='convert the string too a boolean'`
}

Key/Value Parser

Parses strings like key1=value1 key2="some other value" into a map[string]string.


func parseValues() {
	s := `key1=value1 key2="some other value"`
	m := cliutil.ParseKeyValue(s)
	fmt.Println(m["key1"])  // prints "value1"
	fmt.Println(m["key2"])  // prints "some other value"
}

Event Listener

Listens for shutdown events, useful for long-running processes.

func main() {

	// Start the event listener. A message is sent to the shutdown channel when
	// a SIGINT or SIGTERM signal is received.
	listener := cliutil.NewEventListener().Run()

	// Do something long-running in a goroutine.
	go doStuff()

	// Wait for the shutdown signal.
	listener.Wait()
	log.Println("shutdown signal received, exiting")
}

func doStuff() {
	// do stuff here
}

Leveled Logger with Context

A simple, leveled logger with log tags derived from context. The defaults are inspired by the best practices suggested by Splunk.

func main() {
	ctx, logger, _ := cliutil.NewLoggerWithContext(context.Background(), cliutil.LogDebug)
	logger.Debug(ctx, "transaction id created")
	// 2020/04/29 14:24:50.516125 DEBUG message="transaction id created" transid=bqkoscmg10l5tdt068i0

	err := doStuff()
	logger.FatalIfError(ctx, "error doing stuff", err)
	// no-op, will only log the message if err != nil.

	ctx = cliutil.ContextWithLogTag(ctx, "stuff", "done doing it")
	logger.Notice(ctx, "shutdown")
	// 2020/04/29 14:24:50.516140 NOTICE message="shutdown" transid=bqkoscmg10l5tdt068i0 stuff="done doing it"
}

func doStuff() error {

	// do stuff here, returns any errors

	return nil
}

# Functions

AddCommand adds a comand to it's parent, initializes the configuration, and returns a flagger to easily add options.
ContextWithLogTag returns a new context with log tags appended.
DefaultMessageWriter formats log messages according to Splunk's best practices.
FormatJSON returns pretty-printed JSON as a string.
FormatJSONWithFilter applies a JMESPath filter and returns pretty-printed JSON as a string and panics on any marshal errors.
GetOptions reads options from cfg into a.
HandleError either performs a no-op if err is nil or writes the error plus command usage to os.Stderr and exits with a non-zero status otherwise.
HasSpace returns true if s has a space.
InitConfig returns a *viper.Viper with an environment variable prefix set so that options can be passed from environment variables.
IsLetters returns true if s only contains letters.
IsNumber returns true if s only contains numbers.
LogLevel returns the log level's integer representation.
LogLevelValid return true if the log level is valid.
NewBoolOption is an OptionTypeFunc that returns a *BoolOption.
NewBoolStringOption is an OptionTypeFunc that returns a *BoolStringOption.
NewEventListener returns an EventListener with the channels initialized.
NewFlagger returns a new Flagger with the *cobra.Command and *viper.Viper set as properties.
NewFloat64Option is an OptionTypeFunc that returns a *Float64Option.
NewIntOption is an OptionTypeFunc that returns an *IntOption.
NewIntSliceOption is an OptionTypeFunc that returns an *IntSliceOption.
NewIOReaderOption is a OptionTypeFunc that returns a *GroupOption.
NewKeyValueOption is an OptionTypeFunc that returns an *KeyValueOption.
NewLogger returns a LeveledLogger that writes logs to either os.Stdout or ioutil.Discard depending on the passed minimum log level.
NewLoggerWithContext returns a leveled logger with a context that is initialized with a unique transaction ID.
NewStdinOption is an OptionTypeFunc that returns a *StdinOption.
NewStringOption is an OptionTypeFunc that returns a *StringOption.
ParseIntSlice parses a slice of integers from a string.
ParseKeyValue parses key value pairs.
PrintJSON writes pretty-printed JSON to STDOUT.
PrintJSONWithFilter applies a JMESPath filter and writes pretty-printed JSON to STDOUT.
ReadOptions reads options from cfg into a.
RegisterOptionTypeFunc registers an OptionReadSetter by naame.
Sequence returns a sequencce of numbers between start and end as an []int.
SetBoolValue sets s if the name flag is passed.
SetFloat64Value sets v if the name flag is passed.
SetIntSliceValue sets v if the name flag is passed.
SetIntValue sets v if the name flag is passed.
SetOptionMetadata sets metadata for an option.
SetStringValue sets v if the name flag is passed.
Use formats a value for cobra.Command.Use.
WriteError formats and writes an error message to io.Writer w.

# Constants

Ctx* constants contain the keys for contexts with values.
Log* constants represent the log levels as strings for configuration.
Log* constants represent the log levels as strings for configuration.
Log* constants represent the log levels as strings for configuration.
Log* constants represent the log levels as strings for configuration.
LogLevel* represents log levels as integers for comparrison.
LogLevel* represents log levels as integers for comparrison.
LogLevel* represents log levels as integers for comparrison.
LogLevel* represents log levels as integers for comparrison.
LogLevel* represents log levels as integers for comparrison.
LogLevel* represents log levels as integers for comparrison.
Log* constants represent the log levels as strings for configuration.
Log* constants represent the log levels as strings for configuration.
LogTagTransactionID is the log tag that contains the transaction ID.
TagName is the name of the tag.

# Variables

Err* variables contain comon errors.
Err* variables contain comon errors.
Err* variables contain comon errors.
Err* variables contain comon errors.

# Structs

BoolOption implements Option for bool options.
BoolStringOption implements Option for string options.
EventListener listens for SIGINT and SIGTERM signals and notifies the shutdown channel if it detects that either was sent.
Flagger is a utility that streamlines adding flags to commands.
Float64Option implements Option for float64 options.
IntOption implements Option for int options.
IntSliceOption implements Option for []int options.
IOReaderOption implements Option for string options read from an io.Reader.
KeyValueOption implements Option for []int options.
LeveledLogger is a simple leveled logger that writes logs to STDOUT.
StdinOption implements Option for string options read via stdin.
StringOption implements Option for string options.

# Interfaces

OptionType is implemented by structs that set and read options.

# Type aliases

MessageWriter defines a function the writes the log messages.
OptionTypeFunc is a definition for functions that return an OptionType.