Ephemerald manages pools of short-lived servers to be used for testing purposes. It was built to allow paralallel integration tests.
It has REST API for accessing server instances from any language and comes with a built-in go client. See the examples directory for example configurations and client usage.
The ephemerald server can run on a remote host; container connection parameters are rewritten so that the client connects to the right place. This way ephemerald can run on a large server and be used from less powerful development machines.
To run the server, supply a configuration file:
$ ephemerald -c config.yamlPress Q to quit the server.
--helpprint help message.-p <port>changes the listen port. Defaults to 6000--ui streamwill dump the event steam to the console in lieu of a curses-esque UI.--ui nonewill not print any UI information (useful with--log-file /dev/stdout)--log-file <path>write logs to file atpath. Defaults to/dev/null--log-level <level>log level. defaults toinfo. Options aredebug,info,warn,error
Note: use Ctrl-C to stop the server wen not in --ui tui mode (SIGINT,SIGQUIT always work too)
For example, to see only log messages (at debug level) use:
$ ephememerald --ui none --log-level debug --log-file /dev/stdout -c config.yamlContainer pools are configured in a yaml (or json) file. Each pool has options for the container parameters and for lifecycle actions.
The following configuration creates a single pool called "pg" which maintains five containers from the "postgres" image and
exposes port 5432 to clients. See the params and actions below for documentation on those fields.
pools:
pg:
image: postgres
size: 5
port: 5432
params:
username: postgres
database: postgres
url: postgres://{{.Username}}:@{{.Hostname}}:{{.Port}}/{{.Database}}?sslmode=disable
actions:
healthcheck:
type: postgres.ping
retries: 10
delay: 50ms
initialize:
type: exec
path: make
args: [ 'db:migrate' ]
env: [ 'DATABASE_URL={{.Url}}' ]
timeout: 10s
reset:
type: postgres.truncateSee example/config.yaml for a full working configuration.
The params entry allows for declaring parameters needed for connecting to the service. There are three fields
with arbitrary values: username, password, database.
The url can be a golang template and will be executed with access to the following fields:
| Name | Value |
|---|---|
| Hostname | The hostname that the container can be connected at |
| Port | The (automatically-generated) port number that is mapped to the exposed container port |
| Username | The username field declared in params |
| Password | The password field declared in params |
| Database | The database field declared in params |
A params section for postgres may look like this:
username: postgres
database: postgres
url: postgres://{{.Username}}:{{.Password}}@{{.Hostname}}:{{.Port}}/{{.Database}}?sslmode=disableThe container section is passed-through to docker when creating the container. The available
options are:
- labels
- env
- cmd
- volumes
- entrypoint
- user
- capadd
- capdrop
There are three lifecycle actions: healthcheck, initialize, and reset.
healthcheckis used to determine when the container is ready to be used.initializeis used to initialize the container (run migrations, etc...)resetmay be used to revert the container to a state where it can be used again.
All of them are optional (though healthcheck should be used). If reset is not given,
the container will be killed and a new one will be created to replace it.
Each action has, at a minimum, the following three parameters:
| Name | Default | Description |
|---|---|---|
| retries | 3 | number of times to retry the action |
| timeout | 1s | amount of time to allow for the action |
| delay | 500ms | amount of time to delay before retrying |
timeout and delay are durations; they must have a unit suffix as described here.
Note: actions may have different defaults for these fields.
Does nothing. Useful as the reset action so that a container is always reused.
Execute a command on the host operating system. Useful for running migrations to initialize a database.
Extra Parameters:
| Name | Default | Description |
|---|---|---|
| command | "" |
command to execute |
| args | [] |
command-line arguments |
| env | [] |
environment variables |
| dir | "" |
directory to execute in. |
The env entries may be templates with access to the same fields as the params url template. Additionally,
the following environment variables are always set:
EPHEMERALD_IDEPHEMERALD_HOSTNAMEEPHEMERALD_PORTEPHEMERALD_USERNAMEEPHEMERALD_PASSWORDEPHEMERALD_DATABASEEPHEMERALD_URL
If dir is not set, the working directory of the server isused.
Run a HTTP GET request.
Extra Parameters:
| Name | Default | Description |
|---|---|---|
| url | "" |
url to request |
If url is blank, the url from the params is used.
If url is not blank, it may be a template which has access to the same fields that params url template does.
Connect to the exposed container port over TCP.
Executes a query on the database.
Extra Parameters:
| Name | Default | Description |
|---|---|---|
| command | "SELECT 1=1" |
query to execute |
| args | [] |
values to be escaped with positional arguments in command. |
Example:
type: postgres.exec
command: 'INSERT INTO users (name) VALUES ($1)'
args: "Robert'); DROP TABLE STUDENTS;--"Pings the database. Useful for healthcheck.
Runs TRUNCATE TABLE x CASCADE for all tables x.
Extra Parameters:
| Name | Default | Description |
|---|---|---|
| exclude | [] |
an array of table names to not truncate (eg migration versions) |
Execute a redis command.
Extra Parameters:
| Name | Default | Description |
|---|---|---|
| command | "PING" |
redis command to execute |
This is an alias for redis.exec.
This is an alias for redis.exec with a default command of "FLUSHALL".
There is a REST API for clients to checkout and return items from one or more pools.
POST /checkout/{pool} checks out an instance from the given pool and returns
that instance's parameters:
$ curl -s -XPOST localhost:6000/checkout/postgres | jq
{
"id":"8482c266192f013346d03f71b2aa6d4b647909e3502ac525039bdd0fe9fcac30",
"hostname":"localhost",
"port":"34031",
"username":"postgres",
"database":"postgres",
"url":"postgres://postgres:@localhost:34031/postgres?sslmode=disable"
}DELETE /return/{pool}/{id} returns the instance given by id to the pool pool:
$ curl -s -XDELETE localhost:6000/return/postgres/8482c266192f013346d03f71b2aa6d4b647909e3502ac525039bdd0fe9fcac30POST /checkout checks out an instance from every configured pool.
$ curl -s -XPOST localhost:6000/checkout | tee checkout.json | jq
{
"postgres": {
"id": "2dedf5dbe9cc8d7a0cd71ed75455c7310db79aea44925562b82c01b959d85e7e",
"hostname": "localhost",
"port": "34023",
"username": "postgres",
"database": "postgres",
"url": "postgres://postgres:@localhost:34023/postgres?sslmode=disable"
},
"redis": {
"id": "a8dbf5043c7145510f48ccffa6f1e20b9f2c8140dda73d567a29dc2ec823ca46",
"hostname": "localhost",
"port": "34019",
"database": "0",
"url": "redis://localhost:34019/0"
},
"vault": {
"id": "11f4752d5e0b762c65b05809c9500a6e0a20ee4a79b861638a084adf77dbfb78",
"hostname": "localhost",
"port": "34021",
"url": "http://localhost:34021"
}
}DELETE /return returns multiple instances at once. Meant to be used with batch checkout.
$ cat checkout.json
{
"postgres": {
"id": "2dedf5dbe9cc8d7a0cd71ed75455c7310db79aea44925562b82c01b959d85e7e"
},
"redis": {
"id": "a8dbf5043c7145510f48ccffa6f1e20b9f2c8140dda73d567a29dc2ec823ca46"
},
"vault": {
"id": "11f4752d5e0b762c65b05809c9500a6e0a20ee4a79b861638a084adf77dbfb78"
}
}
$ curl -XDELETE -H'Content-Type: application/json' -d @checkout.json localhost:6000/returnNote that the complete response from batch checkout may be sent. The only requirement is the id field for each pool instance.
$ govendor get -d github.com/boz/ephemerald/...
$ cd $GOPATH/src/github.com/boz/ephemerald
$ make server exampleRun the example server and client in separate terminals
$ ./ephemerald/ephemerald -c _example/config.yaml$ ./_example/exampleFollow the building steps then run make install:
$ make installDownload the latest release for your system. Unpack the archive and put the binary in your path.
$ release="https://github.com/boz/ephemerald/releases/download/v0.3.1/ephemerald_Linux_x86_64.tar.gz"
$ curl -L "$release" | tar -C /tmp -zxv
$ /tmp/ephemerald -c config.yaml$ brew install boz/repo/ephemerald
- Configuration
- Current parsing is a disaster
- Allow yaml
- Allow built-in defaults (postgres, redis, etc...)
- Polish/Optimize/Cleanup/Refactor UI.
- Re-add remote actions (websockets API)
- Clients: nodejs, ruby, python, etc...
- Documentation
- Tests