{% raw %}
Note: This function is experimental. Any APIs are subject to change.
Gohan script is an Ansible-like MACRO language for extending your Go code with MACRO functionality.
extensions:
- id: order
path: /v1.0/store/orders
code: |
tasks:
- when: event_type == "post_create_in_transaction"
blocks:
# Try debugger
# - debugger:
- db_get:
tx: $transaction
schema_id: pet
id: $resource.pet_id
register: pet
- when: pet.status != "available"
blocks:
- vars:
exception:
name: CustomException
code: 400
message: "Selected pet isn't available"
else:
- db_update:
tx: $transaction
schema_id: pet
data:
id: $resource.pet_id
status: "pending"
- when: event_type == "post_update_in_transaction"
blocks:
- when: resource.status == "approved"
blocks:
- db_update:
tx: $transaction
schema_id: pet
data:
id: $resource.pet_id
status: "sold"
vars:
world: "USA"
foods:
- apple
- orange
- banana
tasks:
- debug: var=$foods[2]
- debug: msg="Hello \" {{ world }}"
- blocks:
- debug: msg="I like {{ item }}"
with_items:
- apple
- orange
- banana
- debug: msg="I like {{ item }}"
with_items: $foods
# Unlike Ansible, We treat a value as identifier if a string value starts with "$"
# otherwise it is a value
- debug: msg="{{ item.key }} likes {{ item.value }}"
with_dict:
Alice: apple
Bob: orange
- debug: msg="This shouldn't be called"
when: 1 == 0
else:
- debug: msg="This should be called"
- fail: "failed"
when: 1 == 1
rescue:
- debug: msg="rescued {{ error }}"
always:
- debug: msg="Drink beer!"
- debug: msg="test {{ 1 == 1 }}"
- include: lib.yaml
vars:
local_vars: hello from imported code
see more detail on extension/gohanscript/test/core_test.yaml
You can run Gohan script code using this
gohan run ../examples/sample1.yaml
You can run list of tasks.
tasks:
- debug: msg="Hello World"
- debug: msg="This is gohan script"
save this file to hello_world.yaml.
$ gohan run hello_world.yaml
15:17:07.029 ▶ DEBUG hello_world.yaml:1: Hello World
15:17:07.029 ▶ DEBUG hello_world.yaml:2: This is gohan script
You can define variables using "vars".
tasks:
- vars:
place: "Earth"
person:
name: "John"
age: "30"
- debug: msg="Hello {{place}}"
- debug: var=$place
- debug: msg="Hello {{person.name}} "
- debug: var=$person.name
- debug: # show everything
Any string including "{{" get considered as django template. so you can use variables in their. if string start with $, it get considered as a variable identifier. (We are using pongo2 which supports subset of django template..)
$ gohan run variable.yaml
15:21:43.090 ▶ DEBUG variable.yaml:6 Hello Earth
15:21:43.091 ▶ DEBUG variable.yaml:7 Earth
15:21:43.091 ▶ DEBUG variable.yaml:8 Hello John
15:21:43.091 ▶ DEBUG variable.yaml:9 John
15:21:43.091 ▶ DEBUG variable.yaml:10 Dump vars
15:21:43.091 ▶ DEBUG person: map[name:John age:30]
15:21:43.091 ▶ DEBUG __file__: variable.yaml
15:21:43.091 ▶ DEBUG __dir__: .
15:21:43.091 ▶ DEBUG place: Earth
You can loop over the list item.
vars:
foods:
- apple
- orange
- banana
tasks:
- debug: msg="{{ item }}"
with_items:
- apple
- orange
- banana
- debug: msg="{{ item }}"
with_items: $foods
$ gohan run with_items.yaml
15:28:47.736 ▶ DEBUG with_items.yaml:6 apple
15:28:47.736 ▶ DEBUG with_items.yaml:6 orange
15:28:47.736 ▶ DEBUG with_items.yaml:6 banana
15:28:47.736 ▶ DEBUG with_items.yaml:11 apple
15:28:47.736 ▶ DEBUG with_items.yaml:11 orange
15:28:47.736 ▶ DEBUG with_items.yaml:11 banana
You can also loop over a dict.
vars:
person:
name: "John"
age: "30"
tasks:
- debug: msg="{{ item.key }} {{ item.value }}"
with_dict:
name: "John"
age: "30"
- debug: msg="{{ item.key }} {{ item.value }}"
with_dict: $person
$ gohan run with_items.yaml
15:32:42.513 ▶ DEBUG with_items.yaml:5 name John
15:32:42.513 ▶ DEBUG with_items.yaml:5 age 30
15:32:42.513 ▶ DEBUG with_items.yaml:9 name John
15:32:42.513 ▶ DEBUG with_items.yaml:9 age 30
tasks:
- vars:
result: ""
persons:
- name: Alice
hobbies:
- mailing
- reading
- name: Bob
hobbies:
- mailing
- running
- blocks:
- vars:
result: "{{result}}{{item}}"
with_items: $person.hobbies
with_items: $persons
loop_var: person
You can use "when" for conditional. You can use "else" blocks with "when".
vars:
number: 1
tasks:
- debug: msg="Should be called"
when: number == 1
- debug: msg="Should not be called"
when: number == 0
else:
- debug: msg="Should be called"
$ gohan run when.yaml
15:35:55.358 ▶ DEBUG when.yaml:3 Should be called
You can retry task.
- retry: how many times you will retry a task
- delay: how many seconds you will wait on next retry
tasks:
- fail: msg="Failed"
retry: 3
delay: 3
$ gohan run retry.yaml
15:43:35.720 ▶ WARNING error: tasks[0]: Failed
15:43:35.720 ▶ WARNING error: tasks[0]: Failed
Failed
You can group a set of tasks using blocks. blocks also supports loops, conditional and retries.
tasks:
- blocks:
- debug: msg="hello"
- debug: msg="from in block"
$ gohan run blocks.yaml
15:48:30.231 ▶ DEBUG blocks.yaml:2 hello
15:48:30.231 ▶ DEBUG blocks.yaml:3 from in block
You can change variable value using "register".
tasks:
- http_get: url=https://status.github.com/api/status.json
register: result
- debug: msg="{{result.contents.status}}"
$ gohan run register.yaml
15:51:11.005 ▶ DEBUG [register.yaml line:3 column:2] good
We support concurrent execution over a loop.
- worker: specify number of max workers
tasks:
- blocks:
- http_get: url="https://status.github.com/{{ item }}"
register: result
- debug: var=$result.raw_body
worker: 3
with_items:
- /api/status.json
- /api.json
- /api/last-message.json
$ gohan run worker.yaml
15:58:49.151 ▶ DEBUG worker.yaml:4 {"status_url":"https://status.github.com/api/status.json","messages_url":"https://status.github.com/api/messages.json","last_message_url":"https://status.github.com/api/last-message.json","daily_summary":"https://status.github.com/api/daily-summary.json"}
15:58:49.156 ▶ DEBUG worker.yaml:4 {"status":"good","body":"Everything operating normally.","created_on":"2016-03-03T22:03:59Z"}
15:58:49.156 ▶ DEBUG worker.yaml:4 {"status":"good","last_updated":"2016-03-08T23:58:27Z"}
You can also execute tasks in background.
tasks:
- background:
- sleep: 1000
- debug: msg="called 2"
- debug: msg="called 1"
- sleep: 2000
- debug: msg="called 3"
$ gohan run background.yaml
16:02:55.034 ▶ DEBUG background.yaml:6 called 1
16:02:56.038 ▶ DEBUG background.yaml:4 called 2
16:02:57.038 ▶ DEBUG background.yaml:8 called 3
You can define function using "define" task.
- name: name of function
- args: arguments
- body: body of code
tasks:
- define:
name: fib
args:
x: int
body:
- when: x < 2
return: x
- sub_int: a=$x b=1
register: $x
- fib:
x: $x
register: a
- sub_int: a=$x b=1
register: x
- fib:
x: $x
register: b
- add_int: a=$a b=$b
register: result
- return: result
- fib: x=10
register: result2
- debug: msg="result = {{result2}}"
you can use return task in function block.
$ gohan run fib.yaml
16:07:39.964 ▶ DEBUG fib.yaml:23 result = 55
You can include gohan script
tasks:
- include: lib.yaml
$ gohan run include.yaml
16:11:20.569 ▶ DEBUG lib.yaml:0 imported
You can set breakpoint using "debugger"
vars:
world: "USA"
foods:
- apple
- orange
- banana
tasks:
- debugger:
- debug: msg="Hello {{ world }}"
10:50:55.052 gohanscript INFO Debugger port: telnet localhost 40000
Supported command in debugger mode:
- s: step task
- n: next task
- r: return
- c: continue
- p: print current context
- p code: execute miniGo
- l: show current task
You will get separate port per go routine.
additional arguments will be stored in variable. If the value doesn't contain "=", it will be pushed to args. If the value contains "=", it get splitted for key and value and stored in flags.
tasks:
- debug: msg="{{ flags.greeting }} {{ args.0 }}"
$ gohan run args.yaml world greeting=hello
hello world
You can run gohan build-in test. gohan test code find test gohan code in the specified directory.
gohan test
vm := gohan.NewVM()
_, err := vm.RunFile("test/spec.yaml")
if err != nil {
t.Error(err)
}
You can auto generate adapter functions using ./extension/gohanscript/tools/gen.go.
go run ./extension/gohanscript/tools/gen.go genlib -t extension/gohanscript/templates/lib.tmpl -p github.com/cloudwan/gohan/extension/gohanscript/lib -e autogen -ep extension/gohanscript/autogen
please take a look
- extension/gohanscript/lib/tests
- extension/gohanscript/tests
{% endraw %}