- Notifications
You must be signed in to change notification settings - Fork1
Shogun: Functions As Commands for the true samurai developer.
License
influx6/shogun
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Shogun provides Functions as Commands(FACM), which allows the execution of Go functions from the terminal.Such functions receive data through the standard input, respond through standard output and standard errorchannels of your termianl or pty terminal.
Shogun also creates project files and binaries for all packages, which lets youquickly generate Go binaries for your functions, which can be moved and run anywhereindividually.
Inspired bymage andAmazon Lambda functions as Runnable items
Shogun follows the strict requirement that every information to be received by a function mustcome through the standard input filestdin
, this ensures you can pass arbitrary data in or evenJSON payloads to be loaded into aStruct
type.
More so, all response must either be an error returned which will be delivered throughthe standard error filestderr
or be a response written to aio.WriteCloser
to deliverto the standard output filestdout
.
go install -u github.com/influx6/shogun
Then runshogun
to validate successful install:
> shogun⠙ Nothing to do...⡿ Run`shogun -h` to see what it takes to make me work.
Shogun only requires that you have a working installation of Go (>= 1.2) installed with yourGOPATH
set accordingly.
Writing Go package which are to be used by Shogun to generate binaries are rather simple,and only require that each package has all it files tagged with the following build tag aboveit's package declaration with space in between:
// +build shogunpackage something
Your are free to use any other build tag as well and will be sorted accordingly.
Shogun by default will save binaries into theGOBIN
orGOPATH/bin
path extractedfrom the environment, however this can be changed by setting aSHOGUNBIN
environmentvariable. More so, Shogun names all binaries the name of the parent package unless onedeclares an explicit annotation@binaryName
at the package level.
// +build shogun// Package do does something.////@binaryName(name => shogunate_bin)package do
If you wished to add a description for the binary command, we can add adesc
attributein a json block of the@binaryName
annotation.
// +build shogun/* Package do does something.@binaryName(asJSON, name => shogunate_bin, { { "desc": "shogunate_bin provides a nice means" }})*/package do
All binaries created by shogun are self complete and can equally be called directly withouttheshogun
command, which makes it very usable for easy deployable self contained binariesthat can be used in place where behaviors need to be exposed as functions.
Shogun packages are normal Go packages and all directories within the root where shogunis executed will be parsed and processed for identification of possible shogun packages,where those identified will each have a binary generated and the main package if any foundwill combine all other binaries into a single one if so desired.
Shogun focuses on the execution of functions, that supports a limited set of formats.More so, each format allows the use ofContext
orContext
objectsas first place arguments.
- No Argument Functions
func()func()error
- Context Only Functions
func(Context)func(Context)error
- String based Functions
func(string)func(string)errorfunc(Context,string)errorfunc(Context,string, io.WriteCloser)error
- StringSlice based Functions
func([]string)func([]string)errorfunc(Context, []string)errorfunc(Context, []string, io.WriteCloser)error
- Map based Functions
func(map[string]interface{})func(map[string]interface{})errorfunc(Context,map[string]interface{})errorfunc(Context,map[string]interface{}, io.WriteCloser)error
- Struct based Functions
func(Struct)func(Struct)errorfunc(Context,Struct)errorfunc(Struct, io.WriteCloser)errorfunc(Context,Struct, io.WriteCloser)error
- Struct Pointer based Functions
func(*Struct)func(*Struct)errorfunc(Context,*Struct)errorfunc(*Struct, io.WriteCloser)errorfunc(Context,*Struct, io.WriteCloser)error
- Imported Struct based Functions
func(package.Struct)func(package.Struct)errorfunc(Context, package.Struct)errorfunc(package.Struct, io.WriteCloser)errorfunc(Context, package.Struct, io.WriteCloser)error
- Imported Struct Pointer based Functions
func(*package.Struct)func(*package.Struct)errorfunc(Context,*package.Struct)errorfunc(*package.Struct, io.WriteCloser)errorfunc(Context,*package.Struct, io.WriteCloser)error
- io.Reader based Functions
func(io.Reader)func(io.Reader)errorfunc(Context, io.Reader)error
- io.Writer based Functions
func(io.WriteCloser)func(io.WriteCloser)errorfunc(Context, io.WriteCloser)error
- io.Reader and io.Writer based Functions
func(io.Reader, io.WriteCloser)func(io.Reader, io.WriteCloser)errorfunc(Context, io.Reader, io.WriteCloser)error
WhereContext
=> represents the context package.
WhereStruct
=> represents any struct declared in package
wherepackage.Struct
=> represents Struct type imported from other package
Any other thing beyond this type formats won't be allowed and will be ignored infunction list and execution.
// +build shogun// Package katanas provides exported functions as tasks runnable from commandline.//// @binaryName(name => katana-shell)//package katanasimport ("fmt""io""context"ty"github.com/influx6/shogun/examples/types")typewondrastruct {Namestring}funcDraw() {}// Slash is the default tasks due to below annotation.// @defaultfuncSlash()error {fmt.Println("Welcome to Katana slash!")returnnil}funcBob(ctx context.Context,namestring)error {fmt.Printf("Welcome to bob %q.\n",name)returnnil}//@flag(name => time, env => JIJA_TIME, type => Duration, desc => specifies time for jija)funcJija(ctx context.Context,mp ty.Woofer)error {jijatime,found:=ctx.Bag().GetDuration("time")returnnil}
In shogun, you can tag a function as the default function to be executed every it'sbinary is called without argument through shogun or through it's generated binary, by tagging it with a@default
annotation.
Shogun also supports function level flags, where a function using annotation canspecify particular flags which it will access from the either theContext
packageif passed in, except forContext
which only functions for cancelation.
Only the following packages are allowed for usage. If you need context, then itmust always be the first argument.
- context "context.Context"
- github.com/influx6/fuax/context "context.Context"
When usingcontext.Context
package from the internal Go packages, only its ability to be used asa timeout will be set if the-t
or-timeout
flag has a value. Support of filling context with valuesis not planned or desired.
Shogun will use the-time
flag received through the commandline to set lifetimetimeout for the 2 giving context else the context will not have expiration deadlines.
Note that shogun by default does not respectContext
timeouts, it's up to you towrite your function source to takeContext
into account for the lifetime of your function.
Before using any other command apart fromshogun list
in a package, always execute:
> shogun build
Shogun by defaults will process both the root and all first level directories thathave shogun files within, generating appropriate binaries based on package name orifbinaryName
annotation is declared, and will also generate a single binary ifthere exists any shogun files within the root directory, with subcommands that willconnect to other binaries in the first level directories.
This allows you to have a single binary that is bundled with all commands for executing functionsfrom any other subpackage, but this can be changed to only allow single binaries, incase youwant truly separate binaries.
Note, this only applies, if you have Go files that have the+build shogun
within the root, whereshogun build
gets executed.
Shogun will hash shogun files and ensure only when changes occur will a new build bemade and binary will be stored in binary location as dictated by environmentvariableSHOGUNBIN
or defaultGOBIN
/GOPATH/bin
.
Using theshogun
command, we can do the following:
- Build shogun based package files
Run this if the shogun files and directories exists right in the root directory.
shogun build
- Build shogun based package files and remove generated package
shogun build -rm
- Build shogun based package files without generating binaries
Run this if the shogun files and directories exists right in the root directory.
shogun build -skip
- Build a shogun based package files from a directory
shogun build -d=./examples
- Build only shogun based package files into root as packages without main file
shogun build -nomain
- Build shogun based package files binary in directory path
shogun build -bin=./
- Build a shogun based package files in a directory and split binaries as single
shogun build -single -d=./examples -cmd=./cmd
- Build a shogun based package files in a directory and store generated packages in directory
cmd
shogun build -d=./examples -cmd=./cmd
- Build a shogun based package files in a directory without generating binaries
shogun build -skip -d=./examples
- Force rebuild a shogun based package files in a directory
shogun build -f -d=./examples
- Add new shogun file to current package
shogun add vuz.go
- Add new shogun file into a directory in current package
shogun add -dir=vuz vuz.go
- Add new shogun files into package
shogun add vuz.go ball.go wreck.go
You can also add more files into a directory when using-dir
flag in this manner.
- Add new shogun files into package but use
main
as package name
shogun add -m vuz.go
- List all functions in the root
shogun list
- List all functions in from a directory
shogun list -dir=./examples
- List all functions with short commentary
shogunhelp {{BINARYNAME}} {{FunctionName}}
- List all functions with full commentary and source
shogunhelp -s {{BINARYNAME}} {{FunctionName}}
- Run function of package binary that expects no input
shogun {{BINARYNAME}} {{FUNCTIONNAME}}
- Run function of package binary expecting string input with standard input
echo"We lost the war"| shogun {{BINARYNAME}} {{FUNCTIONNAME}}
- Run function of package binary expecting json input with standard input
{"name":"bat"}| shogun {{BINARYNAME}} {{FUNCTIONNAME}}
No, every binary that is built is self contained and theshogun
CLI only proxiescalls to the binary which it expects to be in theSHOGUNBIN
orGOBIN
/GOPATH/bin
.You can call the binary directly withoutshogun
and will work as expected if the pathis added into your environment paths.
With the latest update to shogun, if you have shogun marked package files inyour root directory of your package or within the area whereshogun build
getscalled, then any change will be rebuilt automatically. But for others, you wouldneed to specifically runshogun build -dir=''
to build a given directory.
Whilemage
focuses on using Go functions likemake
orrake
tasks, shogunexpands the usage of functions not just as task runners, but as self contained purebehaviors that can receive input and respond. This allows you to build commandlineapps quicker withshogun
and even quickly test out function behaviours.
More so, I envisionshogun
for the purpose of being able to deploy shogun builtbinaries into docker images as pure functions, that can be used to support a serviceor serve a service like a static file server which only ever runs when needed, ..etc
Of course, you can useshogun
functions like tasks similar tomage
, but in effectthat is a side benefit of the approach.
Contributions are welcome, do please checkout theContribution Guidlines.
Logo is a work ofShadow Fight Wiki.
About
Shogun: Functions As Commands for the true samurai developer.