511 lines
11 KiB
Markdown
511 lines
11 KiB
Markdown
<a id="REST-API"></a>The Icinga Director REST API
|
|
=================================================
|
|
|
|
Introduction
|
|
------------
|
|
|
|
Icinga Director has been designed with a REST API in mind. Most URLs you
|
|
can access with your browser will also act as valid REST url endpoints.
|
|
|
|
Base Headers
|
|
------------
|
|
All your requests MUST have a valid accept header. The only acceptable
|
|
variant right now is `application/json`, so please always append a header
|
|
as follows to your requests:
|
|
|
|
Accept: application/json
|
|
|
|
|
|
Authentication
|
|
--------------
|
|
Please use HTTP authentication and any valid Icinga Web 2 user, granted
|
|
enough permissions to accomplish the desired actions. The restrictions
|
|
and permissions that have been assigned to web users will also be enforced
|
|
for API users. In addition, the permission `director/api` is required for
|
|
any API access.
|
|
|
|
Versioning
|
|
----------
|
|
|
|
There are no version strings so far in the Director URLs. We will try hard
|
|
to not break compatibility with future versions. Sure, sooner or later we
|
|
also might be forced to introduce some kind of versioning. But who knows?
|
|
|
|
As a developer you can trust us to not remove any existing REST url or any
|
|
provided property. However, you must always be ready to accept new properties.
|
|
|
|
URL scheme and supported methods
|
|
--------------------------------
|
|
|
|
We support GET, POST, PUT and DELETE.
|
|
|
|
| Method | Meaning
|
|
| ------ | ------------------------------------------------------------
|
|
| GET | Read / fetch data. Not allowed to run operations with the potential to cause any harm
|
|
| POST | Trigger actions, create or modify objects. Can also be used to partially modify objects
|
|
| PUT | Creates or replaces objects, cannot be used to modify single object properties
|
|
| DELETE | Remove a specific object
|
|
|
|
TODO: more examples showing the difference between POST and PUT
|
|
|
|
POST director/host
|
|
gives 201 on success
|
|
GET director/host?name=hostname.example.com
|
|
PUT director/host?name=hostname.example.com
|
|
gives 200 ok on success and 304 not modified on no change
|
|
DELETE director/host?name=hostname.example.com
|
|
gives 200 on success
|
|
|
|
|
|
First example request with CURL
|
|
-------------------------------
|
|
|
|
```sh
|
|
curl -H 'Accept: application/json' \
|
|
-u 'username:password' \
|
|
'https://icinga.example.com/icingaweb2/director/host?name=hostname.example.com'
|
|
```
|
|
|
|
### CURL helper script
|
|
|
|
A script like the following makes it easy to play around with curl:
|
|
|
|
```sh
|
|
METHOD=$1
|
|
URL=$2
|
|
BODY="$3"
|
|
USERNAME="demo"
|
|
PASSWORD="***"
|
|
test -z "$PASSWORD" || USERNAME="$USERNAME:$PASSWORD"
|
|
|
|
test -z "$BODY" && curl -u "$USERNAME" \
|
|
-i https://icingaweb/icingaweb/$URL \
|
|
-H 'Accept: application/json' \
|
|
-X $METHOD
|
|
|
|
test -z "$BODY" || curl -u "$USERNAME" \
|
|
-i https://icingaweb/icingaweb/$URL \
|
|
-H 'Accept: application/json' \
|
|
-X $METHOD \
|
|
-d "$BODY"
|
|
|
|
echo
|
|
```
|
|
|
|
It can be used as follows:
|
|
|
|
```sh
|
|
director-curl GET director/host?name=localhost
|
|
|
|
director-curl POST director/host '{"object_name": "host2", "... }'
|
|
```
|
|
|
|
|
|
Should I use HTTPS?
|
|
-------------------
|
|
|
|
Sure, absolutely, no doubt. There is no, absolutely no reason to NOT use
|
|
HTTPS these days. Especially not for a configuration tool allowing you to
|
|
configure check commands that are going to be executed on all your servers.
|
|
|
|
Icinga Objects
|
|
--------------
|
|
|
|
### Special parameters
|
|
|
|
#### Resolve object properties
|
|
|
|
In case you add the `resolve` parameter to your URL, all inherited object
|
|
properties will be resolved. Such a URL could look as follows:
|
|
|
|
director/host?name=hostname.example.com&resolved
|
|
|
|
|
|
#### Retrieve all properties
|
|
|
|
TODO: adjust the code to fix this, current implementation has `withNull`
|
|
|
|
Per default properties with `null` value are skipped when shipping a result.
|
|
You can influence this behavior with the properties parameter. Just append
|
|
`properties=ALL` to your URL:
|
|
|
|
director/host?name=hostname.example.com&properties=all
|
|
|
|
|
|
#### Retrieve only specific properties
|
|
|
|
The `properties` parameter also allows you to specify a list of specific
|
|
properties. In that case, only the given properties will be returned, even
|
|
when they have no (`null`) value:
|
|
|
|
director/host?name=hostname.example.com&properties=object_name,address,vars
|
|
|
|
|
|
### Example
|
|
|
|
GET director/host?name=pe2015.example.com
|
|
```json
|
|
{
|
|
"address": "127.0.0.3",
|
|
"check_command": null,
|
|
"check_interval": null,
|
|
"display_name": "pe2015 (example.com)",
|
|
"enable_active_checks": null,
|
|
"flapping_threshold": null,
|
|
"groups": [ ],
|
|
"imports": [
|
|
"generic-host"
|
|
],
|
|
"retry_interval": null,
|
|
"vars": {
|
|
"facts": {
|
|
"aio_agent_build": "1.2.5",
|
|
"aio_agent_version": "1.2.5",
|
|
"architecture": "amd64",
|
|
"augeas": {
|
|
"version": "1.4.0"
|
|
},
|
|
...
|
|
}
|
|
```
|
|
|
|
director/host?name=pe2015.example.com&resolved
|
|
```json
|
|
{
|
|
"address": "127.0.0.3",
|
|
"check_command": "tom_ping",
|
|
"check_interval": "60",
|
|
"display_name": "pe2015 (example.com)",
|
|
"enable_active_checks": true,
|
|
"groups": [ ],
|
|
"imports": [
|
|
"generic-host"
|
|
],
|
|
"retry_interval": "10",
|
|
"vars": {
|
|
"facts": {
|
|
"aio_agent_build": "1.2.5",
|
|
"aio_agent_version": "1.2.5",
|
|
"architecture": "amd64",
|
|
"augeas": {
|
|
"version": "1.4.0"
|
|
},
|
|
...
|
|
}
|
|
```
|
|
|
|
JSON is pretty-printed per default, at least for PHP >= 5.4
|
|
|
|
Error handling
|
|
--------------
|
|
|
|
Director tries hard to return meaningful output and error codes:
|
|
```
|
|
HTTP/1.1 400 Bad Request
|
|
Server: Apache
|
|
Content-Length: 46
|
|
Connection: close
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"error": "Invalid JSON: Syntax error"
|
|
}
|
|
```
|
|
|
|
Trigger actions
|
|
---------------
|
|
You can of course also use the API to trigger specific actions. Deploying the configuration is as simple as issueing:
|
|
|
|
POST director/config/deploy
|
|
|
|
More
|
|
----
|
|
|
|
Currently we do not handle Last-Modified und ETag headers. This would involve some work, but could be a cool feature. Let us know your ideas!
|
|
|
|
|
|
Sample scenario
|
|
---------------
|
|
|
|
Let's show you how the REST API works with a couple of practical examples:
|
|
|
|
### Create a new host
|
|
|
|
```
|
|
POST director/host
|
|
```
|
|
|
|
```json
|
|
{
|
|
"object_name": "apitest",
|
|
"object_type": "object",
|
|
"address": "127.0.0.1",
|
|
"vars": {
|
|
"location": "Berlin"
|
|
}
|
|
}
|
|
```
|
|
#### Response
|
|
```
|
|
HTTP/1.1 201 Created
|
|
Date: Tue, 01 Mar 2016 04:43:55 GMT
|
|
Server: Apache
|
|
Content-Length: 140
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"address": "127.0.0.1",
|
|
"object_name": "apitest",
|
|
"object_type": "object",
|
|
"vars": {
|
|
"location": "Berlin"
|
|
}
|
|
}
|
|
```
|
|
|
|
The most important part of the response is the response code: `201`, a resource has been created. Just for fun, let's fire the same request again. The answer obviously changes:
|
|
|
|
```
|
|
HTTP/1.1 500 Internal Server Error
|
|
Date: Tue, 01 Mar 2016 04:45:04 GMT
|
|
Server: Apache
|
|
Content-Length: 60
|
|
Connection: close
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"error": "Trying to recreate icinga_host (apitest)"
|
|
}
|
|
```
|
|
|
|
So, let's update this host. To work with existing objects, you must ship their `name` in the URL:
|
|
|
|
POST director/host?name=apitest
|
|
|
|
```json
|
|
{
|
|
"object_name": "apitest",
|
|
"object_type": "object",
|
|
"address": "127.0.0.1",
|
|
"vars": {
|
|
"location": "Berlin"
|
|
}
|
|
}
|
|
```
|
|
|
|
Same body, so no change:
|
|
```
|
|
HTTP/1.1 304 Not Modified
|
|
Date: Tue, 01 Mar 2016 04:45:33 GMT
|
|
Server: Apache
|
|
```
|
|
|
|
So let's now try to really change something:
|
|
|
|
POST director/host?name=apitest
|
|
|
|
```json
|
|
{"address": "127.0.0.2", "vars.event": "Icinga CAMP" }
|
|
```
|
|
|
|
We get status `200`, changes have been applied:
|
|
|
|
```
|
|
HTTP/1.1 200 OK
|
|
Date: Tue, 01 Mar 2016 04:46:25 GMT
|
|
Server: Apache
|
|
Content-Length: 172
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"address": "127.0.0.2",
|
|
"object_name": "apitest",
|
|
"object_type": "object",
|
|
"vars": {
|
|
"location": "Berlin",
|
|
"event": "Icinga CAMP"
|
|
}
|
|
}
|
|
```
|
|
|
|
The response always returns the full object on modification. This way you can immediately investigate the merged result. As you can see, `POST` requests only touch the parameters you passed - the rest remains untouched.
|
|
|
|
One more example to prove this:
|
|
|
|
```
|
|
POST director/host?name=apitest
|
|
```
|
|
|
|
```json
|
|
{"address": "127.0.0.2", "vars.event": "Icinga CAMP" }
|
|
```
|
|
|
|
No modification, you get a `304`. HTTP standards strongly discourage shipping a body in this case:
|
|
```
|
|
HTTP/1.1 304 Not Modified
|
|
Date: Tue, 01 Mar 2016 04:52:05 GMT
|
|
Server: Apache
|
|
```
|
|
|
|
As you might have noted, we only changed single properties in the vars dictionary. Now lets override the whole dictionary:
|
|
|
|
```
|
|
POST director/host?name=apitest
|
|
```
|
|
|
|
```json
|
|
{"address": "127.0.0.2", "vars": { "event": [ "Icinga", "Camp" ] } }
|
|
```
|
|
|
|
The response shows that this works as expected:
|
|
|
|
```
|
|
HTTP/1.1 200 OK
|
|
Date: Tue, 01 Mar 2016 04:52:33 GMT
|
|
Server: Apache
|
|
Content-Length: 181
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"address": "127.0.0.2",
|
|
"object_name": "apitest",
|
|
"object_type": "object",
|
|
"vars": {
|
|
"event": [
|
|
"Icinga",
|
|
"Camp"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
If merging properties is not what you want, `PUT` comes to the rescue:
|
|
|
|
PUT director/host?name=apitest
|
|
|
|
```
|
|
{ "vars": { "event": [ "Icinga", "Camp" ] }
|
|
```
|
|
|
|
All other properties vanished, all but name and type:
|
|
```
|
|
HTTP/1.1 200 OK
|
|
Date: Tue, 01 Mar 2016 04:54:33 GMT
|
|
Server: Apache
|
|
Content-Length: 153
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"object_name": "apitest",
|
|
"object_type": "object",
|
|
"vars": {
|
|
"event": [
|
|
"Icinga",
|
|
"Camp"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Let's put "nothing":
|
|
|
|
PUT director/host?name=apitest
|
|
|
|
```json
|
|
{}
|
|
```
|
|
|
|
Works as expected:
|
|
|
|
```
|
|
HTTP/1.1 200 OK
|
|
Date: Tue, 01 Mar 2016 04:57:35 GMT
|
|
Server: Apache
|
|
Content-Length: 62
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"object_name": "apitest",
|
|
"object_type": "object"
|
|
}
|
|
```
|
|
|
|
Of course, `PUT` also supports `304`, you can check this by sending the same request again.
|
|
|
|
Now let's try to cheat:
|
|
|
|
KILL director/host?name=apitest
|
|
|
|
```
|
|
HTTP/1.1 400 Bad Request
|
|
Date: Tue, 01 Mar 2016 04:54:07 GMT
|
|
Server: Apache
|
|
Content-Length: 43
|
|
Connection: close
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"error": "Unsupported method KILL"
|
|
}
|
|
```
|
|
|
|
Ok, no way. So let's use the correct method:
|
|
|
|
DELETE 'director/host?name=apitest
|
|
|
|
```
|
|
HTTP/1.1 200 OK
|
|
Date: Tue, 01 Mar 2016 05:59:22 GMT
|
|
Server: Apache
|
|
Content-Length: 109
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"imports": [
|
|
"generic-host"
|
|
],
|
|
"object_name": "apitest",
|
|
"object_type": "object"
|
|
}
|
|
```
|
|
|
|
### Agent Tickets
|
|
|
|
The Director is very helpful when it goes to manage your Icinga Agents. In
|
|
case you want to fetch tickets through the API, please do as follows:
|
|
|
|
GET director/host/ticket?name=apitest
|
|
|
|
```
|
|
HTTP/1.1 200 OK
|
|
Date: Thu, 07 Apr 2016 22:19:24 GMT
|
|
Server: Apache
|
|
Content-Length: 43
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
"5de9883080e03278039bce57e4fbdbe8fd262c40"
|
|
```
|
|
|
|
Please expect an error in case the host does not exist or has not been
|
|
configured to be an Icinga Agent.
|