chatterbox
is a tool to define restful conversations with a
generic endpoint.
You can define scenarios with a json formalism describing conversations between the client (chatterbox) and the endpoint.
In polling mode, you can drop scenario files into a directory monitored
by chatterbox
and see them being consumed by the tool.
Every time a new scenario is placed within the directory, chatterbox
parses it and then generates the conversation(s) against the endpoint(s).
Once the scenario has been processed, the file is deleted or optionally
moved into ${directory}/consumed
.
chatterbox
embeds V8 the Google’s open source
high-performance JavaScript and WebAssembly engine.
This allows the user to define scenarios in a dynamic way. For example, the user could choose to compute the value of a certain rest-call's property as the result of a user defined JavaScript function.
More use cases could benefit from scripting capabilities and these could be evaluated in the future as the tool evolves.
Currently, chatterbox
can be solely built under Linux.
If you intend to build the chatterbox
binary directly on your Linux
distribution, ensure your system provides:
Make
,AutoGen
GCC
withg++
CMake
Ninja
Git
curl
First, ensure you have checked out all the chatterbox
's submodules:
git submodule init
git submodule update
Build the chatterbox
binary alongside with all its dependencies:
cd scripts
./build.sh build-all
It is possible to use a Dockerfile builder image to compile the binary
of chatterbox
.
scripts/Dockerfile.builder
To build chatterbox
with a Dockerfile builder image, your system needs
to provide Podman or Docker.
To create the chatterbox
builder image:
cd scripts
./build.sh builder-create
$ podman images
REPOSITORY TAG
localhost/chatterbox-builder latest
With this image, it is possible to build the chatterbox
binary:
cd scripts
./build.sh builder-build
Once you have built the chatterbox
binary, you can create the
final consumable chatterbox image:
cd scripts
./build.sh chatterbox-create
$ podman images
REPOSITORY TAG
localhost/chatterbox latest
You typically want to write your scenarios on files and then submit them to
chatterbox
.
Once you have your scenario ready, you can submit it to chatterbox
with:
chatterbox -i scenario.json
You can specify indifferently a relative or an absolute path. If you want, you can also specify a relative path from where files are read.
chatterbox -p /scenarios -i scenario.json
You can use chatterbox
to monitor a directory on filesystem.
On this mode, chatterbox
will constantly check the monitored directory
for new scenarios.
$ chatterbox -p /scenarios -m
>>MONITORING MODE<<
By default, files are moved into ${directory}/consumed
once they have
been consumed. If you prefer them to be deleted you can specify the -d
flag.
The conversation scenario format is pretty straightforward: it is a json defining properties for the conversations you want to realize.
At the root level, or scenario level, you define an array of conversations
:
{
"conversations": [
{
"host" : "http://service1.host1.domain1",
"conversation": []
},
{
"host" : "https://service2.host2.domain2",
"conversation": []
}
]
}
This means that the tool is able to issue a set of restful calls against multiple endpoints.
A conversation
is defined as an array of talk
(s):
{
"conversation": [
{
"for" : 1,
"talk" : {
"auth" : "aws_v4",
"verb" : "GET",
"uri" : "foo",
"query_string" : "param=value",
}
},
{
"for" : 4,
"talk" : {
"auth" : "aws_v2",
"verb" : "HEAD",
"uri" : "bar",
"query_string" : "param=value",
}
}
]
}
A talk
describes a single HTTP
call.
You can repeat a talk
for n
times specifying the for
attribute
in the talk's context.
Every time a scenario runs, a brand new JavaScript context is spawned
into V8
engine and it lasts for the whole scenario's lifespan.
Generally speaking, attributes can be scripted defining JavaScript functions that are executed into the scenario's JavaScript context.
For example, the query_string
attribute of a talk could be defined as this:
{
"talk" : {
"auth" : "aws_v2",
"verb" : "HEAD",
"uri" : "bar",
"query_string" : {
"function": "GetQueryString",
"args": ["foo", "bar"]
},
}
}
When the scenario runs, the query_string
attribute's value is
evaluated as a JavaScript function named: GetQueryString
taking 2 string parameters valued respectively with foo
and bar
.
The GetQueryString
function must be defined inside a file with
extension .js
and placed into the directory checked by chatterbox
.
function GetQueryString(p1, p2) {
log("inf", "GetQueryString", "Invoked with: " + p1 + "," + p2);
return p1+p2;
}
A simple S3 conversation where the client creates a bucket: foobar
and then
checks that the newly created bucket actually exists.
- Input conversation
{
"conversations": [
{
"host" : "s3gw.127.0.0.1.omg.howdoi.website:7480",
"s3_access_key" : "test",
"s3_secret_key" : "test",
"service" : "s3",
"conversation": [
{
"for" : 1,
"talk" : {
"auth" : "aws_v4",
"verb" : "PUT",
"uri" : "foo",
"query_string" : "format=json",
"res_body_dump" : true,
"res_body_format" : "json"
}
},
{
"for" : 1,
"talk" : {
"auth" : "aws_v4",
"verb" : "HEAD",
"uri" : "foo",
"query_string" : "format=json",
"res_body_dump" : true,
"res_body_format" : "json"
}
}
]
}
]
}
- Output rendered conversation
{
"conversations":[
{
"host":"s3gw.127.0.0.1.omg.howdoi.website:7480",
"conversation":[
{
"talk":{
"auth":"aws_v4",
"data":"",
"query_string":"format=json",
"uri":"foobar",
"verb":"PUT"
},
"res_body":null,
"res_code":200
},
{
"talk":{
"auth":"aws_v4",
"data":"",
"query_string":"format=json",
"uri":"foobar",
"verb":"HEAD"
},
"res_body":null,
"res_code":200
}
],
"s3_access_key":"test",
"s3_secret_key":"test",
"service":"s3"
}
]
}