POST /v1/objects: allow array of attrs to undo modifications of

This commit is contained in:
Alexander A. Klimov 2023-06-13 16:40:33 +02:00
parent a3dabde28a
commit 1587431945
2 changed files with 83 additions and 7 deletions

View File

@ -890,9 +890,17 @@ curl -k -s -S -i -u root:icinga -H 'Accept: application/json' \
Existing objects must be modified by sending a `POST` request. The following Existing objects must be modified by sending a `POST` request. The following
parameters need to be passed inside the JSON body: parameters need to be passed inside the JSON body:
Parameters | Type | Description | Parameters | Type | Description |
-----------|------------|--------------------------- |----------------|------------|----------------------------------------------------------------------------------------------------------------------------|
attrs | Dictionary | **Required.** Set specific object attributes for this [object type](09-object-types.md#object-types). | attrs | Dictionary | **Optional.** Set specific object attributes for this [object type](09-object-types.md#object-types). |
| restore\_attrs | Array | **Optional.** Discard modifications of specific object attributes for this [object type](09-object-types.md#object-types). |
One of the above is required.
!!! info
If a particular attribute is given in both sets,
it's first restored and then set to the desired new value.
In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters)
parameter should be provided. parameter should be provided.
@ -936,6 +944,34 @@ curl -k -s -S -i -u root:icinga -H 'Accept: application/json' \
} }
``` ```
To undo such modifications to specific object attributes,
list the latter in the `restore_attrs` parameter. E.g.:
```bash
curl -k -s -S -i -u root:icinga -H 'Accept: application/json' \
-X POST 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
-d '{ "restore_attrs": [ "address", "vars.os" ] }, "pretty": true }'
```
```json
{
"results": [
{
"code": 200.0,
"name": "example.localdomain",
"status": "Attributes updated.",
"type": "Host"
}
]
}
```
Giving `attrs` with the original value would have almost the same effect.
But in this case Icinga would still store that value as a modified attribute,
overriding DSL/Director config (changes). In contrast, `restore_attrs` tells
Icinga to actually forget particular modified attributes, so that changes to
them via Director or plain config are effective again.
### Deleting Objects <a id="icinga2-api-config-objects-delete"></a> ### Deleting Objects <a id="icinga2-api-config-objects-delete"></a>
You can delete objects created using the API by sending a `DELETE` You can delete objects created using the API by sending a `DELETE`

View File

@ -64,7 +64,7 @@ bool ModifyObjectHandler::HandleRequest(
Value attrsVal = params->Get("attrs"); Value attrsVal = params->Get("attrs");
if (attrsVal.GetReflectionType() != Dictionary::TypeInstance) { if (attrsVal.GetReflectionType() != Dictionary::TypeInstance && attrsVal.GetType() != ValueEmpty) {
HttpUtility::SendJsonError(response, params, 400, HttpUtility::SendJsonError(response, params, 400,
"Invalid type for 'attrs' attribute specified. Dictionary type is required." "Invalid type for 'attrs' attribute specified. Dictionary type is required."
"Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?"); "Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?");
@ -73,6 +73,23 @@ bool ModifyObjectHandler::HandleRequest(
Dictionary::Ptr attrs = attrsVal; Dictionary::Ptr attrs = attrsVal;
Value restoreAttrsVal = params->Get("restore_attrs");
if (restoreAttrsVal.GetReflectionType() != Array::TypeInstance && restoreAttrsVal.GetType() != ValueEmpty) {
HttpUtility::SendJsonError(response, params, 400,
"Invalid type for 'restore_attrs' attribute specified. Array type is required.");
return true;
}
Array::Ptr restoreAttrs = restoreAttrsVal;
if (!(attrs || restoreAttrs)) {
HttpUtility::SendJsonError(response, params, 400,
"Missing both 'attrs' and 'restore_attrs'. "
"Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?");
return true;
}
bool verbose = false; bool verbose = false;
if (params) if (params)
@ -95,6 +112,26 @@ bool ModifyObjectHandler::HandleRequest(
String key; String key;
try {
if (restoreAttrs) {
ObjectLock oLock (restoreAttrs);
for (auto& attr : restoreAttrs) {
key = attr;
obj->RestoreAttribute(key);
}
}
} catch (const std::exception& ex) {
result1->Set("code", 500);
result1->Set("status", "Attribute '" + key + "' could not be restored: " + DiagnosticInformation(ex, false));
if (verbose)
result1->Set("diagnostic_information", DiagnosticInformation(ex));
results.push_back(std::move(result1));
continue;
}
try { try {
if (attrs) { if (attrs) {
ObjectLock olock(attrs); ObjectLock olock(attrs);
@ -103,17 +140,20 @@ bool ModifyObjectHandler::HandleRequest(
obj->ModifyAttribute(kv.first, kv.second); obj->ModifyAttribute(kv.first, kv.second);
} }
} }
result1->Set("code", 200);
result1->Set("status", "Attributes updated.");
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
result1->Set("code", 500); result1->Set("code", 500);
result1->Set("status", "Attribute '" + key + "' could not be set: " + DiagnosticInformation(ex, false)); result1->Set("status", "Attribute '" + key + "' could not be set: " + DiagnosticInformation(ex, false));
if (verbose) if (verbose)
result1->Set("diagnostic_information", DiagnosticInformation(ex)); result1->Set("diagnostic_information", DiagnosticInformation(ex));
results.push_back(std::move(result1));
continue;
} }
result1->Set("code", 200);
result1->Set("status", "Attributes updated.");
results.push_back(std::move(result1)); results.push_back(std::move(result1));
} }