From f35587328e1bd99882ed8a4df85d01660d54c007 Mon Sep 17 00:00:00 2001 From: brunomilitzer Date: Thu, 5 May 2022 15:20:30 +0100 Subject: Added Edit Instance Properties Functionality Issue-ID: POLICY-4094 Change-Id: Id52dba3c0912486fa551697be170c05542a0ee22 Signed-off-by: brunomilitzer --- .../commissioning/CommissioningProvider.java | 44 ++++++-- ...AutomationCompositionInstantiationProvider.java | 115 +++++++++++++++++++++ .../runtime/main/rest/CommissioningController.java | 26 +++-- .../runtime/main/rest/InstantiationController.java | 74 ++++++++++++- .../commissioning/CommissioningProviderTest.java | 3 +- .../rest/CommissioningControllerTest.java | 2 +- ...mationCompositionInstantiationProviderTest.java | 5 + 7 files changed, 244 insertions(+), 25 deletions(-) (limited to 'runtime-acm') diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java index 726fcba5c..7d2d4f39c 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. + * Copyright (C) 2021-2022 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import javax.ws.rs.core.Response.Status; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler; import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; @@ -237,15 +238,17 @@ public class CommissioningProvider { /** * Get node templates with common properties added. * - * @param common boolean indicating common or instance properties to be used * @param name the name of the definition to use, null for all definitions * @param version the version of the definition to use, null for all definitions + * @param instanceName automation composition name + * @param common boolean indicating common or instance properties to be used * @return the nodes templates with common or instance properties * @throws PfModelException on errors getting common or instance properties from node_templates */ @Transactional(readOnly = true) - public Map getNodeTemplatesWithCommonOrInstanceProperties(boolean common, String name, - String version) throws PfModelException { + public Map getNodeTemplatesWithCommonOrInstanceProperties( + final String name, final String version, final String instanceName, final boolean common) + throws PfModelException { if (common && verifyIfInstancePropertiesExists()) { throw new PfModelException(Status.BAD_REQUEST, @@ -253,11 +256,17 @@ public class CommissioningProvider { } var serviceTemplateList = serviceTemplateProvider.getServiceTemplateList(name, version); + + if (serviceTemplateList.isEmpty()) { + throw new PfModelException(Status.BAD_REQUEST, + "Tosca service template has to be commissioned before saving instance properties"); + } + var commonOrInstanceNodeTypeProps = serviceTemplateProvider.getCommonOrInstancePropertiesFromNodeTypes(common, serviceTemplateList.get(0)); var serviceTemplates = new ToscaServiceTemplates(); - serviceTemplates.setServiceTemplates(filterToscaNodeTemplateInstance(serviceTemplateList)); + serviceTemplates.setServiceTemplates(filterToscaNodeTemplateInstance(serviceTemplateList, instanceName)); return serviceTemplateProvider.getDerivedCommonOrInstanceNodeTemplates( serviceTemplates.getServiceTemplates().get(0).getToscaTopologyTemplate().getNodeTemplates(), @@ -293,14 +302,19 @@ public class CommissioningProvider { * * @param name the name of the template to get, null for all definitions * @param version the version of the template to get, null for all definitions + * @param instanceName automation composition name * @return the tosca service template * @throws PfModelException on errors getting tosca service template */ @Transactional(readOnly = true) - public String getToscaServiceTemplateReduced(String name, String version) throws PfModelException { + public String getToscaServiceTemplateReduced( + final String name, final String version, final String instanceName) + throws PfModelException { + var serviceTemplateList = serviceTemplateProvider.getServiceTemplateList(name, version); - List filteredServiceTemplateList = filterToscaNodeTemplateInstance(serviceTemplateList); + List filteredServiceTemplateList = + filterToscaNodeTemplateInstance(serviceTemplateList, instanceName); if (filteredServiceTemplateList.isEmpty()) { throw new PfModelException(Status.BAD_REQUEST, "Invalid Service Template"); @@ -342,16 +356,26 @@ public class CommissioningProvider { } } - private List filterToscaNodeTemplateInstance(List serviceTemplates) { + /** + * Filters service templates if is not an instantiation type. + * + * @param serviceTemplates tosca service template + * @param instanceName automation composition name + * @return List of tosca service templates + */ + private List filterToscaNodeTemplateInstance( + List serviceTemplates, String instanceName) { List toscaServiceTemplates = new ArrayList<>(); - serviceTemplates.stream().forEach(serviceTemplate -> { + serviceTemplates.forEach(serviceTemplate -> { Map toscaNodeTemplates = new HashMap<>(); serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().forEach((key, nodeTemplate) -> { - if (!nodeTemplate.getName().contains(HYPHEN)) { + if (StringUtils.isNotEmpty(instanceName) && nodeTemplate.getName().contains(instanceName)) { + toscaNodeTemplates.put(key, nodeTemplate); + } else if (!nodeTemplate.getName().contains(HYPHEN)) { toscaNodeTemplates.put(key, nodeTemplate); } }); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java index 40d4c5a85..98b59aed7 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java @@ -141,6 +141,61 @@ public class AutomationCompositionInstantiationProvider { return saveInstancePropertiesAndAutomationComposition(serviceTemplate, automationCompositions); } + /** + * Updates Instance Properties and Automation Composition Instance. + * + * @param name the name of the automation composition to update + * @param version the version of the automation composition to update + * @param serviceTemplate tosca service template body + * @return InstancePropertiesResponse response from updating instance properties + * @throws PfModelException exception if incorrect instance name + */ + public InstancePropertiesResponse updatesInstanceProperties( + String name, String version, ToscaServiceTemplate serviceTemplate) throws PfModelException { + + if (name.length() < 3) { + throw new PfModelException(Status.BAD_REQUEST, "Instance Name cannot be empty or less than 3 characters!"); + } + + Map nodeTemplates = deepCloneNodeTemplate(serviceTemplate); + Map updatedNodeTemplates = new HashMap<>(); + + String instanceName = serviceTemplate.getName(); + + nodeTemplates.forEach((key, template) -> { + ToscaNodeTemplate toscaNodeTemplate = new ToscaNodeTemplate(); + + String updatedName = updateInstanceNameDescription(instanceName, name, key); + String updatedDescription = updateInstanceNameDescription( + instanceName, name, template.getDescription()); + + toscaNodeTemplate.setName(updatedName); + toscaNodeTemplate.setDescription(updatedDescription); + toscaNodeTemplate.setCapabilities(template.getCapabilities()); + toscaNodeTemplate.setRequirements(template.getRequirements()); + toscaNodeTemplate.setMetadata(template.getMetadata()); + toscaNodeTemplate.setProperties(template.getProperties()); + toscaNodeTemplate.setDerivedFrom(template.getDerivedFrom()); + toscaNodeTemplate.setVersion(template.getVersion()); + toscaNodeTemplate.setType(template.getType()); + toscaNodeTemplate.setTypeVersion(template.getTypeVersion()); + + String updatedKey = updateInstanceNameDescription(instanceName, name, key); + + updatedNodeTemplates.put(updatedKey, toscaNodeTemplate); + }); + + serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().clear(); + serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().putAll(updatedNodeTemplates); + + AutomationCompositions automationCompositions = updateAutomationComposition( + name, instanceName); + + deleteInstanceProperties(name, version); + + return saveInstancePropertiesAndAutomationComposition(serviceTemplate, automationCompositions); + } + /** * Deletes Instance Properties. * @@ -616,4 +671,64 @@ public class AutomationCompositionInstantiationProvider { Type type = new TypeToken>() {}.getType(); return GSON.fromJson(jsonString, type); } + + /** + * Updates Automation composition instance name. + * + * @param oldInstanceName previous saved instance name + * @param newInstanceName new instance name to replace the previous one + * @return AutomationCompositions updated + * @throws PfModelException exception to compositions is not defined + */ + private AutomationCompositions updateAutomationComposition( + String oldInstanceName, String newInstanceName) throws PfModelException { + + List filteredAcmList = automationCompositionProvider.getAutomationCompositions() + .stream().filter(acm -> acm.getName().contains(oldInstanceName)).collect(Collectors.toList()); + + if (filteredAcmList.isEmpty()) { + throw new PfModelException(Status.BAD_REQUEST, "Automation compositions not defined!"); + } + + AutomationComposition automationComposition = filteredAcmList.get(0); + + automationComposition.getDefinition() + .setName(updateInstanceNameDescription(newInstanceName, oldInstanceName, + automationComposition.getDefinition().getName())); + + automationComposition.setName(newInstanceName); + + automationComposition.setDescription( + updateInstanceNameDescription(newInstanceName, oldInstanceName, + automationComposition.getDescription())); + + automationComposition.getElements().forEach((uuid, automationCompositionElement) -> { + automationCompositionElement.getDefinition() + .setName(updateInstanceNameDescription(newInstanceName, oldInstanceName, + automationCompositionElement.getDefinition().getName())); + }); + + AutomationCompositions automationCompositions = new AutomationCompositions(); + automationCompositions.getAutomationCompositionList().add(automationComposition); + + return automationCompositions; + + } + + /** + * Updates instance and description. + * + * @param newInstanceName new instance name to replace the previous one + * @param oldInstanceName previous saved instance name + * @param value to be updated + * @return String updated instance name or description + */ + private String updateInstanceNameDescription( + String newInstanceName, String oldInstanceName, String value) { + String toBeReplaced = value.substring(value.indexOf(oldInstanceName)); + + String replace = value.replace(toBeReplaced, newInstanceName); + + return replace; + } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java index 0fd8661b4..0458b074a 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. + * Copyright (C) 2021-2022 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,6 @@ import javax.ws.rs.core.Response.Status; import lombok.RequiredArgsConstructor; import org.onap.policy.clamp.acm.runtime.commissioning.CommissioningProvider; import org.onap.policy.clamp.acm.runtime.main.web.AbstractRestController; -import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException; import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; @@ -305,10 +304,13 @@ public class CommissioningController extends AbstractRestController { required = false) String name, @ApiParam(value = "Tosca service template version", required = false) @RequestParam( value = "version", - required = false) String version) + required = false) String version, + @ApiParam(value = "Automation composition name", required = false) @RequestParam( + value = "instanceName", + required = false) String instanceName) throws PfModelException { - return ResponseEntity.ok().body(provider.getToscaServiceTemplateReduced(name, version)); + return ResponseEntity.ok().body(provider.getToscaServiceTemplateReduced(name, version, instanceName)); } /** @@ -376,7 +378,6 @@ public class CommissioningController extends AbstractRestController { * @param version the version of the tosca service template to get * @return the specified tosca service template or section Json Schema * @throws PfModelException on errors getting the Common or Instance Properties - * @throws AutomationCompositionException on error getting the Common or Instance Properties */ // @formatter:off @GetMapping(value = "/commission/getCommonOrInstanceProperties", @@ -418,18 +419,23 @@ public class CommissioningController extends AbstractRestController { // @formatter:on public ResponseEntity> queryToscaServiceCommonOrInstanceProperties( @RequestHeader(name = REQUEST_ID_NAME, required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam( - value = "Flag, true for common properties, false for instance", - required = false) @RequestParam(value = "common", defaultValue = "false", required = false) boolean common, @ApiParam(value = "Tosca service template name", required = false) @RequestParam( value = "name", required = false) String name, @ApiParam(value = "Tosca service template version", required = false) @RequestParam( value = "version", - required = false) String version) + required = false) String version, + @ApiParam(value = "Automation composition name", required = false) @RequestParam( + value = "instanceName", + required = false) String instanceName, + @ApiParam( + value = "Flag, true for common properties, false for instance", + required = false) + @RequestParam(value = "common", defaultValue = "false", required = false) boolean common) throws PfModelException { - return ResponseEntity.ok().body(provider.getNodeTemplatesWithCommonOrInstanceProperties(common, name, version)); + return ResponseEntity.ok().body(provider + .getNodeTemplatesWithCommonOrInstanceProperties(name, version, instanceName, common)); } /** diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java index dc56c77e7..b4d978d77 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. + * Copyright (C) 2021-2022 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -192,6 +192,74 @@ public class InstantiationController extends AbstractRestController { return ResponseEntity.ok().body(provider.createInstanceProperties(body)); } + /** + * Updates instance properties. + * + * @param name the name of the automation composition to update + * @param version the version of the automation composition to update + * @param body the body of automation composition following TOSCA definition + * @return a response + */ + // @formatter:off + @PutMapping(value = "/instanceProperties", + consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}, + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation( + value = "Updates instance properties", + notes = "Updates instance properties, returning the saved instances properties and it's version", + response = InstancePropertiesResponse.class, + tags = {TAGS}, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, + description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_PATCH_NAME, + description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_LATEST_NAME, + description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = REQUEST_ID_NAME, + description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class) + }, + extensions = { + @Extension + ( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public ResponseEntity updatesInstanceProperties( + @RequestHeader(name = REQUEST_ID_NAME, required = false) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Automation composition definition name", required = true) + @RequestParam("name") String name, + @ApiParam(value = "Automation composition definition version", required = true) + @RequestParam("version") String version, + @ApiParam(value = "Body of instance properties", required = true) @RequestBody ToscaServiceTemplate body) + throws PfModelException { + + return ResponseEntity.ok().body(provider.updatesInstanceProperties(name, version, body)); + } + /** * Deletes a automation composition definition and instance properties. * @@ -248,8 +316,8 @@ public class InstantiationController extends AbstractRestController { public ResponseEntity deleteInstanceProperties( @RequestHeader(name = REQUEST_ID_NAME, required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Automation composition definition name", required = true) @RequestParam("name") String name, - @ApiParam(value = "Automation composition definition version") @RequestParam( + @ApiParam(value = "Automation composition definition name", required = true) @RequestParam("name") String name, + @ApiParam(value = "Automation composition definition version") @RequestParam( value = "version", required = true) String version) throws PfModelException { diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java index 71aadccb9..152171f9e 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java @@ -163,7 +163,8 @@ class CommissioningProviderTest { when(serviceTemplateProvider.getServiceTemplateList(any(), any())) .thenReturn(List.of(Objects.requireNonNull(serviceTemplate))); - String returnedServiceTemplate = provider.getToscaServiceTemplateReduced(null, null); + String returnedServiceTemplate = provider + .getToscaServiceTemplateReduced(null, null, null); assertThat(returnedServiceTemplate).isNotNull(); ToscaServiceTemplate parsedServiceTemplate = CODER.decode(returnedServiceTemplate, ToscaServiceTemplate.class); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java index 87633dfd4..a0f1a7590 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java @@ -158,7 +158,7 @@ class CommissioningControllerTest extends CommonRestController { createFullEntryInDbWithCommonProps(); Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT - + "/getCommonOrInstanceProperties" + "?common=true&name=ToscaServiceTemplateSimple&version=1.0.0"); + + "/getCommonOrInstanceProperties?common=true"); Response rawresp = invocationBuilder.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java index 248b04595..b826eebbc 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java @@ -120,6 +120,11 @@ class AutomationCompositionInstantiationProviderTest { automationComposition.setVersion(ID_VERSION); when(acProvider.getAutomationCompositions(ID_NAME, ID_VERSION)).thenReturn(List.of(automationComposition)); + var updatedInstancePropertyList = instantiationProvider.createInstanceProperties(serviceTemplate); + assertNull(updatedInstancePropertyList.getErrorDetails()); + var updatedId = new ToscaConceptIdentifier(ID_NAME, ID_VERSION); + assertEquals(updatedId, instancePropertyList.getAffectedInstanceProperties().get(0)); + var instanceOrderState = instantiationProvider.getInstantiationOrderState(ID_NAME, ID_VERSION); assertEquals(AutomationCompositionOrderedState.UNINITIALISED, instanceOrderState.getOrderedState()); assertEquals(ID_NAME, instanceOrderState.getAutomationCompositionIdentifierList().get(0).getName()); -- cgit 1.2.3-korg