Target attributes update can be (re-)triggered by management API (#690)

* extend Management API with attribute `requestAttributes`
* introduce new DMF Event Topic `REQUEST_ATTRIBUTES_UPDATE`
* enhance REST documentation by new functionality
* add tests for:
  * Management API
  * Amqp Message Dispatcher Service
  * Repository (Target Management)

Signed-off-by: Jeroen Jan Laverman (INST/ESY3) <jeroen.laverman@bosch-si.com>
This commit is contained in:
Jeroen Laverman
2018-06-14 12:48:31 +02:00
committed by Dominic Schabel
parent f4340098d9
commit ecfe774e53
18 changed files with 275 additions and 17 deletions

View File

@@ -46,6 +46,9 @@ public class MgmtTarget extends MgmtNamedEntity {
@JsonProperty
private String securityToken;
@JsonProperty
private boolean requestAttributes;
/**
* @return the controllerId
*/
@@ -167,4 +170,13 @@ public class MgmtTarget extends MgmtNamedEntity {
public void setSecurityToken(final String securityToken) {
this.securityToken = securityToken;
}
public boolean isRequestAttributes() {
return requestAttributes;
}
@JsonIgnore
public void setRequestAttributes(final boolean requestAttributes) {
this.requestAttributes = requestAttributes;
}
}

View File

@@ -24,6 +24,9 @@ public class MgmtTargetRequestBody {
@JsonProperty
private String securityToken;
@JsonProperty
private Boolean requestAttributes;
public String getSecurityToken() {
return securityToken;
}
@@ -88,4 +91,11 @@ public class MgmtTargetRequestBody {
this.address = address;
}
public Boolean isRequestAttributes() {
return requestAttributes;
}
public void setRequestAttributes(final Boolean requestAttributes) {
this.requestAttributes = requestAttributes;
}
}

View File

@@ -133,6 +133,7 @@ public final class MgmtTargetMapper {
targetRest.setLastModifiedAt(target.getLastModifiedAt());
targetRest.setSecurityToken(target.getSecurityToken());
targetRest.setRequestAttributes(target.isRequestControllerAttributes());
// last target query is the last controller request date
final Long lastTargetQuery = target.getLastTargetQuery();

View File

@@ -120,9 +120,18 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
public ResponseEntity<MgmtTarget> updateTarget(@PathVariable("controllerId") final String controllerId,
@RequestBody final MgmtTargetRequestBody targetRest) {
if (targetRest.isRequestAttributes() != null) {
if (targetRest.isRequestAttributes()) {
targetManagement.requestControllerAttributes(controllerId);
} else {
return ResponseEntity.badRequest().build();
}
}
final Target updateTarget = this.targetManagement.update(entityFactory.target().update(controllerId)
.name(targetRest.getName()).description(targetRest.getDescription()).address(targetRest.getAddress())
.securityToken(targetRest.getSecurityToken()));
.securityToken(targetRest.getSecurityToken()).requestAttributes(targetRest.isRequestAttributes()));
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget);
MgmtTargetMapper.addPollStatus(updateTarget, response);

View File

@@ -68,6 +68,7 @@ import com.jayway.jsonpath.JsonPath;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Step;
import ru.yandex.qatools.allure.annotations.Stories;
/**
@@ -1539,6 +1540,56 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
.andDo(MockMvcResultPrinter.print()).andExpect(status().is(HttpStatus.NO_CONTENT.value()));
}
@Test
@Description("Request update of Controller Attributes.")
public void triggerControllerAttributesUpdate() throws Exception {
// create target with attributes
final String knownTargetId = "targetIdNeedsUpdate";
final Map<String, String> knownControllerAttrs = new HashMap<>();
knownControllerAttrs.put("a", "1");
knownControllerAttrs.put("b", "2");
testdataFactory.createTarget(knownTargetId);
controllerManagement.updateControllerAttributes(knownTargetId, knownControllerAttrs, null);
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isFalse();
verifyAttributeUpdateCanBeRequested(knownTargetId);
verifyRequestAttributesAttributeIsOptional(knownTargetId);
verifyResettingRequestAttributesIsNotAllowed(knownTargetId);
}
@Step
private void verifyAttributeUpdateCanBeRequested(final String knownTargetId) throws Exception {
final String body = new JSONObject().put("requestAttributes", true).toString();
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
}
@Step
private void verifyRequestAttributesAttributeIsOptional(final String knownTargetId) throws Exception {
final String body = new JSONObject().put("description", "verify attribute can be missing").toString();
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
}
@Step
private void verifyResettingRequestAttributesIsNotAllowed(final String knownTargetId) throws Exception {
final String body = new JSONObject().put("requestAttributes", false).toString();
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId).content(body)
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isTrue();
}
@Test
public void searchTargetsUsingRsqlQuery() throws Exception {
final int amountTargets = 10;

View File

@@ -219,6 +219,8 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
.type("enum")
.attributes(key("value").value("['error', 'in_sync', 'pending', 'registered', 'unknown']")),
fieldWithPath(fieldArrayPrefix + "securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN),
fieldWithPath(fieldArrayPrefix + "requestAttributes")
.description(MgmtApiModelProperties.REQUEST_ATTRIBUTES),
fieldWithPath(fieldArrayPrefix + "installedAt").description(MgmtApiModelProperties.INSTALLED_AT),
fieldWithPath(fieldArrayPrefix + "lastModifiedAt")
.description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"),

View File

@@ -143,6 +143,8 @@ public final class MgmtApiModelProperties {
public static final String SECURITY_TOKEN = "Pre-Shared key that allows targets to authenticate at Direct Device Integration API if enabled in the tenant settings.";
public static final String REQUEST_ATTRIBUTES = "Request re-transmission of target attributes.";
public static final String META_DATA = "List of metadata.";
public static final String META_DATA_KEY = "Metadata property key.";

View File

@@ -90,6 +90,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
.type("enum").attributes(
key("value").value("['error', 'in_sync', 'pending', 'registered', 'unknown']")),
fieldWithPath("content[].securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN),
fieldWithPath("content[].requestAttributes").description(MgmtApiModelProperties.REQUEST_ATTRIBUTES),
fieldWithPath("content[].installedAt").description(MgmtApiModelProperties.INSTALLED_AT),
fieldWithPath("content[].lastModifiedAt")
.description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"),
@@ -141,6 +142,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
.attributes(key("value")
.value("['error', 'in_sync', 'pending', 'registered', 'unknown']")),
fieldWithPath("[]securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN),
fieldWithPath("[]requestAttributes").description(MgmtApiModelProperties.REQUEST_ATTRIBUTES),
fieldWithPath("[]_links.self").ignored())));
}
@@ -180,12 +182,13 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
.andDo(this.document.document(
pathParameters(
parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)),
requestFields(requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
requestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION),
requestFieldWithPath("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
requestFieldWithPath("address").description(MgmtApiModelProperties.ADDRESS),
requestFieldWithPath("securityToken")
.description(MgmtApiModelProperties.SECURITY_TOKEN)),
requestFields(optionalRequestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
optionalRequestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION),
optionalRequestFieldWithPath("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID),
optionalRequestFieldWithPath("address").description(MgmtApiModelProperties.ADDRESS),
optionalRequestFieldWithPath("securityToken")
.description(MgmtApiModelProperties.SECURITY_TOKEN),
optionalRequestFieldWithPath("requestAttributes").description(MgmtApiModelProperties.REQUEST_ATTRIBUTES)),
getResponseFieldTarget(false)));
}
@@ -570,6 +573,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
target.put("name", name);
target.put("address", "https://192.168.0.1");
target.put("securityToken", "2345678DGGDGFTDzztgf");
target.put("requestAttributes", true);
return this.objectMapper.writeValueAsString(target);
}