It allows to use declarative language (yaml) to talk to APIs and to save the response for future calls.
The main use case is to talk to HashiCorp Vault API.
It is heavily based on Tavern-ci
pip install yapi-ci
For this example we will use http://httpbin.org/put as VAULT_ADDR, this service will echo everything we send plus extra information about our request.
---
stages:
- name: 01-Init Vaultrequest:
url: "{env_vars.VAULT_ADDR}"method: PUTjson:
secret_shares: 1secret_threshold: 1mykeys:
- 7f921414b13ad05eb844dc349423765d857e8175b48c5854ada0e24e96924ac2response:
status_code: 200save:
$ext:
function: extensions.save_responseextra_kwargs:
path: "examples/data/{env_vars.VAULT_CLUSTER}/init.json"body:
headers: headersjson_keys_list: json.mykeysjson_secret_shares: json.secret_sharesjson_full: json
- name: 02-Unseal Vaultrequest:
url: "{env_vars.VAULT_ADDR}"method: PUTjson:
mykeys: "ext.json.mykeys.to_list()"myheaders: "resp.headers.to_dict()"json_keys_list: "resp.json_keys_list.to_list()[0]"json_secret_shares: "test string {resp.json_secret_shares}"json_full: "resp.json_full.to_dict()"$ext:
function: extensions.read_jsonextra_kwargs:
path: "examples/data/{env_vars.VAULT_CLUSTER}/init.json"sub_vars: Trueresponse:
status_code: 200save:
$ext:
function: extensions.save_responseextra_kwargs:
path: "examples/data/{env_vars.VAULT_CLUSTER}/unsealed_response.json"env_vars.VAULT_ADDRwill be replaced by the enviromental variable$VAULT_ADDRas is the same with all variables starting withenv_vars.- Do a
GETcall tourl - The json sent to the API will be:
{
"mykeys": [
"7f921414b13ad05eb844dc349423765d857e8175b48c5854ada0e24e96924ac2"
],
"secret_shares": 1,
"secret_threshold": 1
}- It expects a HTTP response of
200or it will error out. - It will save the output of the response as a json file under
data/{env_vars.VAULT_CLUSTER}/init.json - It will try to convert the response to json and save them in variables for the next stage:
response:
...body:
headers: headersjson_keys_list: json.mykeysjson_secret_shares: json.secret_sharesjson_full: json- Replace replace variables that start with
{env_vars.}with environmental variables. - Insert the variables saved in previous stages from
resp.converting them to a python dictionary or list depending if we want a json object or array. - Variables that have
{}are used toformatthe string instead of replacing it with its value.
json:
mykeys: "ext.json.mykeys.to_list()"myheaders: "resp.headers.to_dict()"json_keys_list: "resp.json_keys_list.to_list()[0]"json_secret_shares: "test string {resp.json_secret_shares}"json_full: "resp.json_full.to_dict()"- Read
data/{env_vars.VAULT_CLUSTER}/init.jsonand replace variables that start withext.in the body with data from the json whensub_varsis set toTrue.
"json": {
"mykeys": [
"7f921414b13ad05eb844dc349423765d857e8175b48c5854ada0e24e96924ac2"
],Becomes:
mykeys: "ext.json.mykeys.to_list()"- Do a
PUTcall tourl - With the json:
{
"json_full": {
"mykeys": [
"7f921414b13ad05eb844dc349423765d857e8175b48c5854ada0e24e96924ac2"
],
"secret_shares": 1,
"secret_threshold": 1
},
"json_keys_list": "7f921414b13ad05eb844dc349423765d857e8175b48c5854ada0e24e96924ac2",
"json_secret_shares": "test string 1",
"myheaders": {
"Accept-Encoding": "identity",
"Content-Length": "123",
"Content-Type": "application/json",
"Host": "httpbin.org"
},
"mykeys": [
"7f921414b13ad05eb844dc349423765d857e8175b48c5854ada0e24e96924ac2"
]
}- It will expect a
200response code or error out. - It will save the response to
data/{env_vars.VAULT_CLUSTER}/unsealed_response.json
- Add Automated testing
- Add version tagging
- Add package automatic building from tags