Skip to content

Commit

Permalink
(choria-io#1665) initial basic working app framework
Browse files Browse the repository at this point in the history
This allows applications to be built that wraps RPC and KV
components.

Application definitions are documented using a schema and
are validated on loading, from the definition a CLI app is
built that can have nested sub commands and more.

Application definitions goes in files called x-app.yaml,
a symlink from x to choria would then load x-app.yaml and
construct the CLI when x is invoked.

An additional config file can be read called applications.yaml
that can be accessed via go templates in the definition in a few
places.

The config and definitions can live in ., ~/.config/choria/builder
or /etc/choria/builder.

Paths are using XDG, but its a super primitive implementation
for the moment, will be refined via issue 1624, thus paths
and file names are subject to change

Signed-off-by: R.I.Pienaar <[email protected]>
  • Loading branch information
ripienaar committed May 11, 2022
1 parent f45e845 commit e8878bd
Show file tree
Hide file tree
Showing 9 changed files with 1,146 additions and 1 deletion.
18 changes: 17 additions & 1 deletion cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import (
"path/filepath"
"runtime"
"runtime/pprof"
"strings"
"sync"
"syscall"
"time"

"github.com/choria-io/go-choria/protocol"
"github.com/choria-io/go-choria/providers/appbuilder"

log "github.com/sirupsen/logrus"
"gopkg.in/alecthomas/kingpin.v2"
Expand Down Expand Up @@ -53,6 +55,20 @@ func ParseCLI() (err error) {

go interruptWatcher()

// If we are not invoked as something something choria, then check
// if the app builder has an app configuration matching the name we
// are run as, if it does, we invoke it instead of the standard choria
// cli tools
//
// TODO: too janky, need to do a better job here, looking at the name is not enough
if !strings.Contains(os.Args[0], "choria") {
builder := appbuilder.NewAppBuilder(ctx, filepath.Base(os.Args[0]))
if builder.HasDefinition() {
builder.RunCommand()
os.Exit(0)
}
}

bi = &build.Info{}

cli.app = kingpin.New("choria", "Choria Orchestration System")
Expand Down Expand Up @@ -210,7 +226,7 @@ func forcequit() {
}
}

<-time.NewTimer(grace).C
<-time.After(grace)

dumpGoRoutines()

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ require (
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/achanda/go-sysctl v0.0.0-20160222034550-6be7678c45d2 // indirect
github.com/adrg/xdg v0.4.0 // indirect
github.com/aelsabbahy/GOnetstat v0.0.0-20160428114218-edf89f784e08 // indirect
github.com/aelsabbahy/go-ps v0.0.0-20201009164808-61c449472dcf // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/achanda/go-sysctl v0.0.0-20160222034550-6be7678c45d2 h1:NYoPVh1XuUB5VBWLXRKoqzQhl4bajIxh+XuURbJ0uwc=
github.com/achanda/go-sysctl v0.0.0-20160222034550-6be7678c45d2/go.mod h1:DCNKSpXhum14Y258jSbRmJvcesbzEdBPincz7yJUx3k=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
github.com/aelsabbahy/GOnetstat v0.0.0-20160428114218-edf89f784e08 h1:oD15ssIOuFLi64zhkPRsaIDvhx4PeZb2QdQoR/wKY2g=
github.com/aelsabbahy/GOnetstat v0.0.0-20160428114218-edf89f784e08/go.mod h1:FETZSu2VGNDJbGfeRExaz/SNbX0TTaqJEMo1yvsKoZ8=
github.com/aelsabbahy/go-ps v0.0.0-20201009164808-61c449472dcf h1:KyjxaqJO0pHF7Clre644OiJ5s235JVRsz6ioDkoQ96s=
Expand Down Expand Up @@ -752,6 +754,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
243 changes: 243 additions & 0 deletions internal/fs/schemas/builder.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"id": "https://choria.io/schemas/choria/builder/v1/application.json",
"title": "io.choria.builder.v1.application",
"description": "Choria Builder Application Specification",
"type": "object",
"required": ["name","description","version","author","commands"],
"definitions": {
"shortname": {
"type": "string",
"minLength": 1,
"pattern": "^[a-z0-9_-]*$"
},
"semver": {
"type": "string",
"description": "Semantic Versioning 2.0.0 version string",
"minLength": 5,
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
},
"standard_command": {
"type": "object",
"required": ["name","description","type"],
"properties": {
"name": {
"type": "string",
"description": "A unique name for this command",
"$ref": "#/definitions/shortname"
},
"description": {
"$ref": "#/definitions/description"
}
}
},
"description": {
"type": "string",
"description": "A human friendly description of what an item does",
"minLength": 1
},
"generic_flag": {
"type": "object",
"required": ["name","description"],
"properties": {
"name": {
"description": "A unique name for this flag",
"$ref": "#/definitions/shortname"
},
"description": {
"$ref": "#/definitions/description"
},
"required": {
"type": "boolean",
"description": "Indicates this flag must be passed",
"default": false
},
"placeholder": {
"type": "string",
"description": "String to show as value place holder in help output"
}
}
},
"generic_argument":{
"type": "object",
"required": ["name","description"],
"properties": {
"name": {
"description": "A unique name for this argument",
"$ref": "#/definitions/shortname"
},
"description": {
"$ref": "#/definitions/description"
},
"required": {
"type": "boolean",
"description": "Indicates that this flag must be passed",
"default": false
}
}
},
"commands": {
"type": "array",
"items": {
"anyOf": [
{"$ref": "#/definitions/rpc_command"},
{"$ref": "#/definitions/parent_command"},
{"$ref": "#/definitions/kv_command"}
]
}
},
"parent_command": {
"type": "object",
"description": "A command that does not do anything but serves as a anchor for sub commands",
"additionalItems": false,
"allOf": [
{"$ref":"#/definitions/standard_command"},
{
"type": "object",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"const": "parent"
},
"commands": {
"description": "Additional CLI commands to add",
"$ref": "#/definitions/commands",
"minLength": 1
}
}
}
]
},
"kv_command": {
"type": "object",
"description": "A command that interact with the Choria Key-Value store",
"additionalItems": false,
"allOf": [
{"$ref":"#/definitions/standard_command"},
{
"type": "object",
"required": ["type","action","bucket","key"],
"properties": {
"type": {
"type": "string",
"const": "kv"
},
"commands": {
"description": "Additional CLI commands to add",
"$ref": "#/definitions/commands"
},
"bucket": {
"type": "string",
"description": "The name of the Key-Value store bucket",
"pattern": "\\A[a-zA-Z0-9_-]+\\z",
"minLength": 1
},
"key": {
"type": "string",
"description": "The key to act on",
"minLength": 1
},
"value": {
"type": "string",
"description": "The value to store for the put operation"
},
"action": {
"type": "string",
"description": "The action to perform against the bucket and key",
"enum": ["get","put","del"]
}
}
}
]
},
"rpc_command": {
"type": "object",
"additionalItems": false,
"allOf": [
{"$ref":"#/definitions/standard_command"},
{
"type": "object",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"const": "rpc"
},
"commands": {
"description": "Additional CLI commands to add",
"$ref": "#/definitions/commands"
},
"std_filters": {
"type": "boolean",
"description": "Enables standard RPC filters like -C, -I etc",
"default": false
},
"output_formats_flags": {
"type": "boolean",
"description": "Enable flags to adjust the output format like --json, --table etc",
"default": false
},
"display_flag": {
"type": "boolean",
"description": "Enables the --display flag",
"default": false
},
"batch_flags": {
"type": "boolean",
"description": "Enables the --batch and --batch-sleep flags",
"default": false
},
"arguments": {
"type": "array",
"description": "List or arguments to accept after the command name",
"items": {
"$ref": "#/definitions/generic_argument"
}
},
"flags": {
"type": "array",
"description": "List of flags to add to the command",
"items": {
"allOf": [
{ "$ref":"#/definitions/generic_flag"},
{
"type": "object",
"properties": {
"reply_filter":{
"type": "string",
"description": "Choria reply filter"
}
}
}
]
}
}
}
}
]
}
},
"properties": {
"name": {
"description": "A unique name for this application",
"$ref": "#/definitions/shortname"
},
"description": {
"$ref": "#/definitions/description"
},
"version": {
"$ref": "#/definitions/semver"
},
"author": {
"type": "string",
"description": "Contact details for the author",
"minLength": 1
},
"commands": {
"description": "A list of commands that make up the application",
"minItems": 1,
"$ref": "#/definitions/commands"
}
}
}
1 change: 1 addition & 0 deletions internal/fs/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
//go:embed plugin
//go:embed misc
//go:embed completion
//go:embed schemas
var FS embed.FS

type consoleRender interface {
Expand Down
Loading

0 comments on commit e8878bd

Please sign in to comment.