Gohan provides various utitliy commands.
Run gohan -h
to list available commands
NAME:
gohan - Gohan
USAGE:
gohan [global options] command [command options] [arguments...]
COMMANDS:
client Manage Gohan resources
validate, v Validate document
init-db, idb Initialize DB backend with given schema file
convert, conv Convert DB
server, srv Run API Server
test_extensions, test_ex Run extension tests
migrate, mig Generate goose migration script
template, template Convert gohan schema using pongo2 template
run, run Run Gohan script Code
test, test Run Gohan script Test
openapi, openapi Convert gohan schema to OpenAPI
markdown, markdown Convert gohan schema to markdown doc
dot, dot Convert gohan schema to dot file for graphviz
glace-server, gsrv Run API Server with graceful restart support
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--debug, -d Show debug messages
--help, -h show help
--version, -v print the version
NAME:
validate - Validate Json Schema file
USAGE:
command validate [command options] [arguments...]
DESCRIPTION:
OPTIONS:
--schema, -s '../schema/core.json' Json schema path
--json, -i '../example/example.json' json path
NAME:
template - Convert gohan schema using pongo2 template
USAGE:
command template [command options] [arguments...]
DESCRIPTION:
Convert gohan schema using pongo2 template
OPTIONS:
--config-file "gohan.yaml" Server config File
--template, -t Template File
NAME:
openapi - Convert gohan schema to OpenAPI
USAGE:
command openapi [command options] [arguments...]
DESCRIPTION:
Convert gohan schema to OpenAPI
OPTIONS:
--config-file "gohan.yaml" Server config File
--template, -t "embed://etc/templates/openapi.tmpl" Template File
--split-by-resource-group "" Group by resource
--policy "admin" Show only schema with chosen policy
--scope ["tenant", "domain", "admin"] Show only schema with chosen token scopes. No scope flag will convert API with Keystone v2 policy.
--version "0.1" Version of the API
--title "gohan API" Title of the API
--description "" Description of the API
NAME:
markdown - Convert gohan schema using pongo2 template
USAGE:
command markdown [command options] [arguments...]
DESCRIPTION:
Convert gohan schema using pongo2 template
OPTIONS:
--config-file "gohan.yaml" Server config File
--template, -t "embed://etc/templates/markdown.tmpl" Template File
--split-by-resource-group "" Group by resource
--policy "admin" Show only schema with chosen policy
You can use gohan client command to connect to gohan.
Gohan client will show quick help for sub command for current server schema.
Gohan CLI Client is configured though environment variables. Configuration can be divided into few sections. You can use default configuration for client with: source ./etc/gohan_client.rc
To configure keystone access for Gohan Client CLI, only few options should be set (they are compatible with those from gophercloud/gophercloud:
OS_AUTH_URL
- keystone urlOS_USERNAME
- keystone usernameOS_PASSWORD
- keystone passwordOS_TENANT_NAME
orOS_TENANT_ID
- keystone tenant name or idOS_DOMAIN_NAME
orOS_DOMAIN_ID
- keystone domain name or id
Gohan enpoint url can be specified directly or Gohan Client can get it from configured keystone.
To specify endpoint directly, set GOHAN_ENDPOINT_URL
to proper url.
When using keystone:
GOHAN_SERVICE_NAME
- Gohan service name in keystoneGOHAN_REGION
- Gohan region name in keystone
Note: setting all above options will result in using GOHAN_ENDPOINT_URL
!
Gohan CLI Client is fetching available schemas from Gohan endpoint and can cache them in temp file for performance:
GOHAN_SCHEMA_URL
- Gohan schema urlGOHAN_CACHE_SCHEMAS
- should cache schemas (default - true)GOHAN_CACHE_TIMEOUT
- how long cache is valid, uses 1h20m10s format (default - 5m)GOHAN_CACHE_PATH
- where to store cache schemas (default -/tmp/.cached_gohan_schemas
)
Usage can be briefly described with:
gohan client schema_id command [arguments...] [resource_identifier]
Each part of above command is described below.
schema_id
determines which resource type we want to manage.
If used schema_id
is not defined in Gohan, Gohan CLI Client will return Command not found
error.
Commands are identical for each resources:
list
- List all resourcesshow
- Show resource detailscreate
- Create resourceset
- Update existing resourcedelete
- Delete resource
Arguments should be specified in --name value
format.
Passing JSON null value --name "<null>"
Passing JSON not null value --name '{"name": [{"name": "value"}, {"name": "value"}]}'
In addition to resource related commands, some formatting commands are available:
-
--output-format [json/table]
- specifies in which format results should be shown. Can also be specified with :code:GOHAN_OUTPUT_FORMAT
environment variable.json
, e.g:
{
"name": "Resource name",
"description": "Resource very long and meaningful description",
"some_list": [
"list_element_1",
"list_element_2"
]
}
..
- :code:
table
, e.g:
+-------------+--------------------------------------+
| FIELD | TYPE |
+-------------+--------------------------------------+
| name | Resource name |
| description | Resource description |
| some_list | ["list_element_1", "list_element_2"] |
+-------------+--------------------------------------+
-
:code:
--verbosity [0-3]
- specifies how much information Gohan Client should show - handy for debugging. Can also be specified with :code:GOHAN_VERBOSITY
environment variable.- :code:
0
- no additional debug information is shown - :code:
1
- Sent request url and method is shown - :code:
2
- same as level :code:1
+ request & response body - :code:
3
- same as level :code:2
+ used auth token
- :code:
-
:code:
--fields [field1,field2,field3]
- specifies which fields Gohan Client should show - handy for filtering out unwanted data. Can also be specified with :code:GOHAN_FIELDS
environment variable.
Some commands (:code:show, set, delete
) are executed on one resource only. To identify whis reource,
it's name or id could be used:
gohan client network show network-id
gohan client network show "Network Name"
gohan client subnet create --network "Network Name"
gohan client subnet create --network network-id
gohan client subnet create --network_id network-id
Any custom actions specified in schema are also supported as commands by gohan client and should be invoked as follows:
gohan client schema_id command [common arguments] [command input] [resource identifier]
Where common arguments
and resource identifier
are described aboved and command input
is passed as JSON value.
Gohan stores an event log recording create, update and delete database operations. This is done in the database transaction, so we can assume that this event log data is consistent with the resource data.
The event log data contains the following information. (see schema in gohan.json)
- id -- an unique ID of the event
- type -- the type of the event
- path -- the path of the resource related to the event
- timestamp -- the time at which the event occurred
- version -- the version of the resource after this event occurred
- body -- the contents of the resource after this event occurred
The Gohan server will select one master node using the etcd backend CAS API. Only the master node will then poll the event log table, pushing to the backend.
We may support mysql binlog api for better performance in future.
Gohan will keep track of the state version of any resource associated to
a schema with metadata containing the key state_versioning
set to
true
. In such a case Gohan will remember the config version and
the state version of the resource. During creation the config version of
such a resource will be set to 1
. On delete and update the version is
bumped by one. The state version is 0
originally and later read from
the sync backend and updated asynchronously. Both the versions are returned
in GET requests, together with additional information about the state.
For example say a simplistic resource with the following schema is created:
- description: Just a named object
id: named_object
parent: ""
metadata:
state_versioning: true
singular: named_object
plural: named_object
prefix: /v1.0
schema:
properties:
name:
default: ""
permission:
- create
- update
title: Name
type: string
unique: false
id:
permission:
- create
title: ID
type: string
format: uuid
properties_order:
- id
- name
required:
- name
type: object
title: Named Object
and the name
is set to Alice
. Then Gohan, through the standard event sync,
writes the following JSON object to the backend under the key
config/v1.0/named_object/someGeneratedUuid
:
{
"body": {
"id": "someGeneratedUuid",
"name": "Alice"
},
"version": 1
}
A worker program might now read this information, create a corresponding
southbound resource and write the following to the backend under the key
state/v1.0/named_object/someGeneratedUuid
:
{
"version": 1,
"error": "",
"state": "Alice exists"
}
Gohan will read this information and update the database accordingly.
Any state updates made when the state version already equals the config version will be ignored.
After a resource has been created in the southbound, one might monitor its
status. This is done using a very similar approach to status updates.
Monitoring updates the monitoring
field in the database, which is returned
together with the rest of the state.
A continuation of the above example follows. After the resource has been created
in the southbound a worker program might monitor its status and then write
the result of this monitoring under the key
monitoring/v1.0/named_object/someGeneratedUuid
as the following JSON:
{
"version": 1,
"monitoring": "Alice is well"
}
Gohan will read this information and update the database accordingly.
Any monitoring updates made when the state version does not yet equal the config version or the version in the JSON data doesn't match with the config version will be ignored.
Gohan has another way to handle data reported from sync layer. Gohan
will watch sync keys with prefix then if its key's creation/update/deletion
happens, gohan will occur notification
type event with action and data.
Sync keys and event path can be configured in gohan.yaml
configuration file like:
watch:
keys:
- /v2.0/servers
- /v2.0/systems
events:
- v2.0
With an above configuration example, gohan will watch the updates of sync keys including
/v2.0/servers
and /v2.0/systems
as an prefix. If gohan detected some changes,
emitted events can be handled by gohan extension by configuring following extensions configuration,
for example:
extensions:
- id: sync_watch_handler
path: "v2.0"
url: ./handler.js
In Gohan HA environment, watched keys are load-balanced among working gohan instances. Even if new gohan instance is added or some gohan instance is stopped, each gohan will automatically detect instance addition and deletion then watched keys are automatically reballanced.
gohan migrate command is a simple wrapper for goose command. Using gohan migrate command, you can use gohan configuration to manage goose based db migraion. gohan create command will genenarete initial goose file using schema.
NAME:
gohan migrate - Manage migrations
USAGE:
gohan migrate [global options] command [command options] [arguments...]
VERSION:
a71c59f8f5e0f0b17957e1c9901e89b99a93b81d
COMMANDS:
up Migrate to the most recent version
up-by-one Migrate one version up
create Create a template for a new migration
initial, init Generate initial goose migration script from schema
down Migrate to the oldest version
redo Migrate one version back
status Display migration status
version Display migration version
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
gohan generate command generates server side code. The idea is to genearate code which is fastest as possible.
- Use echo framework which is fastest web framework in golang in early 2017
- Trying to minimize use of interface
- Use sqlboilar OR mapping framework SQLBoilar SQLBoilar framework generates ORM code from table schema. This is fastest ORM solution for golang in early 2017 accoding to benchmark.
- Generate JSON marshal function
You can also change generated code providing custom template.
NAME:
generate - Generate ServerSide Code
USAGE:
command generate [command options] [arguments...]
OPTIONS:
--template, -t Application template path
--templates Template configuration
--config-file, -c "./gohan.yaml" Gohan config file
--output, -o "." Dir of output
--package, -p "gen" Package Name
--dbname, -d "gohan" DB Name
--resetdb Reset Database on create
This command requires mysql setup, and generated code would work with only MySQL.
Setup mysql
Prepare gohan.yaml with MySQL configuration
Write template configuration files.
type can be all, group or resource. If type is all, all schema would be included in to a single file. If type is resource, we will generate files for each resources. If type is group, we will generate files for each resources groups.
You can control generated filename using output_path. output_path may contrain "resource", and this identifire would be substituted by actual schema id.
- type: all
template_path: server.tmpl
output_path: base_controller.go
- type: resource
template_path: controller.tmpl
output_path: __resource___controller.go
Prepare main.go file
package main
import (
"./gen"
_ "github.com/go-sql-driver/mysql"
)
func main() {
configFile := "./gohan.yaml"
gen.RunServer(configFile, nil)
}
You can add custom logic by providing own controller struct using embed struct.
type Controller struct {
gen.BaseController
DB *sql.DB
}
func (controller *Controller) CreateUser(c echo.Context) error {
// Custom Logic
}
//Route setup routes
func (controller *Controller) Routes() map[string]*gen.Handler {
routes := controller.BaseController.Routes()
routes["/ccc/users"].POST = controller.CreateUser
return routes
}
//Route setup routes
func (controller *Controller) SetDB(db *sql.DB) {
controller.BaseController.SetDB(db)
controller.DB = db
}