EXEd is an api service which provide remote execute (including code release) on top of exector plugins (e.g.: ansible/salt plugin).
Usage | Type | Value |
---|---|---|
Job State Done | int | 0 |
Job State Running | int | 1 |
Job State Failure | int | 2 |
Operate State OK | int | 0 |
Operate State Skiped | int | 1 |
Operate State Failed | int | 2 |
Operate State Unreachable | int | 3 |
Operate State Changed | int | 4 |
Service State Started | int | 0 |
Service State Stoped | int | 1 |
Service State Restarted | int | 2 |
- Job State for async job.
- Operate State for executor task.
- Service State for service api endpoint.
Flags | Usage | Default |
---|---|---|
-h/--help | show usage | - |
-v/--version | show version | - |
-c/--conf | path to config file | ${cwd}/exed.conf |
-d/--daemon | run as daemon | run frontground |
--exe-conf | celery worker ext args | - |
Opts | Section | Usage | Default |
---|---|---|---|
listen | api | api listen address | 127.0.0.1 |
listen_port | api | api listen port | 16808 |
pid_file | api | api server pidfile | - (no pidfile) |
executor | runner | executor plugin | ansible |
concurrency | runner | celery concurrency | ${nproc} |
redis_url | runner | redis connection info | redis://127.0.0.1:6379 |
broker_url | runner | rmq connection info | amqp://guest:guest@localhost:5672// |
log_level | log | log level of exe server | debug |
error_log | log | error log path | - (stdout) |
access_log | log | access log path | - (stdout) |
- these options under log section doesn't affect celery worker.
Opts | Section | Usage | Default |
---|---|---|---|
workdir | ansible | ansible work dir | ${cwd} |
inventory | ansible | ansible inventory file/dir | inventory |
playbooks | ansible | ansible playbooks dir | playbooks |
sshkey | ansible | path to ssh private key file | - |
- when use ansible executor plugin, there should be an init pb named "_deploy.yml".
- the init pb should accept two vars: "_targets" and "_role".
$ pip install cherrypy six ansible "celery[redis]" # install packages
$ bin/exed -c etc/exed.conf -d # start the api server
$ celery worker -A exe.runner -l info --exe-conf etc/exed.conf # start the celery worker
- Before you do that, you should have rabbitmq/redis server deployed.
- Make sure both api/worker can access rabbitmq and redis server.
- Make sure your ansible (including playbooks and inventory) was on the same machine with both api/worker.
Endpoint | Usage | Supported method |
---|---|---|
/target${query_params} | Match and list remote hosts with given pattern | GET |
Endpoint | Usage | Supported method |
---|---|---|
/targets${query_params} | Match and list remote hosts with given pattern | GET |
/jobs/(jid)${query_params} | List all jobs or query specific job | GET |
/jobs/(jid) | Delete specific job | DELETE |
Endpoint | Usage | Supported method |
---|---|---|
/ping${query_params} | Ping remote host (block/sync mode) | GET |
/ping | Ping remote host(s) (non-block/async mode) | POST |
/facter${query_params} | Gather facter info of remote host (block/sync mode) | GET |
/facter | Gather facter info of remote host(s) (non-block/async mode) | POST |
/service${query_params} | Manipulate service on remote host (block/sync mode) | GET |
/service | Manipulate service on remote host(s) (non-block/async mode) | POST |
/execute${query_params} | Execute raw command on remote host (block/sync mode) | GET |
/execute | Execute raw command on remote host(s) (non-block/async mode) | POST |
/deploy | Deploy service/role/app on remote host(s) (non-block/async mode) | POST |
Endpoint | Usage | Supported method |
---|---|---|
/release | Gather release plugins info | GET |
/release | Gather released revision or release new revision on remote host(s) | POST |
-
The Remote API uses standard HTTP status codes to indicate the success or failure of the API call.
-
The body of the response will be JSON in the following format:
{ "message": "operate conflict" }
GET /target
Match and list remote hosts with given pattern, return json string array contain all matched hosts.
GET /target?pattern=karazhan.* HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
["karazhan.0ops.io", "karazhan...", ...]
- pattern: str, pattern use to match remote host fqdn. Default using '*' for match all hosts.
- 200 - no error
- 400 - bad request/parameter
- 500 - server error
GET /jobs
List current jobs, return json string array contain all jobs.
GET /jobs HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
["eb1f4035-d62b-497f-9e3f-543e8e6f15f3", "c4f6acd3-4dda-44d0-8f99-76b4587e55d0", ...]
- Those are Job IDs (jid)
- detail: 1/True/true or 0/False/false, show job detail of each jobs. Only jid(s) was returned by default.
- 200 - no error
- 400 - bad request/parameter
- 500 - server error
GET /jobs/(jid)
Query job by job ID.
GET /jobs/c4f6acd3-4dda-44d0-8f99-76b4587e55d0?outputs=1&follow=1 HTTP/1.1
HTTP/1.1 200 OK
Transfer-Encoding: chunked
{
"state": 0,
"error": "",
"startat": 1488272314,
"operate": "deploy",
"operate_args": {
"role": "nginx",
"partial": null",
"extra_vars": {}
},
"return_data": {},
"targets": [
"molten-core.0ops.io",
"karazhan.0ops.io"
]
{"molten-core.0ops.io": {"state": 4, ...}} (chunk)
{"karazhan.0ops.io": {"state": 4, ...}} (chunk)
}
- The server will using chunked transfer encoding when query with follow=1.
- The content of each chunk is depend on operate type of that job.
- outputs: 1/True/true or 0/False/false, show return data of each operations. Only Job State was returned by default.
- follow: 1/True/true or 0/False/false, show return data of each operations using follow mode (http chunked).
- 200 - no error
- 400 - bad request/parameter
- 404 - no such jobs
- 500 - server error
DELETE /jobs/(jid)
Delete job by job ID.
DELETE /jobs/eb1f4035-d62b-497f-9e3f-543e8e6f15f3 HTTP/1.1
HTTP/1.1 204 No Content
- 204 - no error
- 400 - bad request/parameter
- 404 - no such jobs
- 500 - server error
GET /ping
Ping remote host in block mode.
GET /ping?target=molten-core.0ops.io HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{"molten-core.0ops.io": {"status": 0}}
status 0 -> ok with nothing changed (see Consts/Enum
section for more details on operate state).
- target (required): fqdn of remote host to ping.
- 200 - no error
- 400 - bad request/parameter
- 404 - no such host
- 500 - server error
GET /facter
Gather facter info of remote host in block mode.
GET /facter?target=molten-core.0ops.io HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"molten-core.0ops.io": {
"state": 0,
"facter": {
(...facter json...)
}
}
}
again, state 0 means ok with nothing changed (see Consts/Enum
section for more details on operate state).
- target (required): fqdn of remote host to gather facter from.
- 200 - no error
- 400 - bad request/parameter
- 404 - no such host
- 500 - server error
GET /service
Manipulate service on remote host in block mode.
GET /service?target=molten-core.0ops.io&state=2&name=nginx&graceful=1 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{"molten-core.0ops.io": {"status": 4}}
state 4 means ok with something changed (see Consts/Enum
section for more details on operate state).
- target (required): fqdn of remote host to gather facter from.
- state (required): operate type (see
Consts/Enum
section for more details on service state enum) - name (required): service name.
- graceful: 1/True/true or 0/False/false, do graceful restart (reload) when state is restarted. Default is false.
- 200 - no error
- 400 - bad request/parameter
- 404 - no such host
- 500 - server error
GET /execute
Execute RAW Command on remote host in block mode.
GET /execute?target=molten-core.0ops.io&cmd=ifconfig HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"molten-core.0ops.io": {
"status": 4,
"rtc": 0,
"stderr": "",
"stdout": "(...output of ifconfig...)"
}
}
state 4 means ok with something changed (see Consts/Enum
section for more details on operate state).
- target (required): fqdn of remote host to gather facter from.
- cmd (required): command to run on remote host
- 200 - no error
- 400 - bad request/parameter
- 404 - no such host
- 500 - server error
POST /deploy
Deploy service/role/app on remote host(s), only support async mode.
POST /deploy HTTP/1.1
Content-Type: application/json
{
"targets": [
"molten-core.0ops.io",
"karazhan.0ops.io",
],
"role": "nginx",
"partial": "reconfig",
"extra_vars": {
"upstreams": [
"127.0.0.1:8080",
"127.0.0.1:8081"
],
"server_name": "exe.0ops.io"
}
}
HTTP/1.1 201 Create
Content-Type: application/json
{"jid": "c4f6acd3-4dda-44d0-8f99-76b4587e55d0"}
- Job in async mode (not only deploy) only return jid without block when job was created.
- EXEd doesn't known the detail about role/partial/extra_vars, it just pass them to the executor plugin, for this request, with ansible plugin, which means:
- There should be an ansible playbooks role with name nginx.
- Inside that role, there should be a tag with name reconfig.
- targets (required) - String array, remote hosts to deploy.
- role (required) - String, the role/app to deploy on remote hosts.
- partial - String, only deploy things marked by this tag.
- extra_vars - Object, vars which used by the role (e.g.: render config).
- 201 - job created
- 400 - bad parameter
- 500 - server error
POST /ping | /facter | /service | /execute
Do operate in non-block/async mode.
POST /service HTTP/1.1
Content-Type: application/json
{
"targets": [
"molten-core.0ops.io",
"karazhan.0ops.io",
],
"name": "ntp",
"state": 2,
"graceful": true,
}
HTTP/1.1 201 Create
Content-Type: application/json
{"jid": "eb1f4035-d62b-497f-9e3f-543e8e6f15f3"}
- All job in async mode only return jid without block when job was created.
- Those api have same parameters of their corresponding method in block/sync mode.
- The different here is async mode using POST with json data instead of GET with query string.
- 201 - job created
- 400 - bad request/parameter
- 500 - server error
GET /release
Gather release plugins info from server.
GET /release HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"type": "common",
"name": "common_release"
},
{
"type": "something_else",
"name": "yet_another_release"
}
]
- The server current have two release plugins loaded.
- 200 - no error
- 400 - bad request/parameter
- 500 - server error
POST /release
Release/Rollback/GatherRevision on remote host(s).
POST /release HTTP/1.1
Content-Type: application/json
{
"targets": [
"molten-core.0ops.io",
"karazhan.0ops.io"
],
"appname": "zerops",
"apptype": "common",
"revision": "1cc5aae96d61fd491f6dc626a06e3d3b792182b1",
"rollback": false,
"extra_opts": {
"giturl": "[email protected]:whisperaven/0ops.git",
"concurrency": 1,
"graceful_reload": false,
(...options...)
}
}
HTTP/1.1 201 Create
Content-Type: application/json
{"jid": "c4f6acd3-4dda-44d0-8f99-76b4587e55d0"}
- Every Job in async mode (including ping/facter/service/etc.) only return jid without block when job was created.
- EXEd doesn't care about the detail of release, it just pass args to the release plugin, for this request, means:
- There should be an release plugin with __RHANDLER_TYPE__ = "common" defined.
- The release method of that plugin will invoked like this: release(revison, **extra_opts).
- When rollback is true, the rollback method of that plugin will invoked like this: rollback(revision, **extra_opts).
- When revision is ?, the revision method of that plugin will invoked like this: revision(**extra_opts)
- targets (required) - String array, remote hosts to release.
- appname (required) - String, name of app to release.
- apptype (required) - String, type of release plugin to use.
- revision (required) - String, the revision to release/rollback.
- extra_opts - Object, extra options to the release/rollback/revision method of release plugin.