Project Configuration
edward.json
The edward.json file defines the services and groups that can be managed by Edward.
Edward will look for an edward.json file in the current working directory, and if not found there, it will look for edward.json in every parent directory to the root.
If no config file can be found, Edward will exit with an error and print usage information.
You can override this behavior with the --config
or -c
flag:
$ edward -c path/to/alternative.json list
Structure
An edward.json file at its core is a JSON document, containing an object with three array attributes:
{
"imports": [],
"groups": [],
"services": []
}
These attributes are all optional.
Services
A basic service consists of a name, a path in which to run the build and launch commands, and commands to perform the build and launch steps:
{
"name": "myservice",
"path": "path/to/myservice",
"commands": {
"build": "make install",
"launch": "myservice"
}
}
The service name is the name you will use to identify this service when calling Edward commands.
Names must be unique
Service and group names must be unique within your Edward config. If duplicates are found, Edward will exit with an error.
The path and each of the commands are optional. If no path is specified, Edward will run the commands in the current working directory. If a build command is omitted, only the launch script will be executed, and vice versa. This allows you to run pre-flight build steps common to many services, or start third-party applications you don’t need to build.
You can use environment variables in the path and commands:
{
"name": "myservice",
"path": "$HOME/src/myservice",
"commands": {
"launch": "myservice -key $MY_KEY"
}
}
However, you cannot use shell-specific constructs like piping (|
) or redirection (>
). For complex
build and launch operations, we recommend consolidating multiple commands into a separate script file.
Custom Stop Scripts
If you need to run a specific command to stop a service, you can add a stop command to the service definition:
{
"name": "myservice",
"commands": {
"launch": "myservice up",
"stop": "myservice down"
}
}
If this command fails, Edward will attempt to send a kill signal to the running service.
Detecting Successful Launch
When Edward starts a service, it will confirm that the service has started successfully before proceeding. By default, Edward will consider a service to have started if it is listening on one or more ports.
You can override this behavior by setting the launch_checks attribute for the service.
If your service will output a known piece of text to the console when it has finished startup, you can specify a log_text:
{
"name": "myservice",
...
"launch_checks": {
"log_text": "Finished startup"
}
}
In this case, once the text “Finished startup” appears in the console lot, Edward will deem the service to have started successfully.
Alternatively, you can specify a set of ports:
{
"name": "myservice",
...
"launch_checks": {
"ports": [8080, 8081]
}
}
And Edward will wait for all the listed ports to be open before considering the service started. When ports are specified, the process that opens them will not be taken into account.
You can also configure Edward to wait for a given amount of time (in ms) before considering a service as successfully started:
{
"name": "myservice",
...
"launch_checks": {
"wait": 500
}
}
If the service process exits before the end of this time, it will be considered to have failed.
Only one launch check may be used
Note that only one of these checks may be configured for a single service.
Environment Variables
To specify environment variables to be passed to a service, you can add the env attribute, which is an array of environment variables in the form KEY=VALUE
:
{
"name": "myservice",
...
"env": [
"ENV_VAR=value"
]
}
Platform-Specific Services
Some services need different configuration for different platforms. To make a service platform-specific, set the platform attribute.
It is permitted to have multiple services with the same name, provided they have different platforms.
The below example will create two instances of myservice: one for Mac OS (darwin) and one for Linux:
{
"name": "myservice",
...
"platform": "darwin"
},
{
"name": "myservice",
...
"platform": "linux"
}
“Warming Up” Services
Some services may do a portion of their setup on the first request they receive. To cut down on waiting time when working with such services, you can configure Edward to make a request to a URL after starting a service.
{
"name": "myservice",
...
"warmup": {
"url": "http://localhost:8080"
}
}
Requests to these URLs will happen in the background, and will not delay the starting of other services.
Autorestart (watch)
To save you running edward restart
every time you make a change to a service, you can configure a set of
directories to be monitored for changes. If a file in the specified directories changes, your service will
automatically be restarted.
{
"name": "myservice",
...
"watch": {
"include": ["dir1", "dir2"]
}
}
In the above example, changes in dir1 or dir2 will result in myservice being restarted.
You can also specify directories to be explicitly excluded:
{
"name": "myservice",
...
"watch": {
"include": ["dir1", "dir2"],
"exclude": ["dir1/exclude"]
}
}
If rebuilding the service fails, the existing running instance will not be stopped. Details of attempts to restart services can be found in the service logs.
Requiring Sudo
If a service needs sudo to run, it will need to be marked appropriately:
{
"name": "myservice",
"requiresSudo": true
}
If any service to be started/stopped/restarted requires sudo, Edward will trigger a prompt for the user’s password. This prompt is triggered through scripting, Edward itself will not have access to your password.
Groups
The groups array contains a list of group objects, each of which have a name and a list of children. A group’s children can be either services, or other groups.
{
"name": "mygroup",
"children": ["childgroup", "childservice"]
}
The above example specifies a group called mygroup with two children, childgroup and childservice.
You may also provide environment variables to be shared by the whole group, in the same format as for individual services:
{
"name": "mygroup",
"children": ["childgroup", "childservice"],
"env": [
"ENV_VAR=value"
]
}
Imports
The imports array is a list of other config files to be imported into this one:
"imports": ["import1.json", "path/to/import2.json"]
The paths to imports are relative to the parent edward.json
file. Imported config files may also import other
config files.
The combined configuration is validated after all imports have been loaded, so a group in one file may have as a child a service from another file, provided they are connected by an import in some way.
Versioning
If you are using features from a new version of Edward, and want to make sure that your config file can only be used by that version or higher, you can specify the edwardVersion setting in your config file:
{
"edwardVersion": "1.6.0",
"imports": [],
"groups": [],
"services": []
}
This will require that Edward version 1.6.0 or higher is installed in order to use your config file.