diff --git a/doc/API/Alerts.md b/doc/API/Alerts.md index a3cd5c5c7f..e98edc27b6 100644 --- a/doc/API/Alerts.md +++ b/doc/API/Alerts.md @@ -36,7 +36,7 @@ Output: "alerted": "1", "open": "1", "timestamp": "2014-12-11 14:40:02" - }, + }] } ``` @@ -140,7 +140,7 @@ Output: "alerted": "1", "open": "1", "timestamp": "2014-12-11 14:40:02" - } + }] } ``` @@ -247,7 +247,7 @@ Output: "extra": "{\"mute\":false,\"count\":\"15\",\"delay\":\"300\",\"invert\":false}", "disabled": "0", "name": "A test rule" - }, + }] } ``` diff --git a/doc/API/DeviceGroups.md b/doc/API/DeviceGroups.md index 919f12948e..fde8af6b4c 100644 --- a/doc/API/DeviceGroups.md +++ b/doc/API/DeviceGroups.md @@ -37,6 +37,67 @@ Output: ] ``` +### `add_devicegroup` + +Add a new device group. Upon success, the ID of the new device group is returned +and the HTTP response code is `201`. + +Route: `/api/v0/devicegroups` + +Input (JSON): + +- `name`: *required* - The name of the device group +- `type`: *required* - should be `static` or `dynamic`. Setting this to static + requires that the devices input be provided +- `desc`: *optional* - Description of the device group +- `rules`: *required if type == dynamic* - A set of rules to determine which + devices should be included in this device group +- `devices`: *required if type == static* - A list of devices that should be + included in this group. This is a static list of devices + +Examples: + +Dynamic Example: + +```curl +curl -H 'X-Auth-Token: YOURAPITOKENHERE' \ + -d '{"name": "New Device Group", \ + "desc": "A very fancy dynamic group", \ + "type": "dynamic", + "rules": "{\"condition\":\"AND\",\"rules\":[{\"id\":\"access_points.name\",\"field\":\"access_points.name\",\"type\":\"string\",\"input\":\"text\",\"operator\":\"equal\",\"value\":\"accesspoint1\"}],\"valid\":true}"}' \ + https://librenms.org/api/v0/devicegroups +``` + +Output: + +```json +{ + "status": "ok", + "id": 86, + "message": "Device group New Device Group created" +} +``` + +Static Example: + +```curl +curl -H 'X-Auth-Token: YOURAPITOKENHERE' \ + -X POST \ + -d '{"name":"New Device Group","type":"static","devices":[261,271]}' \ + https://librenms.org/api/v0/devicegroups +``` + +Output: + +```json +{ + "status": "ok", + "id": 86, + "message": "Device group New Device Group created" +} +``` + + ### `get_devices_by_group` List all devices matching the group provided. diff --git a/includes/html/api_functions.inc.php b/includes/html/api_functions.inc.php index 5008cc7d20..096c22e49b 100644 --- a/includes/html/api_functions.inc.php +++ b/includes/html/api_functions.inc.php @@ -18,6 +18,7 @@ use App\Models\PortsFdb; use App\Models\Sensor; use Illuminate\Database\Eloquent\Builder; use Illuminate\Routing\Router; +use Illuminate\Support\Facades\Validator; use LibreNMS\Alerting\QueryBuilderParser; use LibreNMS\Config; use LibreNMS\Exceptions\InvalidIpException; @@ -1684,6 +1685,44 @@ function rename_device(\Illuminate\Http\Request $request) } } +function add_device_group(\Illuminate\Http\Request $request) +{ + $data = json_decode($request->getContent(), true); + if (json_last_error() || !is_array($data)) { + return api_error(400, "We couldn't parse the provided json. " . json_last_error_msg()); + } + + $rules = [ + 'name' => 'required|string|unique:device_groups', + 'type' => 'required|in:dynamic,static', + 'devices' => 'array|required_if:type,static', + 'devices.*' => 'integer', + 'rules' => 'json|required_if:type,dynamic', + ]; + + $v = Validator::make($data, $rules); + if ($v->fails()) { + return api_error(422, $v->messages()); + } + + // Only use the rules if they are able to be parsed by the QueryBuilder + $query = QueryBuilderParser::fromJson($data['rules'])->toSql(); + if (empty($query)) { + return api_error(500, "We couldn't parse your rule"); + } + + $deviceGroup = DeviceGroup::make(['name' => $data['name'], 'type' => $data['type'], 'desc' => $data['desc']]); + $deviceGroup->rules = json_decode($data['rules']); + $deviceGroup->save(); + + if ($data['type'] == 'static') { + $deviceGroup->devices()->sync($data['devices']); + } + + return api_success($deviceGroup->id, 'id', 'Device group ' . $deviceGroup->name . ' created', 201); +} + + function get_device_groups(\Illuminate\Http\Request $request) { $hostname = $request->route('hostname'); diff --git a/routes/api.php b/routes/api.php index c234157d03..35287f1ec3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -74,6 +74,7 @@ Route::group(['prefix' => 'v0', 'namespace' => '\App\Api\Controllers'], function Route::delete('rules/{id}', 'LegacyApiController@delete_rule')->name('delete_rule'); Route::post('services/{hostname}', 'LegacyApiController@add_service_for_host')->name('add_service_for_host'); Route::get('oxidized/config/search/{searchstring}', 'LegacyApiController@search_oxidized')->name('search_oxidized'); + Route::post('devicegroups', 'LegacyApiController@add_device_group')->name('add_device_group'); }); // restricted by access