Skip to content
/ cli Public

Reduce boiler plate needed on each new Golang main functions (Command Line Interface) for both tool and servers

License

Notifications You must be signed in to change notification settings

fortio/cli

Repository files navigation

Go Reference Go Report Card GitHub Release

cli

Reduce boiler plate needed on each new Golang main functions (Command Line Interface) for both tools and servers (use fortio.org/scli ServerMain() for server)

It abstracts the repetitive parts of a main() command line tool, flag parsing, usage, etc...

You can see real use example in a tool like multicurl or a server like proxy.

It also supports (sub)commands style (where there is a word/command before the flags and remaining arguments, fortio uses that mode).

Tool Example

Client/Tool example (no dynamic flag url or config) sampleTool

Code as simple as

import (
	"flag"
	"os"

	"fortio.org/cli"
	"fortio.org/log"
)

func main() {
	myFlag := flag.String("myflag", "default", "my flag")
	cli.MinArgs = 2
	cli.MaxArgs = 4
	cli.Main() // Will have either called cli.ExitFunction or everything is valid
	// Next line output won't show when passed -quiet
	log.Infof("Info test, -myflag is %q", *myFlag)
	// This always shows
	log.Printf("Hello world, version %s, args %v", cli.ShortVersion, flag.Args())
	// This shows and is colorized and structured, unless loglevel is set to critical.
	log.S(log.Error, "Error test",
		log.Str("myflag", *myFlag),
		log.Attr("num_args", len(flag.Args())),
		log.Attr("args", flag.Args()))
}
$ sampleTool a
sampleTool 1.2.0 usage:
	sampleTool [flags] arg1 arg2 [arg3...arg4]
or 1 of the special arguments
	sampleTool {help|version|buildinfo}
flags:
  -logger-force-color
    	Force color output even if stderr isn't a terminal
  -logger-no-color
    	Prevent colorized output even if stderr is a terminal
  -loglevel level
    	log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info)
  -myflag string
    	my flag (default "default")
  -quiet
    	Quiet mode, sets loglevel to Error (quietly) to reduces the output
At least 2 arguments expected, got 1

Since v1.3, the above is colorized on a terminal and looks like this:

Color usage output

or normal case:

Color log output

Old style, no colors:

$ sampleTool -logger-no-color a b
17:20:41 [I] Info test, -myflag is "default"
17:20:41 Hello world, version dev, args [a b]
17:20:41 [E] Error test, myflag="default", num_args="2", args="[a b]"

Additional builtins

buildinfo

e.g

% go install github.com/fortio/multicurl@latest
go: downloading github.com/fortio/multicurl v1.10.1
% multicurl buildinfo
1.10.1 h1:h9yM3XplwG7JWtVaSS0eJPiDmCJfnxvj3w+yoAMWMo4= go1.19.6 arm64 darwin
go	go1.19.6
path	github.com/fortio/multicurl
mod	github.com/fortio/multicurl	v1.10.1	h1:h9yM3XplwG7JWtVaSS0eJPiDmCJfnxvj3w+yoAMWMo4=
dep	fortio.org/cli	v0.6.1	h1:V9L6ly4oz4fJjeQ5745FulIMsFAwFZvLPSUN+cKUrKk=
dep	fortio.org/log	v1.2.2	h1:vs42JjNwiqbMbacittZjJE9+oi72Za6aekML9gKmILg=
dep	fortio.org/version	v1.0.2	h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0=
build	-compiler=gc
build	CGO_ENABLED=1
build	CGO_CFLAGS=
build	CGO_CPPFLAGS=
build	CGO_CXXFLAGS=
build	CGO_LDFLAGS=
build	GOARCH=arm64
build	GOOS=darwin

help

% multicurl help
Fortio multicurl 1.10.1 usage:
	multicurl [flags] url
or 1 of the special arguments
	multicurl {help|version|buildinfo}
flags:
[...]
  -logger-force-color
    	Force color output even if stderr isn't a terminal
  -logger-no-color
    	Prevent colorized output even if stderr is a terminal
  -loglevel level
    	log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info)
  -quiet
    	Quiet mode, sets loglevel to Error (quietly) to reduces the output

version

Short 'numeric' version (v skipped, useful for docker image tags etc)

 % multicurl version
1.10.1

https/tls in FROM scratch docker images

You should always try to use FROM scratch Docker images when possible, it's one of the strength of go.

Using this fortio.org/cli as a base makes it work for outcalls to internet valid TLS certs (e.g. https). It does this by defaulting to the bundle provided by golang.org/x/crypto/x509roots/fallback automatically.

See https://github.com/fortio/multicurl for a good example.

If you do not want this behavior, build using -tags no_tls_fallback.

Small binaries

If you application doesn't do http request/response logging at all, use -tags no_http or -tags no_net (that one will also imply no_tls_fallback) and save 1.6 Mbytes in your binary's size (because the linker isn't smart enough to see net/http isn't actually used) (1.1Mbytes for log's no_http and 530k from the no_tls_fallback)

And, if you don't need any of the advanced JSON logging (which is quite likely with a cli), use -tags no_json the logger will still produce json structured logging just not as advanced if what you log are deep structures - this saves another 130k or so.

These tags are from fortio.org/log v1.14 and later

In summary: for smallest pure local cli binaries using this package:

CGO_ENABLE=0 go build -trimpath -ldflags="-w -s" -tags no_net,no_json .

saves ~1.7Mbytes in total (a basic cli dependending on this package will then only be about 300k more as an hello world yet include color help, buildinfo, version, logging etc)

About

Reduce boiler plate needed on each new Golang main functions (Command Line Interface) for both tool and servers

Resources

License

Stars

Watchers

Forks