From c6012167b9692eb38bcb479f233543e93c51c998 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Thu, 2 Jul 2020 09:30:52 -0400 Subject: Rename XxxActorServiceProvider to XxxActor Renamed the actors and their test classes. Addressed review comments: - some license dates Issue-ID: POLICY-2684 Change-Id: Ic9d83e146ef36bb305496d541166cb9f80544025 Signed-off-by: Jim Hahn --- .../controlloop/actor/appclcm/AppcLcmActor.java | 310 ++++++++++++++ .../actor/appclcm/AppcLcmActorServiceProvider.java | 310 -------------- ...licy.controlloop.actorserviceprovider.spi.Actor | 2 +- .../appclcm/AppcLcmActorServiceProviderTest.java | 457 --------------------- .../actor/appclcm/AppcLcmActorTest.java | 457 +++++++++++++++++++++ 5 files changed, 768 insertions(+), 768 deletions(-) create mode 100644 models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java delete mode 100644 models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java delete mode 100644 models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java create mode 100644 models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java (limited to 'models-interactions/model-actors/actor.appclcm') diff --git a/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java b/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java new file mode 100644 index 000000000..04ef55aeb --- /dev/null +++ b/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActor.java @@ -0,0 +1,310 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications copyright (c) 2018 Nokia + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.appclcm; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.AbstractMap; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.onap.policy.appclcm.AppcLcmBody; +import org.onap.policy.appclcm.AppcLcmCommonHeader; +import org.onap.policy.appclcm.AppcLcmDmaapWrapper; +import org.onap.policy.appclcm.AppcLcmInput; +import org.onap.policy.appclcm.AppcLcmOutput; +import org.onap.policy.appclcm.AppcLcmResponseCode; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.appc.AppcOperation; +import org.onap.policy.controlloop.actor.appc.ModifyConfigOperation; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcLcmActor extends BidirectionalTopicActor { + + /* + * Confirmed by Daniel, should be 'APPC'. + * The actor name defined in the yaml for both legacy operations and lcm operations is still “APPC”. Perhaps in a + * future review it would be better to distinguish them as two separate actors in the yaml but it should be okay for + * now. + */ + public static final String NAME = "APPC"; + + private static final Logger logger = LoggerFactory.getLogger(AppcLcmActor.class); + + /* To be used in future releases to restart a single vm */ + private static final String APPC_VM_ID = "vm-id"; + + // Strings for targets + private static final String TARGET_VM = "VM"; + private static final String TARGET_VNF = "VNF"; + + // Strings for recipes + private static final String RECIPE_RESTART = AppcLcmConstants.OPERATION_RESTART; + private static final String RECIPE_REBUILD = AppcLcmConstants.OPERATION_REBUILD; + private static final String RECIPE_MIGRATE = AppcLcmConstants.OPERATION_MIGRATE; + private static final String RECIPE_MODIFY = AppcLcmConstants.OPERATION_CONFIG_MODIFY; + + /* To be used in future releases when LCM ConfigModify is used */ + private static final String APPC_REQUEST_PARAMS = "request-parameters"; + private static final String APPC_CONFIG_PARAMS = "configuration-parameters"; + + private static final Set recipes = AppcLcmConstants.OPERATION_NAMES; + private static final ImmutableMap> targets = new ImmutableMap.Builder>() + .put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).put(RECIPE_REBUILD, ImmutableList.of(TARGET_VM)) + .put(RECIPE_MIGRATE, ImmutableList.of(TARGET_VM)).put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)).build(); + private static final ImmutableMap> payloads = + new ImmutableMap.Builder>().put(RECIPE_RESTART, ImmutableList.of(APPC_VM_ID)) + .put(RECIPE_MODIFY, ImmutableList.of(APPC_REQUEST_PARAMS, APPC_CONFIG_PARAMS)).build(); + + /** + * Constructs the object. + */ + public AppcLcmActor() { + super(NAME, BidirectionalTopicActorParams.class); + + // add LCM operations first as they take precedence + for (String opname : AppcLcmConstants.OPERATION_NAMES) { + addOperator(new BidirectionalTopicOperator(NAME, opname, this, AppcLcmOperation.SELECTOR_KEYS, + AppcLcmOperation::new)); + } + + // add legacy operations + addOperator(new BidirectionalTopicOperator(NAME, ModifyConfigOperation.NAME, this, AppcOperation.SELECTOR_KEYS, + ModifyConfigOperation::new)); + } + + /** + * This actor should take precedence. + */ + @Override + public int getSequenceNumber() { + return -1; + } + + @Override + public String actor() { + return NAME; + } + + @Override + public List recipes() { + return ImmutableList.copyOf(recipes); + } + + @Override + public List recipeTargets(String recipe) { + return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); + } + + @Override + public List recipePayloads(String recipe) { + return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); + } + + /** + * Constructs an APPC request conforming to the lcm API. The actual request is constructed and + * then placed in a wrapper object used to send through DMAAP. + * + * @param onset the event that is reporting the alert for policy to perform an action + * @param operation the control loop operation specifying the actor, operation, target, etc. + * @param policy the policy the was specified from the yaml generated by CLAMP or through the + * Policy GUI/API + * @return an APPC request conforming to the lcm API using the DMAAP wrapper + */ + public static AppcLcmDmaapWrapper constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, + Policy policy, String targetVnf) { + + /* Construct an APPC request using LCM Model */ + + /* + * The actual LCM request is placed in a wrapper used to send through dmaap. The current + * version is 2.0 as of R1. + */ + AppcLcmRecipeFormatter lcmRecipeFormatter = new AppcLcmRecipeFormatter(policy.getRecipe()); + + AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); + dmaapRequest.setVersion("2.0"); + dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + operation.getSubRequestId()); + dmaapRequest.setRpcName(lcmRecipeFormatter.getUrlRecipe()); + dmaapRequest.setType("request"); + + /* This is the actual request that is placed in the dmaap wrapper. */ + final AppcLcmInput appcRequest = new AppcLcmInput(); + + /* The common header is a required field for all APPC requests. */ + AppcLcmCommonHeader requestCommonHeader = new AppcLcmCommonHeader(); + requestCommonHeader.setOriginatorId(onset.getRequestId().toString()); + requestCommonHeader.setRequestId(onset.getRequestId()); + requestCommonHeader.setSubRequestId(operation.getSubRequestId()); + + appcRequest.setCommonHeader(requestCommonHeader); + + /* + * Action Identifiers are required for APPC LCM requests. For R1, the recipes supported by + * Policy only require a vnf-id. + */ + HashMap requestActionIdentifiers = new HashMap<>(); + requestActionIdentifiers.put("vnf-id", targetVnf); + + appcRequest.setActionIdentifiers(requestActionIdentifiers); + + /* + * An action is required for all APPC requests, this will be the recipe specified in the + * policy. + */ + appcRequest.setAction(lcmRecipeFormatter.getBodyRecipe()); + + /* + * For R1, the payloads will not be required for the Restart, Rebuild, or Migrate recipes. + * APPC will populate the payload based on A&AI look up of the vnd-id provided in the action + * identifiers. + */ + if (recipeSupportsPayload(policy.getRecipe()) && payloadSupplied(policy.getPayload())) { + appcRequest.setPayload(parsePayload(policy.getPayload())); + } else { + appcRequest.setPayload(null); + } + + /* + * The APPC request must be wrapped in an input object. + */ + AppcLcmBody body = new AppcLcmBody(); + body.setInput(appcRequest); + + /* + * Once the LCM request is constructed, add it into the body of the dmaap wrapper. + */ + dmaapRequest.setBody(body); + + /* Return the request to be sent through dmaap. */ + return dmaapRequest; + } + + private static boolean payloadSupplied(Map payload) { + return payload != null && !payload.isEmpty(); + } + + private static boolean recipeSupportsPayload(String recipe) { + return !RECIPE_RESTART.equalsIgnoreCase(recipe) && !RECIPE_REBUILD.equalsIgnoreCase(recipe) + && !RECIPE_MIGRATE.equalsIgnoreCase(recipe); + } + + private static String parsePayload(Map payload) { + StringBuilder payloadString = new StringBuilder("{"); + payload.forEach( + (key, value) -> payloadString.append("\"").append(key).append("\": ").append(value).append(",")); + return payloadString.substring(0, payloadString.length() - 1) + "}"; + } + + /** + * Parses the operation attempt using the subRequestId of APPC response. + * + * @param subRequestId the sub id used to send to APPC, Policy sets this using the operation + * attempt + * + * @return the current operation attempt + */ + public static Integer parseOperationAttempt(String subRequestId) { + Integer operationAttempt; + try { + operationAttempt = Integer.parseInt(subRequestId); + } catch (NumberFormatException e) { + logger.debug("A NumberFormatException was thrown due to error in parsing the operation attempt"); + return null; + } + return operationAttempt; + } + + /** + * Processes the APPC LCM response sent from APPC. Determines if the APPC operation was + * successful/unsuccessful and maps this to the corresponding Policy result. + * + * @param dmaapResponse the dmaap wrapper message that contains the actual APPC reponse inside + * the body field + * + * @return an key-value pair that contains the Policy result and APPC response message + */ + public static SimpleEntry processResponse(AppcLcmDmaapWrapper dmaapResponse) { + AppcLcmBody appcBody = dmaapResponse.getBody(); + if (appcBody == null) { + throw new NullPointerException("APPC Body is null"); + } + + /* The actual APPC response is inside the dmaap wrapper's body.input field. */ + AppcLcmOutput appcResponse = appcBody.getOutput(); + if (appcResponse == null) { + throw new NullPointerException("APPC Response is null"); + } + + /* The message returned in the APPC response. */ + String message; + + /* The Policy result determined from the APPC Response. */ + PolicyResult result; + + /* If there is no status, Policy cannot determine if the request was successful. */ + if (appcResponse.getStatus() == null) { + message = "Policy was unable to parse APP-C response status field (it was null)."; + return new AbstractMap.SimpleEntry<>(PolicyResult.FAILURE_EXCEPTION, message); + } + + /* If there is no code, Policy cannot determine if the request was successful. */ + String responseValue = AppcLcmResponseCode.toResponseValue(appcResponse.getStatus().getCode()); + if (responseValue == null) { + message = "Policy was unable to parse APP-C response status code field."; + return new AbstractMap.SimpleEntry<>(PolicyResult.FAILURE_EXCEPTION, message); + } + + /* Save the APPC response's message for Policy notification message. */ + message = appcResponse.getStatus().getMessage(); + + /* Maps the APPC response result to a Policy result. */ + switch (responseValue) { + case AppcLcmResponseCode.ACCEPTED: + /* Nothing to do if code is accept, continue processing */ + result = null; + break; + case AppcLcmResponseCode.SUCCESS: + result = PolicyResult.SUCCESS; + break; + case AppcLcmResponseCode.FAILURE: + result = PolicyResult.FAILURE; + break; + case AppcLcmResponseCode.REJECT: + case AppcLcmResponseCode.ERROR: + default: + result = PolicyResult.FAILURE_EXCEPTION; + } + return new AbstractMap.SimpleEntry<>(result, message); + } +} diff --git a/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java b/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java deleted file mode 100644 index 393ce0ccb..000000000 --- a/models-interactions/model-actors/actor.appclcm/src/main/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProvider.java +++ /dev/null @@ -1,310 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. - * Modifications copyright (c) 2018 Nokia - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.controlloop.actor.appclcm; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.AbstractMap; -import java.util.AbstractMap.SimpleEntry; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.onap.policy.appclcm.AppcLcmBody; -import org.onap.policy.appclcm.AppcLcmCommonHeader; -import org.onap.policy.appclcm.AppcLcmDmaapWrapper; -import org.onap.policy.appclcm.AppcLcmInput; -import org.onap.policy.appclcm.AppcLcmOutput; -import org.onap.policy.appclcm.AppcLcmResponseCode; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actor.appc.AppcOperation; -import org.onap.policy.controlloop.actor.appc.ModifyConfigOperation; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor; -import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.PolicyResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AppcLcmActorServiceProvider extends BidirectionalTopicActor { - - /* - * Confirmed by Daniel, should be 'APPC'. - * The actor name defined in the yaml for both legacy operations and lcm operations is still “APPC”. Perhaps in a - * future review it would be better to distinguish them as two separate actors in the yaml but it should be okay for - * now. - */ - public static final String NAME = "APPC"; - - private static final Logger logger = LoggerFactory.getLogger(AppcLcmActorServiceProvider.class); - - /* To be used in future releases to restart a single vm */ - private static final String APPC_VM_ID = "vm-id"; - - // Strings for targets - private static final String TARGET_VM = "VM"; - private static final String TARGET_VNF = "VNF"; - - // Strings for recipes - private static final String RECIPE_RESTART = AppcLcmConstants.OPERATION_RESTART; - private static final String RECIPE_REBUILD = AppcLcmConstants.OPERATION_REBUILD; - private static final String RECIPE_MIGRATE = AppcLcmConstants.OPERATION_MIGRATE; - private static final String RECIPE_MODIFY = AppcLcmConstants.OPERATION_CONFIG_MODIFY; - - /* To be used in future releases when LCM ConfigModify is used */ - private static final String APPC_REQUEST_PARAMS = "request-parameters"; - private static final String APPC_CONFIG_PARAMS = "configuration-parameters"; - - private static final Set recipes = AppcLcmConstants.OPERATION_NAMES; - private static final ImmutableMap> targets = new ImmutableMap.Builder>() - .put(RECIPE_RESTART, ImmutableList.of(TARGET_VM)).put(RECIPE_REBUILD, ImmutableList.of(TARGET_VM)) - .put(RECIPE_MIGRATE, ImmutableList.of(TARGET_VM)).put(RECIPE_MODIFY, ImmutableList.of(TARGET_VNF)).build(); - private static final ImmutableMap> payloads = - new ImmutableMap.Builder>().put(RECIPE_RESTART, ImmutableList.of(APPC_VM_ID)) - .put(RECIPE_MODIFY, ImmutableList.of(APPC_REQUEST_PARAMS, APPC_CONFIG_PARAMS)).build(); - - /** - * Constructs the object. - */ - public AppcLcmActorServiceProvider() { - super(NAME, BidirectionalTopicActorParams.class); - - // add LCM operations first as they take precedence - for (String opname : AppcLcmConstants.OPERATION_NAMES) { - addOperator(new BidirectionalTopicOperator(NAME, opname, this, AppcLcmOperation.SELECTOR_KEYS, - AppcLcmOperation::new)); - } - - // add legacy operations - addOperator(new BidirectionalTopicOperator(NAME, ModifyConfigOperation.NAME, this, AppcOperation.SELECTOR_KEYS, - ModifyConfigOperation::new)); - } - - /** - * This actor should take precedence. - */ - @Override - public int getSequenceNumber() { - return -1; - } - - @Override - public String actor() { - return NAME; - } - - @Override - public List recipes() { - return ImmutableList.copyOf(recipes); - } - - @Override - public List recipeTargets(String recipe) { - return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList())); - } - - @Override - public List recipePayloads(String recipe) { - return ImmutableList.copyOf(payloads.getOrDefault(recipe, Collections.emptyList())); - } - - /** - * Constructs an APPC request conforming to the lcm API. The actual request is constructed and - * then placed in a wrapper object used to send through DMAAP. - * - * @param onset the event that is reporting the alert for policy to perform an action - * @param operation the control loop operation specifying the actor, operation, target, etc. - * @param policy the policy the was specified from the yaml generated by CLAMP or through the - * Policy GUI/API - * @return an APPC request conforming to the lcm API using the DMAAP wrapper - */ - public static AppcLcmDmaapWrapper constructRequest(VirtualControlLoopEvent onset, ControlLoopOperation operation, - Policy policy, String targetVnf) { - - /* Construct an APPC request using LCM Model */ - - /* - * The actual LCM request is placed in a wrapper used to send through dmaap. The current - * version is 2.0 as of R1. - */ - AppcLcmRecipeFormatter lcmRecipeFormatter = new AppcLcmRecipeFormatter(policy.getRecipe()); - - AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); - dmaapRequest.setVersion("2.0"); - dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + operation.getSubRequestId()); - dmaapRequest.setRpcName(lcmRecipeFormatter.getUrlRecipe()); - dmaapRequest.setType("request"); - - /* This is the actual request that is placed in the dmaap wrapper. */ - final AppcLcmInput appcRequest = new AppcLcmInput(); - - /* The common header is a required field for all APPC requests. */ - AppcLcmCommonHeader requestCommonHeader = new AppcLcmCommonHeader(); - requestCommonHeader.setOriginatorId(onset.getRequestId().toString()); - requestCommonHeader.setRequestId(onset.getRequestId()); - requestCommonHeader.setSubRequestId(operation.getSubRequestId()); - - appcRequest.setCommonHeader(requestCommonHeader); - - /* - * Action Identifiers are required for APPC LCM requests. For R1, the recipes supported by - * Policy only require a vnf-id. - */ - HashMap requestActionIdentifiers = new HashMap<>(); - requestActionIdentifiers.put("vnf-id", targetVnf); - - appcRequest.setActionIdentifiers(requestActionIdentifiers); - - /* - * An action is required for all APPC requests, this will be the recipe specified in the - * policy. - */ - appcRequest.setAction(lcmRecipeFormatter.getBodyRecipe()); - - /* - * For R1, the payloads will not be required for the Restart, Rebuild, or Migrate recipes. - * APPC will populate the payload based on A&AI look up of the vnd-id provided in the action - * identifiers. - */ - if (recipeSupportsPayload(policy.getRecipe()) && payloadSupplied(policy.getPayload())) { - appcRequest.setPayload(parsePayload(policy.getPayload())); - } else { - appcRequest.setPayload(null); - } - - /* - * The APPC request must be wrapped in an input object. - */ - AppcLcmBody body = new AppcLcmBody(); - body.setInput(appcRequest); - - /* - * Once the LCM request is constructed, add it into the body of the dmaap wrapper. - */ - dmaapRequest.setBody(body); - - /* Return the request to be sent through dmaap. */ - return dmaapRequest; - } - - private static boolean payloadSupplied(Map payload) { - return payload != null && !payload.isEmpty(); - } - - private static boolean recipeSupportsPayload(String recipe) { - return !RECIPE_RESTART.equalsIgnoreCase(recipe) && !RECIPE_REBUILD.equalsIgnoreCase(recipe) - && !RECIPE_MIGRATE.equalsIgnoreCase(recipe); - } - - private static String parsePayload(Map payload) { - StringBuilder payloadString = new StringBuilder("{"); - payload.forEach( - (key, value) -> payloadString.append("\"").append(key).append("\": ").append(value).append(",")); - return payloadString.substring(0, payloadString.length() - 1) + "}"; - } - - /** - * Parses the operation attempt using the subRequestId of APPC response. - * - * @param subRequestId the sub id used to send to APPC, Policy sets this using the operation - * attempt - * - * @return the current operation attempt - */ - public static Integer parseOperationAttempt(String subRequestId) { - Integer operationAttempt; - try { - operationAttempt = Integer.parseInt(subRequestId); - } catch (NumberFormatException e) { - logger.debug("A NumberFormatException was thrown due to error in parsing the operation attempt"); - return null; - } - return operationAttempt; - } - - /** - * Processes the APPC LCM response sent from APPC. Determines if the APPC operation was - * successful/unsuccessful and maps this to the corresponding Policy result. - * - * @param dmaapResponse the dmaap wrapper message that contains the actual APPC reponse inside - * the body field - * - * @return an key-value pair that contains the Policy result and APPC response message - */ - public static SimpleEntry processResponse(AppcLcmDmaapWrapper dmaapResponse) { - AppcLcmBody appcBody = dmaapResponse.getBody(); - if (appcBody == null) { - throw new NullPointerException("APPC Body is null"); - } - - /* The actual APPC response is inside the dmaap wrapper's body.input field. */ - AppcLcmOutput appcResponse = appcBody.getOutput(); - if (appcResponse == null) { - throw new NullPointerException("APPC Response is null"); - } - - /* The message returned in the APPC response. */ - String message; - - /* The Policy result determined from the APPC Response. */ - PolicyResult result; - - /* If there is no status, Policy cannot determine if the request was successful. */ - if (appcResponse.getStatus() == null) { - message = "Policy was unable to parse APP-C response status field (it was null)."; - return new AbstractMap.SimpleEntry<>(PolicyResult.FAILURE_EXCEPTION, message); - } - - /* If there is no code, Policy cannot determine if the request was successful. */ - String responseValue = AppcLcmResponseCode.toResponseValue(appcResponse.getStatus().getCode()); - if (responseValue == null) { - message = "Policy was unable to parse APP-C response status code field."; - return new AbstractMap.SimpleEntry<>(PolicyResult.FAILURE_EXCEPTION, message); - } - - /* Save the APPC response's message for Policy notification message. */ - message = appcResponse.getStatus().getMessage(); - - /* Maps the APPC response result to a Policy result. */ - switch (responseValue) { - case AppcLcmResponseCode.ACCEPTED: - /* Nothing to do if code is accept, continue processing */ - result = null; - break; - case AppcLcmResponseCode.SUCCESS: - result = PolicyResult.SUCCESS; - break; - case AppcLcmResponseCode.FAILURE: - result = PolicyResult.FAILURE; - break; - case AppcLcmResponseCode.REJECT: - case AppcLcmResponseCode.ERROR: - default: - result = PolicyResult.FAILURE_EXCEPTION; - } - return new AbstractMap.SimpleEntry<>(result, message); - } -} diff --git a/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index 403ad9859..53d2c2a7c 100644 --- a/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1 @@ -org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider \ No newline at end of file +org.onap.policy.controlloop.actor.appclcm.AppcLcmActor diff --git a/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java b/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java deleted file mode 100644 index 56ce047dd..000000000 --- a/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorServiceProviderTest.java +++ /dev/null @@ -1,457 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.controlloop.actor.appclcm; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.time.Instant; -import java.util.AbstractMap; -import java.util.HashMap; -import java.util.UUID; -import java.util.stream.Collectors; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.policy.appclcm.AppcLcmBody; -import org.onap.policy.appclcm.AppcLcmCommonHeader; -import org.onap.policy.appclcm.AppcLcmDmaapWrapper; -import org.onap.policy.appclcm.AppcLcmInput; -import org.onap.policy.appclcm.AppcLcmOutput; -import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; -import org.onap.policy.controlloop.ControlLoopEventStatus; -import org.onap.policy.controlloop.ControlLoopOperation; -import org.onap.policy.controlloop.ControlLoopTargetType; -import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.PolicyResult; -import org.onap.policy.controlloop.policy.Target; -import org.onap.policy.controlloop.policy.TargetType; -import org.onap.policy.simulators.Util; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AppcLcmActorServiceProviderTest { - - private static final String VNF01 = "vnf01"; - - private static final String VNF_ID_KEY = "vnf-id"; - - private static final String REJECT = "REJECT"; - - private static final String PARTIAL_FAILURE = "PARTIAL FAILURE"; - - private static final String FAILURE = "FAILURE"; - - private static final Logger logger = LoggerFactory.getLogger(AppcLcmActorServiceProviderTest.class); - - private static final VirtualControlLoopEvent onsetEvent; - private static final ControlLoopOperation operation; - private static final Policy policy; - private static final AppcLcmDmaapWrapper dmaapResponse; - - private static final String RECIPE_RESTART = "Restart"; - private static final String RECIPE_REBUILD = "Rebuild"; - private static final String RECIPE_MIGRATE = "Migrate"; - - static { - /* - * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a - * target type of VM. - */ - onsetEvent = new VirtualControlLoopEvent(); - onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); - onsetEvent.setRequestId(UUID.randomUUID()); - onsetEvent.setClosedLoopEventClient("tca.instance00001"); - onsetEvent.setTargetType(ControlLoopTargetType.VM); - onsetEvent.setTarget("generic-vnf.vnf-name"); - onsetEvent.setFrom("DCAE"); - onsetEvent.setClosedLoopAlarmStart(Instant.now()); - onsetEvent.setAai(new HashMap<>()); - onsetEvent.getAai().put("generic-vnf.vnf-name", "fw0001vm001fw001"); - onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); - - /* Construct an operation with an APPC actor and restart operation. */ - operation = new ControlLoopOperation(); - operation.setActor("APPC"); - operation.setOperation(RECIPE_RESTART); - operation.setTarget("VM"); - operation.setEnd(Instant.now()); - operation.setSubRequestId("1"); - - /* Construct a policy specifying to restart vm. */ - policy = new Policy(); - policy.setName("Restart the VM"); - policy.setDescription("Upon getting the trigger event, restart the VM"); - policy.setActor("APPC"); - policy.setTarget(new Target(TargetType.VNF)); - policy.setRecipe(RECIPE_RESTART); - policy.setPayload(null); - policy.setRetry(2); - policy.setTimeout(300); - - /* A sample DMAAP request wrapper. */ - AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); - dmaapRequest.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); - dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); - dmaapRequest.setType("request"); - - /* A sample DMAAP response wrapper */ - dmaapResponse = new AppcLcmDmaapWrapper(); - dmaapResponse.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); - dmaapResponse.setRpcName(policy.getRecipe().toLowerCase()); - dmaapResponse.setType("response"); - - /* A sample APPC LCM request. */ - AppcLcmInput appcRequest = new AppcLcmInput(); - - /* The following code constructs a sample APPC LCM Request */ - appcRequest.setAction("restart"); - - HashMap actionIdentifiers = new HashMap<>(); - actionIdentifiers.put(VNF_ID_KEY, "trial-vnf-003"); - - appcRequest.setActionIdentifiers(actionIdentifiers); - - AppcLcmCommonHeader commonHeader = new AppcLcmCommonHeader(); - commonHeader.setRequestId(onsetEvent.getRequestId()); - commonHeader.setSubRequestId("1"); - commonHeader.setOriginatorId(onsetEvent.getRequestId().toString()); - - appcRequest.setCommonHeader(commonHeader); - - appcRequest.setPayload(null); - - AppcLcmBody appcBody = new AppcLcmBody(); - appcBody.setInput(appcRequest); - - dmaapRequest.setBody(appcBody); - - /* The following code constructs a sample APPC LCM Response */ - AppcLcmOutput appcResponse = new AppcLcmOutput(appcRequest); - appcResponse.getStatus().setCode(400); - appcResponse.getStatus().setMessage("Restart Successful"); - - appcBody.setOutput(appcResponse); - - dmaapResponse.setBody(appcBody); - } - - /** - * Set up before test class. - * - * @throws Exception if an error occurs - */ - @BeforeClass - public static void setUpSimulator() throws Exception { - Util.buildAaiSim(); - } - - /** - * Tear down after test class. - */ - @AfterClass - public static void tearDownSimulator() { - HttpServletServerFactoryInstance.getServerFactory().destroy(); - } - - @Test - public void testConstructor() { - AppcLcmActorServiceProvider prov = new AppcLcmActorServiceProvider(); - assertEquals(-1, prov.getSequenceNumber()); - - // verify that it has the operators we expect - var expected = AppcLcmConstants.COMBINED_OPERATION_NAMES.stream().sorted().collect(Collectors.toList()); - var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); - - assertEquals(expected.toString(), actual.toString()); - } - - /** - * A test to construct an APPC LCM restart request. - */ - @Test - public void constructRestartRequestTest() { - - AppcLcmDmaapWrapper dmaapRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, policy, VNF01); - - /* The service provider must return a non null DMAAP request wrapper */ - assertNotNull(dmaapRequest); - - /* The DMAAP wrapper's type field must be request */ - assertEquals("request", dmaapRequest.getType()); - - /* The DMAAP wrapper's body field cannot be null */ - assertNotNull(dmaapRequest.getBody()); - - AppcLcmInput appcRequest = dmaapRequest.getBody().getInput(); - - /* A common header is required and cannot be null */ - assertNotNull(appcRequest.getCommonHeader()); - assertEquals(appcRequest.getCommonHeader().getRequestId(), onsetEvent.getRequestId()); - - /* An action is required and cannot be null */ - assertNotNull(appcRequest.getAction()); - assertEquals(RECIPE_RESTART, appcRequest.getAction()); - - /* Action Identifiers are required and cannot be null */ - assertNotNull(appcRequest.getActionIdentifiers()); - assertNotNull(appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); - assertEquals(VNF01, appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); - - logger.debug("APPC Request: \n" + appcRequest.toString()); - } - - /** - * A test to process a successful APPC restart response. - */ - @Test - public void processRestartResponseSuccessTest() { - AbstractMap.SimpleEntry result = - AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.SUCCESS, result.getKey()); - assertEquals("Restart Successful", result.getValue()); - } - - /** - * A test to assert that a null pointer exception is thrown if the APPC response body - * is null. - */ - @Test(expected = NullPointerException.class) - public void processNullBodyResponseTest() { - AppcLcmActorServiceProvider.processResponse(new AppcLcmDmaapWrapper()); - } - - /** - * A test to assert that a null pointer exception is thrown if the APPC response - * output is null. - */ - @Test(expected = NullPointerException.class) - public void processNullOutputResponseTest() { - AppcLcmDmaapWrapper dmaapWrapper = new AppcLcmDmaapWrapper(); - dmaapWrapper.setBody(new AppcLcmBody()); - AppcLcmActorServiceProvider.processResponse(dmaapWrapper); - } - - /** - * A test to map APPC response results to corresponding Policy results. - */ - @Test - public void appcToPolicyResultTest() { - - AbstractMap.SimpleEntry result; - - /* If APPC accepts, PolicyResult is null */ - dmaapResponse.getBody().getOutput().getStatus().setCode(100); - dmaapResponse.getBody().getOutput().getStatus().setMessage("ACCEPTED"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertNull(result.getKey()); - - /* If APPC is successful, PolicyResult is success */ - dmaapResponse.getBody().getOutput().getStatus().setCode(400); - dmaapResponse.getBody().getOutput().getStatus().setMessage("SUCCESS"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.SUCCESS, result.getKey()); - - /* If APPC returns an error, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(200); - dmaapResponse.getBody().getOutput().getStatus().setMessage("ERROR"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC rejects, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(300); - dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* Test multiple reject codes */ - dmaapResponse.getBody().getOutput().getStatus().setCode(306); - dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - dmaapResponse.getBody().getOutput().getStatus().setCode(313); - dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC returns failure, PolicyResult is failure */ - dmaapResponse.getBody().getOutput().getStatus().setCode(401); - dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE, result.getKey()); - - /* Test multiple failure codes */ - dmaapResponse.getBody().getOutput().getStatus().setCode(406); - dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE, result.getKey()); - - dmaapResponse.getBody().getOutput().getStatus().setCode(450); - dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE, result.getKey()); - - /* If APPC returns partial success, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(500); - dmaapResponse.getBody().getOutput().getStatus().setMessage("PARTIAL SUCCESS"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC returns partial failure, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(501); - dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* Test multiple partial failure codes */ - dmaapResponse.getBody().getOutput().getStatus().setCode(599); - dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - dmaapResponse.getBody().getOutput().getStatus().setCode(550); - dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - - /* If APPC code is unknown to Policy, PolicyResult is failure exception */ - dmaapResponse.getBody().getOutput().getStatus().setCode(700); - dmaapResponse.getBody().getOutput().getStatus().setMessage("UNKNOWN"); - result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); - } - - /* - * This test exercises getters not exercised in other tests. - */ - @Test - public void testMethods() { - AppcLcmActorServiceProvider sp = new AppcLcmActorServiceProvider(); - - assertEquals("APPC", sp.actor()); - assertEquals(4, sp.recipes().size()); - assertEquals("VM", sp.recipeTargets(RECIPE_RESTART).get(0)); - assertEquals("vm-id", sp.recipePayloads(RECIPE_RESTART).get(0)); - } - - @Test - public void testPayloadNotPassedWhenNotSupportedByRecipe() { - // given - Policy migratePolicy = constructPolicyWithRecipe(RECIPE_MIGRATE); - Policy rebuildPolicy = constructPolicyWithRecipe(RECIPE_REBUILD); - Policy restartPolicy = constructPolicyWithRecipe(RECIPE_RESTART); - - // when - AppcLcmDmaapWrapper migrateRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, migratePolicy, VNF01); - AppcLcmDmaapWrapper rebuildRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, rebuildPolicy, VNF01); - AppcLcmDmaapWrapper restartRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, restartPolicy, VNF01); - - // then - assertNull(migrateRequest.getBody().getInput().getPayload()); - assertNull(rebuildRequest.getBody().getInput().getPayload()); - assertNull(restartRequest.getBody().getInput().getPayload()); - } - - @Test - public void testPayloadNotPassedWhenNotSuppliedOrEmpty() { - // given - Policy noPayloadPolicy = constructHealthCheckPolicyWithPayload(null); - Policy emptyPayloadPolicy = constructHealthCheckPolicyWithPayload(new HashMap<>()); - - // when - AppcLcmDmaapWrapper noPayloadRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, noPayloadPolicy, VNF01); - AppcLcmDmaapWrapper emptyPayloadRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, emptyPayloadPolicy, VNF01); - - // then - assertNull(noPayloadRequest.getBody().getInput().getPayload()); - assertNull(emptyPayloadRequest.getBody().getInput().getPayload()); - } - - @Test - public void testPayloadParsedProperlyForSinglePayloadParameter() { - // given - HashMap payload = new HashMap<>(); - payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); - Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); - - // when - AppcLcmDmaapWrapper dmaapRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, otherPolicy, VNF01); - - // then - assertEquals("{\"requestParameters\": {\"host-ip-address\":\"10.183.37.25\"}}", - dmaapRequest.getBody().getInput().getPayload()); - } - - @Test - public void testPayloadParsedProperlyForMultiplePayloadParameters() { - // given - HashMap payload = new HashMap<>(); - payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); - payload.put("configurationParameters", - "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," - + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," - + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]"); - Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); - - // when - AppcLcmDmaapWrapper dmaapRequest = - AppcLcmActorServiceProvider.constructRequest(onsetEvent, operation, otherPolicy, VNF01); - - // then - assertEquals(dmaapRequest.getBody().getInput().getPayload(), "{\"requestParameters\": " - + "{\"host-ip-address\":\"10.183.37.25\"}," + "\"configurationParameters\": " - + "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," - + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," - + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]" + "}"); - } - - private Policy constructHealthCheckPolicyWithPayload(HashMap payload) { - return constructHealthCheckPolicyWithPayloadAndRecipe(payload, "Health-Check"); - } - - private Policy constructPolicyWithRecipe(String recipe) { - return constructHealthCheckPolicyWithPayloadAndRecipe(null, recipe); - } - - private Policy constructHealthCheckPolicyWithPayloadAndRecipe(HashMap payload, String recipe) { - Policy otherPolicy = new Policy(); - otherPolicy.setName("Perform health check"); - otherPolicy.setDescription("Upon getting the trigger event, perform health check"); - otherPolicy.setActor("APPC"); - otherPolicy.setTarget(new Target(TargetType.VNF)); - otherPolicy.setRecipe(recipe); - otherPolicy.setPayload(payload); - otherPolicy.setRetry(2); - otherPolicy.setTimeout(300); - return otherPolicy; - } -} diff --git a/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java b/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java new file mode 100644 index 000000000..e2bbb10db --- /dev/null +++ b/models-interactions/model-actors/actor.appclcm/src/test/java/org/onap/policy/controlloop/actor/appclcm/AppcLcmActorTest.java @@ -0,0 +1,457 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.appclcm; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.time.Instant; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.UUID; +import java.util.stream.Collectors; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.appclcm.AppcLcmBody; +import org.onap.policy.appclcm.AppcLcmCommonHeader; +import org.onap.policy.appclcm.AppcLcmDmaapWrapper; +import org.onap.policy.appclcm.AppcLcmInput; +import org.onap.policy.appclcm.AppcLcmOutput; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.ControlLoopTargetType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.simulators.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AppcLcmActorTest { + + private static final String VNF01 = "vnf01"; + + private static final String VNF_ID_KEY = "vnf-id"; + + private static final String REJECT = "REJECT"; + + private static final String PARTIAL_FAILURE = "PARTIAL FAILURE"; + + private static final String FAILURE = "FAILURE"; + + private static final Logger logger = LoggerFactory.getLogger(AppcLcmActorTest.class); + + private static final VirtualControlLoopEvent onsetEvent; + private static final ControlLoopOperation operation; + private static final Policy policy; + private static final AppcLcmDmaapWrapper dmaapResponse; + + private static final String RECIPE_RESTART = "Restart"; + private static final String RECIPE_REBUILD = "Rebuild"; + private static final String RECIPE_MIGRATE = "Migrate"; + + static { + /* + * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a + * target type of VM. + */ + onsetEvent = new VirtualControlLoopEvent(); + onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); + onsetEvent.setRequestId(UUID.randomUUID()); + onsetEvent.setClosedLoopEventClient("tca.instance00001"); + onsetEvent.setTargetType(ControlLoopTargetType.VM); + onsetEvent.setTarget("generic-vnf.vnf-name"); + onsetEvent.setFrom("DCAE"); + onsetEvent.setClosedLoopAlarmStart(Instant.now()); + onsetEvent.setAai(new HashMap<>()); + onsetEvent.getAai().put("generic-vnf.vnf-name", "fw0001vm001fw001"); + onsetEvent.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET); + + /* Construct an operation with an APPC actor and restart operation. */ + operation = new ControlLoopOperation(); + operation.setActor("APPC"); + operation.setOperation(RECIPE_RESTART); + operation.setTarget("VM"); + operation.setEnd(Instant.now()); + operation.setSubRequestId("1"); + + /* Construct a policy specifying to restart vm. */ + policy = new Policy(); + policy.setName("Restart the VM"); + policy.setDescription("Upon getting the trigger event, restart the VM"); + policy.setActor("APPC"); + policy.setTarget(new Target(TargetType.VNF)); + policy.setRecipe(RECIPE_RESTART); + policy.setPayload(null); + policy.setRetry(2); + policy.setTimeout(300); + + /* A sample DMAAP request wrapper. */ + AppcLcmDmaapWrapper dmaapRequest = new AppcLcmDmaapWrapper(); + dmaapRequest.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); + dmaapRequest.setRpcName(policy.getRecipe().toLowerCase()); + dmaapRequest.setType("request"); + + /* A sample DMAAP response wrapper */ + dmaapResponse = new AppcLcmDmaapWrapper(); + dmaapResponse.setCorrelationId(onsetEvent.getRequestId().toString() + "-" + "1"); + dmaapResponse.setRpcName(policy.getRecipe().toLowerCase()); + dmaapResponse.setType("response"); + + /* A sample APPC LCM request. */ + AppcLcmInput appcRequest = new AppcLcmInput(); + + /* The following code constructs a sample APPC LCM Request */ + appcRequest.setAction("restart"); + + HashMap actionIdentifiers = new HashMap<>(); + actionIdentifiers.put(VNF_ID_KEY, "trial-vnf-003"); + + appcRequest.setActionIdentifiers(actionIdentifiers); + + AppcLcmCommonHeader commonHeader = new AppcLcmCommonHeader(); + commonHeader.setRequestId(onsetEvent.getRequestId()); + commonHeader.setSubRequestId("1"); + commonHeader.setOriginatorId(onsetEvent.getRequestId().toString()); + + appcRequest.setCommonHeader(commonHeader); + + appcRequest.setPayload(null); + + AppcLcmBody appcBody = new AppcLcmBody(); + appcBody.setInput(appcRequest); + + dmaapRequest.setBody(appcBody); + + /* The following code constructs a sample APPC LCM Response */ + AppcLcmOutput appcResponse = new AppcLcmOutput(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("Restart Successful"); + + appcBody.setOutput(appcResponse); + + dmaapResponse.setBody(appcBody); + } + + /** + * Set up before test class. + * + * @throws Exception if an error occurs + */ + @BeforeClass + public static void setUpSimulator() throws Exception { + Util.buildAaiSim(); + } + + /** + * Tear down after test class. + */ + @AfterClass + public static void tearDownSimulator() { + HttpServletServerFactoryInstance.getServerFactory().destroy(); + } + + @Test + public void testConstructor() { + AppcLcmActor prov = new AppcLcmActor(); + assertEquals(-1, prov.getSequenceNumber()); + + // verify that it has the operators we expect + var expected = AppcLcmConstants.COMBINED_OPERATION_NAMES.stream().sorted().collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + } + + /** + * A test to construct an APPC LCM restart request. + */ + @Test + public void constructRestartRequestTest() { + + AppcLcmDmaapWrapper dmaapRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, policy, VNF01); + + /* The service provider must return a non null DMAAP request wrapper */ + assertNotNull(dmaapRequest); + + /* The DMAAP wrapper's type field must be request */ + assertEquals("request", dmaapRequest.getType()); + + /* The DMAAP wrapper's body field cannot be null */ + assertNotNull(dmaapRequest.getBody()); + + AppcLcmInput appcRequest = dmaapRequest.getBody().getInput(); + + /* A common header is required and cannot be null */ + assertNotNull(appcRequest.getCommonHeader()); + assertEquals(appcRequest.getCommonHeader().getRequestId(), onsetEvent.getRequestId()); + + /* An action is required and cannot be null */ + assertNotNull(appcRequest.getAction()); + assertEquals(RECIPE_RESTART, appcRequest.getAction()); + + /* Action Identifiers are required and cannot be null */ + assertNotNull(appcRequest.getActionIdentifiers()); + assertNotNull(appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); + assertEquals(VNF01, appcRequest.getActionIdentifiers().get(VNF_ID_KEY)); + + logger.debug("APPC Request: \n" + appcRequest.toString()); + } + + /** + * A test to process a successful APPC restart response. + */ + @Test + public void processRestartResponseSuccessTest() { + AbstractMap.SimpleEntry result = + AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.SUCCESS, result.getKey()); + assertEquals("Restart Successful", result.getValue()); + } + + /** + * A test to assert that a null pointer exception is thrown if the APPC response body + * is null. + */ + @Test(expected = NullPointerException.class) + public void processNullBodyResponseTest() { + AppcLcmActor.processResponse(new AppcLcmDmaapWrapper()); + } + + /** + * A test to assert that a null pointer exception is thrown if the APPC response + * output is null. + */ + @Test(expected = NullPointerException.class) + public void processNullOutputResponseTest() { + AppcLcmDmaapWrapper dmaapWrapper = new AppcLcmDmaapWrapper(); + dmaapWrapper.setBody(new AppcLcmBody()); + AppcLcmActor.processResponse(dmaapWrapper); + } + + /** + * A test to map APPC response results to corresponding Policy results. + */ + @Test + public void appcToPolicyResultTest() { + + AbstractMap.SimpleEntry result; + + /* If APPC accepts, PolicyResult is null */ + dmaapResponse.getBody().getOutput().getStatus().setCode(100); + dmaapResponse.getBody().getOutput().getStatus().setMessage("ACCEPTED"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertNull(result.getKey()); + + /* If APPC is successful, PolicyResult is success */ + dmaapResponse.getBody().getOutput().getStatus().setCode(400); + dmaapResponse.getBody().getOutput().getStatus().setMessage("SUCCESS"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.SUCCESS, result.getKey()); + + /* If APPC returns an error, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(200); + dmaapResponse.getBody().getOutput().getStatus().setMessage("ERROR"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC rejects, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(300); + dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* Test multiple reject codes */ + dmaapResponse.getBody().getOutput().getStatus().setCode(306); + dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + dmaapResponse.getBody().getOutput().getStatus().setCode(313); + dmaapResponse.getBody().getOutput().getStatus().setMessage(REJECT); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC returns failure, PolicyResult is failure */ + dmaapResponse.getBody().getOutput().getStatus().setCode(401); + dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE, result.getKey()); + + /* Test multiple failure codes */ + dmaapResponse.getBody().getOutput().getStatus().setCode(406); + dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE, result.getKey()); + + dmaapResponse.getBody().getOutput().getStatus().setCode(450); + dmaapResponse.getBody().getOutput().getStatus().setMessage(FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE, result.getKey()); + + /* If APPC returns partial success, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(500); + dmaapResponse.getBody().getOutput().getStatus().setMessage("PARTIAL SUCCESS"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC returns partial failure, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(501); + dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* Test multiple partial failure codes */ + dmaapResponse.getBody().getOutput().getStatus().setCode(599); + dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + dmaapResponse.getBody().getOutput().getStatus().setCode(550); + dmaapResponse.getBody().getOutput().getStatus().setMessage(PARTIAL_FAILURE); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + + /* If APPC code is unknown to Policy, PolicyResult is failure exception */ + dmaapResponse.getBody().getOutput().getStatus().setCode(700); + dmaapResponse.getBody().getOutput().getStatus().setMessage("UNKNOWN"); + result = AppcLcmActor.processResponse(dmaapResponse); + assertEquals(PolicyResult.FAILURE_EXCEPTION, result.getKey()); + } + + /* + * This test exercises getters not exercised in other tests. + */ + @Test + public void testMethods() { + AppcLcmActor sp = new AppcLcmActor(); + + assertEquals("APPC", sp.actor()); + assertEquals(4, sp.recipes().size()); + assertEquals("VM", sp.recipeTargets(RECIPE_RESTART).get(0)); + assertEquals("vm-id", sp.recipePayloads(RECIPE_RESTART).get(0)); + } + + @Test + public void testPayloadNotPassedWhenNotSupportedByRecipe() { + // given + Policy migratePolicy = constructPolicyWithRecipe(RECIPE_MIGRATE); + Policy rebuildPolicy = constructPolicyWithRecipe(RECIPE_REBUILD); + Policy restartPolicy = constructPolicyWithRecipe(RECIPE_RESTART); + + // when + AppcLcmDmaapWrapper migrateRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, migratePolicy, VNF01); + AppcLcmDmaapWrapper rebuildRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, rebuildPolicy, VNF01); + AppcLcmDmaapWrapper restartRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, restartPolicy, VNF01); + + // then + assertNull(migrateRequest.getBody().getInput().getPayload()); + assertNull(rebuildRequest.getBody().getInput().getPayload()); + assertNull(restartRequest.getBody().getInput().getPayload()); + } + + @Test + public void testPayloadNotPassedWhenNotSuppliedOrEmpty() { + // given + Policy noPayloadPolicy = constructHealthCheckPolicyWithPayload(null); + Policy emptyPayloadPolicy = constructHealthCheckPolicyWithPayload(new HashMap<>()); + + // when + AppcLcmDmaapWrapper noPayloadRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, noPayloadPolicy, VNF01); + AppcLcmDmaapWrapper emptyPayloadRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, emptyPayloadPolicy, VNF01); + + // then + assertNull(noPayloadRequest.getBody().getInput().getPayload()); + assertNull(emptyPayloadRequest.getBody().getInput().getPayload()); + } + + @Test + public void testPayloadParsedProperlyForSinglePayloadParameter() { + // given + HashMap payload = new HashMap<>(); + payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); + Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); + + // when + AppcLcmDmaapWrapper dmaapRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, otherPolicy, VNF01); + + // then + assertEquals("{\"requestParameters\": {\"host-ip-address\":\"10.183.37.25\"}}", + dmaapRequest.getBody().getInput().getPayload()); + } + + @Test + public void testPayloadParsedProperlyForMultiplePayloadParameters() { + // given + HashMap payload = new HashMap<>(); + payload.put("requestParameters", "{\"host-ip-address\":\"10.183.37.25\"}"); + payload.put("configurationParameters", + "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," + + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," + + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]"); + Policy otherPolicy = constructHealthCheckPolicyWithPayload(payload); + + // when + AppcLcmDmaapWrapper dmaapRequest = + AppcLcmActor.constructRequest(onsetEvent, operation, otherPolicy, VNF01); + + // then + assertEquals(dmaapRequest.getBody().getInput().getPayload(), "{\"requestParameters\": " + + "{\"host-ip-address\":\"10.183.37.25\"}," + "\"configurationParameters\": " + + "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\"," + + "\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\"," + + "\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]" + "}"); + } + + private Policy constructHealthCheckPolicyWithPayload(HashMap payload) { + return constructHealthCheckPolicyWithPayloadAndRecipe(payload, "Health-Check"); + } + + private Policy constructPolicyWithRecipe(String recipe) { + return constructHealthCheckPolicyWithPayloadAndRecipe(null, recipe); + } + + private Policy constructHealthCheckPolicyWithPayloadAndRecipe(HashMap payload, String recipe) { + Policy otherPolicy = new Policy(); + otherPolicy.setName("Perform health check"); + otherPolicy.setDescription("Upon getting the trigger event, perform health check"); + otherPolicy.setActor("APPC"); + otherPolicy.setTarget(new Target(TargetType.VNF)); + otherPolicy.setRecipe(recipe); + otherPolicy.setPayload(payload); + otherPolicy.setRetry(2); + otherPolicy.setTimeout(300); + return otherPolicy; + } +} -- cgit 1.2.3-korg