clio

package module
v0.0.0-...-76d52b9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2023 License: Apache-2.0 Imports: 23 Imported by: 0

README

CLIO

An easy way to bootstrap your application with batteries included.

Status

Consider this project to be in alpha. The API is not stable and may change at any time.

What is included?

  • Pairs well with cobra and viper via fangs, covering CLI arg parsing and config file + env var loading.
  • Provides an event bus via partybus, enabling visibility deep in your execution stack as to what is happening.
  • Provides a logger via the logger interface, allowing you to swap out for any concrete logger you'd like.
  • Supplies a redactor object that can be used to remove sensitive output before it's exposed (in the log or elsewhere).
  • Defines a generic UI interface that adapts well to TUI frameworks such as bubbletea.

Example

Here's a basic example of how to use clio + cobra to get a fully functional CLI application going:

package main

import (
	"io"
	"os"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/wagoodman/go-partybus"
	"github.com/boss-net/clio"
	"github.com/boss-net/fangs"
)

// Define your per-command or entire application config as a struct
type MyCommandConfig struct {
	TimestampServer string `mapstructure:"timestamp-server"`
	// ...
}

// ... add cobra flags just as you are used to doing in any other cobra application
func (c *MyCommandConfig) AddFlags(flags fangs.FlagSet) {
	flags.StringVarP(
		&c.TimestampServer, "timestamp-server", "",
		"URL to a timestamp server to use for timestamping the signature",
	)
	// ...
}

func MyCommand(app clio.Application) *cobra.Command {
	cfg := &MyCommandConfig{
		TimestampServer: "https://somewhere.out/there", // a default value
	}

	return app.SetupCommand(&cobra.Command{
		Use:     "my-command",
		PreRunE: app.Setup(cfg),
		RunE: func(cmd *cobra.Command, args []string) error {
			// perform command functions here
			return nil
		},
	}, cfg)
}

func main() {
	cfg := clio.NewSetupConfig(clio.Identification{
		Name: "awesome",
		Version: "v1.0.0",
    })

	app := clio.New(*cfg)
	
	root := app.SetupRootCommand(&cobra.Command{})

	root.AddCommand(MyCommand(app))

	if err := root.Execute(); err != nil {
		os.Exit(1)
	}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultLogger

func DefaultLogger(clioCfg Config, store redact.Store) (logger.Logger, error)

func VersionCommand

func VersionCommand(id Identification) *cobra.Command

Types

type Application

type Application interface {
	AddFlags(flags *pflag.FlagSet, cfgs ...any)
	SetupCommand(cmd *cobra.Command, cfgs ...any) *cobra.Command
	SetupRootCommand(cmd *cobra.Command, cfgs ...any) *cobra.Command
}

func New

func New(cfg SetupConfig) Application

type BusConstructor

type BusConstructor func(Config) *eventbus.Bus

type Config

type Config struct {
	// Items that end up in the target application configuration
	Log *LoggingConfig     `yaml:"log" json:"log" mapstructure:"log"`
	Dev *DevelopmentConfig `yaml:"dev" json:"dev" mapstructure:"dev"`

	// this is a list of all "config" objects from SetupCommand calls
	FromCommands []any `yaml:"-" json:"-" mapstructure:"-"`
}

type DevelopmentConfig

type DevelopmentConfig struct {
	Profile Profile `yaml:"profile" json:"profile" mapstructure:"profile"`
}

func (*DevelopmentConfig) DescribeFields

func (d *DevelopmentConfig) DescribeFields(set fangs.FieldDescriptionSet)

func (*DevelopmentConfig) PostLoad

func (d *DevelopmentConfig) PostLoad() error

type Identification

type Identification struct {
	Name           string `json:"application,omitempty"`    // application name
	Version        string `json:"version,omitempty"`        // application semantic version
	GitCommit      string `json:"gitCommit,omitempty"`      // git SHA at build-time
	GitDescription string `json:"gitDescription,omitempty"` // indication of git tree (either "clean" or "dirty") at build-time
	BuildDate      string `json:"buildDate,omitempty"`      // date of the build
}

Identification defines the application name and version details (generally from build information)

type Initializer

type Initializer func(*State) error

type LoggerConstructor

type LoggerConstructor func(Config, redact.Store) (logger.Logger, error)

type LoggingConfig

type LoggingConfig struct {
	Quiet        bool         `yaml:"quiet" json:"quiet" mapstructure:"quiet"` // -q, indicates to not show any status output to stderr
	Verbosity    int          `yaml:"-" json:"-" mapstructure:"verbosity"`     // -v or -vv , controlling which UI (ETUI vs logging) and what the log level should be
	Level        logger.Level `yaml:"level" json:"level" mapstructure:"level"` // the log level string hint
	FileLocation string       `yaml:"file" json:"file" mapstructure:"file"`    // the file path to write logs to
	// contains filtered or unexported fields
}

LoggingConfig contains all logging-related configuration options available to the user via the application config.

func (*LoggingConfig) AddFlags

func (l *LoggingConfig) AddFlags(flags fangs.FlagSet)

func (*LoggingConfig) AllowUI

func (l *LoggingConfig) AllowUI(stdin fs.File) bool

func (*LoggingConfig) DescribeFields

func (l *LoggingConfig) DescribeFields(d fangs.FieldDescriptionSet)

func (*LoggingConfig) PostLoad

func (l *LoggingConfig) PostLoad() error

type Profile

type Profile string
const (
	ProfileCPU        Profile = "cpu"
	ProfileMem        Profile = "mem"
	ProfilingDisabled Profile = "none"
)

type SetupConfig

type SetupConfig struct {
	// Metadata about the target application
	ID Identification

	// Default configuration items that end up in the target application configuration
	DefaultLoggingConfig     *LoggingConfig
	DefaultDevelopmentConfig *DevelopmentConfig

	// Items required for setting up the application (clio-only configuration)
	FangsConfig       fangs.Config
	BusConstructor    BusConstructor
	LoggerConstructor LoggerConstructor
	UIConstructor     UIConstructor
	Initializers      []Initializer
	// contains filtered or unexported fields
}

func NewSetupConfig

func NewSetupConfig(id Identification) *SetupConfig

func (*SetupConfig) WithBusConstructor

func (c *SetupConfig) WithBusConstructor(constructor BusConstructor) *SetupConfig

func (*SetupConfig) WithConfigFinders

func (c *SetupConfig) WithConfigFinders(finders ...fangs.Finder) *SetupConfig

func (*SetupConfig) WithConfigInRootHelp

func (c *SetupConfig) WithConfigInRootHelp() *SetupConfig

func (*SetupConfig) WithDevelopmentConfig

func (c *SetupConfig) WithDevelopmentConfig(cfg DevelopmentConfig) *SetupConfig

func (*SetupConfig) WithGlobalConfigFlag

func (c *SetupConfig) WithGlobalConfigFlag() *SetupConfig

func (*SetupConfig) WithGlobalLoggingFlags

func (c *SetupConfig) WithGlobalLoggingFlags() *SetupConfig

func (*SetupConfig) WithInitializers

func (c *SetupConfig) WithInitializers(initializers ...Initializer) *SetupConfig

func (*SetupConfig) WithLoggerConstructor

func (c *SetupConfig) WithLoggerConstructor(constructor LoggerConstructor) *SetupConfig

func (*SetupConfig) WithLoggingConfig

func (c *SetupConfig) WithLoggingConfig(cfg LoggingConfig) *SetupConfig

func (*SetupConfig) WithNoBus

func (c *SetupConfig) WithNoBus() *SetupConfig

func (*SetupConfig) WithNoLogging

func (c *SetupConfig) WithNoLogging() *SetupConfig

func (*SetupConfig) WithUI

func (c *SetupConfig) WithUI(uis ...UI) *SetupConfig

func (*SetupConfig) WithUIConstructor

func (c *SetupConfig) WithUIConstructor(constructor UIConstructor) *SetupConfig

type State

type State struct {
	Config       Config
	Bus          *partybus.Bus
	Subscription *partybus.Subscription
	Logger       logger.Logger
	RedactStore  redact.Store
	UIs          []UI
}

type UI

type UI interface {
	Setup(subscription partybus.Unsubscribable) error
	partybus.Handler
	Teardown(force bool) error
}

type UIConstructor

type UIConstructor func(Config) ([]UI, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL