In a service oriented architecture, an existing challenge is to manage running binaries, dependencies and networking. Orchestra's goal is to provide a unique place where you can run, stop, aggregate logs and config your Go binaries.
- Standalone: The first requirement is to provide support as a standalone tool, without external dependencies (apart from docker when using vendors). An optional flag will be provided to run the Go binaries inside a docker container.
- Rerun: Reload (build, test and run) services upon modification
- Vendors: Specify dependecies with existing services. Vendor software (e.g. postgres, rabbitmq, etc) will run inside Docker. This feature relies on
crane
. - Configuration: A global configuration file will be required to specify
ENV
variables for every service. An optional configuration file can be specified - Testing: Run unit tests and acceptance tests.
- Logging: Show aggregated logs for every service in the fleet.
- Reliability: Services started with Orchestra should operate atomically and in a reliable way. When Orchestra starts a service should check for the running processes, and match and kill services running outside this toolkit (e.g. running
go run main.go
inside a service folder or the./service
binary) - Scale: Services should be able to scale, by default the scale level is set to 1. A scale value can be set for every service inside their configuration file.
start
- rerun: uses rerun to run the services
- scale: overwrites the defined scale parameter
stop
restart
vendors
logs
ps
- The application will create a
.orchestra
folder in the directory (inside theGOPATH
) that we want to orchestrate. The purpose of this directoy is to provide the necessary context when running orchestra again. - The application can be run in every folder inside the
GOPATH
, e.g. let's assume that we have a single repo (calledmyservices
) with all the services in different folders, you can run orchestra inside that folder and it will recursively (withdepth=1
) look in every directory for a configuration file (i.e.service.yml
) and register the services. This approach works seamlessly with services split in multiple repositories in one GitHub account. - Logging is extremely important, and with great logging comes great responsibilities. For simplicity we'll redirect the output of a service into a file, then we use
github.com/ActiveState/tail
library to aggregate the logs of different services, maybe make them colorful and prefix them with the service name. - Code reload of Go binaries can be achieved using
github.com/skelterjohn/rerun
. It relies onfsnotify
and it watches for changes in the Go files. It can be possible, before every run, to run the tests again usinggo test
. I am considering of forking the project for the sake of better logging. - The application is a pure command-line toolkit, for this reason we may need commands, maybe subcommands and flags. For simplicity I intend to use the well known
github.com/codegangsta/cli
library. YAML
will be used as the standard format to store configuration files. In Go, a YAML parser is required,github.com/go-yaml/yaml
is my favorite option at the moment to marshal or unmarshal files.- An initialization process may be used to initialize a folder as an orchestra project. This may be a useful step to do some checks before start looking into all subdirectories and start running the binaries.