From dd1fd8d3f4f30766a82f7c5200400bedec683354 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Thu, 30 Jul 2020 18:05:02 -0400 Subject: Add Step classes for usecases controller Add usecases-specific classes for managing preprocessor steps. Issue-ID: POLICY-2748 Change-Id: I62a2bf8fbeb656a5017531a3f3de6a6dbad5a004 Signed-off-by: Jim Hahn --- .../apps/controller/usecases/step/AaiCqStep2.java | 66 +++ .../controller/usecases/step/AaiGetPnfStep2.java | 70 +++ .../usecases/step/AaiGetTenantStep2.java | 94 ++++ .../usecases/step/GetTargetEntityStep2.java | 60 +++ .../apps/controller/usecases/step/GuardStep2.java | 115 +++++ .../apps/controller/usecases/step/LockStep2.java | 71 +++ .../apps/controller/usecases/step/Step2.java | 433 +++++++++++++++++ .../controller/usecases/step/AaiCqStep2Test.java | 131 ++++++ .../usecases/step/AaiGetPnfStep2Test.java | 133 ++++++ .../usecases/step/AaiGetTenantStep2Test.java | 161 +++++++ .../usecases/step/GetTargetEntityStep2Test.java | 87 ++++ .../controller/usecases/step/GuardStep2Test.java | 166 +++++++ .../controller/usecases/step/LockStep2Test.java | 134 ++++++ .../apps/controller/usecases/step/Step2Test.java | 514 +++++++++++++++++++++ 14 files changed, 2235 insertions(+) create mode 100644 controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2.java create mode 100644 controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2.java create mode 100644 controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2.java create mode 100644 controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2.java create mode 100644 controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2.java create mode 100644 controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2.java create mode 100644 controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/Step2.java create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2Test.java create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2Test.java create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2Test.java create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2Test.java create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2Test.java create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2Test.java create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/Step2Test.java (limited to 'controlloop/common') diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2.java new file mode 100644 index 000000000..9ae1d7fb0 --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2.java @@ -0,0 +1,66 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.controlloop.actor.aai.AaiActor; +import org.onap.policy.controlloop.actor.aai.AaiCustomQueryOperation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; + +/** + * Wrapper for {@link AaiCustomQueryOperation}. The {@link #success(OperationOutcome)} + * method stores the resultant "tenant" object in the step's context. + */ +public class AaiCqStep2 extends Step2 { + + /** + * Constructs the object using information from another step. + * + * @param otherStep step whose information should be used + */ + public AaiCqStep2(Step2 otherStep) { + super(otherStep, AaiActor.NAME, AaiCustomQueryOperation.NAME); + } + + /** + * Skips the operation if we already have the data. + */ + @Override + public boolean start(long remainingMs) { + if (stepContext.contains(AaiCqResponse.CONTEXT_KEY)) { + // already have the data + return false; + } + + return super.start(remainingMs); + } + + /** + * Saves the response for later use. + */ + @Override + public void success(OperationOutcome outcome) { + AaiCqResponse resp = outcome.getResponse(); + stepContext.setProperty(AaiCqResponse.CONTEXT_KEY, resp); + + super.success(outcome); + } +} diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2.java new file mode 100644 index 000000000..131daef9d --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.onap.policy.controlloop.actor.aai.AaiActor; +import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; + +/** + * Wrapper for {@link AaiGetPnfOperation}. The {@link #success(OperationOutcome)} method + * stores the resultant PNF object in the step's context. + *

+ * Note: this assumes that the target entity is one of the properties returned by + * {@link AaiGetPnfOperation#getPropertyNames()}. + */ +public class AaiGetPnfStep2 extends Step2 { + + + /** + * Constructs the object using information from another step. + * + * @param otherStep step whose information should be used + */ + public AaiGetPnfStep2(Step2 otherStep) { + super(otherStep, AaiActor.NAME, AaiGetPnfOperation.NAME); + } + + /** + * Skips the operation if we already have the data. + */ + @Override + public boolean start(long remainingMs) { + if (stepContext.contains(AaiGetPnfOperation.getKey(getTargetEntity()))) { + // already have the data + return false; + } + + return super.start(remainingMs); + } + + /** + * Saves the response for later use. + */ + @Override + public void success(OperationOutcome outcome) { + StandardCoderObject resp = outcome.getResponse(); + stepContext.setProperty(AaiGetPnfOperation.getKey(getTargetEntity()), resp); + + super.success(outcome); + } +} diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2.java new file mode 100644 index 000000000..d1851dd42 --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2.java @@ -0,0 +1,94 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.onap.policy.controlloop.actor.aai.AaiActor; +import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; + +/** + * Wrapper for {@link AaiGetTenantOperation}. The vserver name is extracted from the + * enrichment data and passed as the target entity for the operation. The + * {@link #success(OperationOutcome)} method stores the resultant "tenant" object in the + * step's context. + */ +public class AaiGetTenantStep2 extends Step2 { + + private final String vserver; + + + /** + * Constructs the object using information from another step. + * + * @param otherStep step whose information should be used + */ + public AaiGetTenantStep2(Step2 otherStep) { + super(otherStep, AaiActor.NAME, AaiGetTenantOperation.NAME); + + vserver = event.getAai().get(VSERVER_VSERVER_NAME); + if (StringUtils.isBlank(vserver)) { + throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data"); + } + } + + /** + * The vserver is passed as the target entity, thus we don't need to include the + * target entity in the property list. + */ + @Override + public List getPropertyNames() { + return Collections.emptyList(); + } + + @Override + public void setProperties() { + getOperation().setProperty(OperationProperties.AAI_TARGET_ENTITY, vserver); + } + + /** + * Skips the operation if we already have the data. + */ + @Override + public boolean start(long remainingMs) { + if (stepContext.contains(AaiGetTenantOperation.getKey(vserver))) { + // already have the data + return false; + } + + return super.start(remainingMs); + } + + /** + * Saves the response for later use. + */ + @Override + public void success(OperationOutcome outcome) { + StandardCoderObject resp = outcome.getResponse(); + stepContext.setProperty(AaiGetTenantOperation.getKey(vserver), resp); + + super.success(outcome); + } +} diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2.java new file mode 100644 index 000000000..06201b13c --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.drools.apps.controller.usecases.GetTargetEntityOperation2; +import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants; + +/** + * Wrapper for {@link GetTargetEntityOperation2}. The {@link #start(long)} method always + * returns {@code false}, as the Operation should never actually be started. + */ +public class GetTargetEntityStep2 extends Step2 { + + + /** + * Constructs the object using information from another step. + * + * @param otherStep step whose information should be used + */ + public GetTargetEntityStep2(Step2 otherStep) { + super(otherStep, UsecasesConstants.GET_TARGET_ENTITY_ACTOR, UsecasesConstants.GET_TARGET_ENTITY_OPERATION); + } + + @Override + protected Operation buildOperation() { + return new GetTargetEntityOperation2(stepContext, event, params); + } + + /** + * The operation does not actually have to be executed, as it populates the target + * entity as soon as {@link Operation#setProperty(String, Object)} is invoked. + */ + @Override + public boolean start(long remainingMs) { + if (!isInitialized()) { + throw new IllegalStateException("step has not been initialized"); + } + + return false; + } +} diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2.java new file mode 100644 index 000000000..b7247ce69 --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.onap.policy.controlloop.actor.guard.DecisionOperation; +import org.onap.policy.controlloop.actor.guard.GuardActor; +import org.onap.policy.controlloop.actor.so.VfModuleCreate; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; + +/** + * Wrapper for a Guard operation. Note: this makes a clone of the operation parameters, + * replacing the payload. It overrides the operation's property names with that are + * relevant for guards. In addition, it overrides the relevant loadXxx() methods to load + * the data into the payload instead of into the operation's properties. It also + * increments or decrements the VF Count, depending whether the operation is a "VF Module + * Create" or not. + */ +public class GuardStep2 extends Step2 { + public static final String PAYLOAD_KEY_TARGET_ENTITY = "target"; + public static final String PAYLOAD_KEY_VF_COUNT = "vfCount"; + + private final Operation policyOper; + + + /** + * Constructs the object using information from another step. + * + * @param otherStep step whose information should be used + */ + public GuardStep2(Step2 otherStep, String closedLoopControlName) { + super(otherStep, GuardActor.NAME, DecisionOperation.NAME); + + if (!otherStep.isInitialized()) { + throw new IllegalStateException("policy operation must be initialized before the guard operation"); + } + + this.policyOper = otherStep.getOperation(); + + Map payload = new LinkedHashMap<>(); + payload.put("actor", otherStep.getActorName()); + payload.put("operation", otherStep.getOperationName()); + payload.put("requestId", params.getRequestId()); + payload.put("clname", closedLoopControlName); + + params = params.toBuilder().payload(payload).build(); + } + + @Override + public boolean acceptsEvent() { + return true; + } + + /** + * Builds the list of properties on the policy's actual operation. + */ + @Override + public List getPropertyNames() { + List names = new ArrayList<>(1); + + // include VF Count if the policy's operation needs it + if (policyOper.getPropertyNames().contains(OperationProperties.DATA_VF_COUNT)) { + names.add(OperationProperties.DATA_VF_COUNT); + } + + return names; + } + + /** + * Load the target entity into the payload instead of the operation's properties. + */ + @Override + protected void loadTargetEntity(String propName) { + params.getPayload().put(PAYLOAD_KEY_TARGET_ENTITY, getTargetEntity()); + } + + /** + * Load the VF Count into the payload instead of the operation's properties. + * Increments the count for "VF Module Create". Decrements it otherwise. + */ + @Override + protected void loadVfCount(String propName) { + // run guard with the proposed VF count + int count = getVfCount(); + if (VfModuleCreate.NAME.equals(policyOper.getName())) { + ++count; + } else { + --count; + } + + params.getPayload().put(PAYLOAD_KEY_VF_COUNT, count); + } +} diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2.java new file mode 100644 index 000000000..507a08116 --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.eventmanager.ActorConstants; +import org.onap.policy.drools.apps.controller.usecases.LockOperation2; + +/** + * Wrapper for the LOCK pseudo operation. Arranges for the lock's future to generate an + * outcome. + */ +public class LockStep2 extends Step2 { + + /** + * Constructs the object using information from another step. + * + * @param otherStep step whose information should be used + */ + public LockStep2(Step2 otherStep) { + super(otherStep, ActorConstants.LOCK_ACTOR, ActorConstants.LOCK_OPERATION); + } + + @Override + public boolean acceptsEvent() { + return true; + } + + @Override + public boolean start(long remainingMs) { + super.start(remainingMs); + + if (future != null) { + future.whenComplete((outcome, thrown) -> { + outcome.setFinalOutcome(true); + params.getCompleteCallback().accept(outcome); + }); + } + + /* + * ELSE: The operation must have thrown an exception. Nothing more to do as + * super.start() will have already propagated the exception to the completion + * handler. + */ + + return true; + } + + @Override + protected Operation buildOperation() { + return new LockOperation2(stepContext, params); + } +} diff --git a/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/Step2.java b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/Step2.java new file mode 100644 index 000000000..9275f791d --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/Step2.java @@ -0,0 +1,433 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ModelVer; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.Tenant; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation; +import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.eventmanager.Step; +import org.onap.policy.controlloop.eventmanager.StepContext; +import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants; + +/** + * Steps specific to the usecases controller. The {@link #setProperties()} method is used + * to load the various properties into the operation, extracting enrichment data where + * appropriate, and extracting other data from the step's context. For each property, + * there is a getXxx() method for extracting the value and a loadXxx() method for loading + * the extracted value into the operation. In addition, the + * {@link #success(OperationOutcome)} method is responsible for extracting responses from + * an operation outcome and recording the data in the step's context for use by subsequent + * steps. + */ +public class Step2 extends Step { + public static final String TARGET_INFO_MSG = "Target information"; + public static final String ENRICHMENT_PREFIX = "enrichment/"; + public static final String VSERVER_VSERVER_NAME = "vserver.vserver-name"; + public static final String RESOURCE_LINK = "resource-link"; + public static final String RESULT_DATA = "result-data"; + + private static final Map> PROPERTY_LOADER; + private static final Map> PROPERTY_SAVER; + + static { + /* + * Populate map for PROPERTY_LOADER. + */ + Map> map = new HashMap<>(); + + map.put(OperationProperties.AAI_DEFAULT_CLOUD_REGION, Step2::loadCloudRegion); + map.put(OperationProperties.AAI_DEFAULT_TENANT, Step2::loadTenant); + map.put(OperationProperties.AAI_PNF, Step2::loadPnf); + map.put(OperationProperties.AAI_RESOURCE_VNF, Step2::loadResourceVnf); + map.put(OperationProperties.AAI_SERVICE, Step2::loadService); + map.put(OperationProperties.AAI_SERVICE_MODEL, Step2::loadServiceModel); + map.put(OperationProperties.AAI_TARGET_ENTITY, Step2::loadTargetEntity); + map.put(OperationProperties.AAI_VNF, Step2::loadVnf); + map.put(OperationProperties.AAI_VNF_MODEL, Step2::loadVnfModel); + map.put(OperationProperties.AAI_VSERVER_LINK, Step2::loadVserverLink); + map.put(OperationProperties.DATA_VF_COUNT, Step2::loadVfCount); + map.put(OperationProperties.EVENT_ADDITIONAL_PARAMS, Step2::loadAdditionalEventParams); + map.put(OperationProperties.EVENT_PAYLOAD, Step2::loadEventPayload); + map.put(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES, Step2::loadOptCdsGrpcAaiProperties); + + map.put(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, Step2::loadDefaultGenericVnf); + + PROPERTY_LOADER = Collections.unmodifiableMap(map); + + + /* + * Populate map for PROPERTY_SAVER. + */ + Map> map2 = new HashMap<>(); + + map2.put(OperationProperties.DATA_VF_COUNT, Step2::storeVfCount); + + PROPERTY_SAVER = Collections.unmodifiableMap(map2); + } + + + protected final StepContext stepContext; + protected final VirtualControlLoopEvent event; + + /** + * {@code True} if the associated preprocessing steps have been loaded, {@code false} + * otherwise. + */ + @Getter + @Setter + private boolean preprocessed; + + /** + * Actions to take to store the Operation's properties back into the context. + */ + private List> postProcessors = new LinkedList<>(); + + + /** + * Constructs the object. This is used when constructing the step for the policy's + * actual operation. + * + * @param stepContext the step's context + * @param params operation parameters + * @param event the event being processed + */ + public Step2(StepContext stepContext, ControlLoopOperationParams params, VirtualControlLoopEvent event) { + super(params, new AtomicReference<>()); + this.stepContext = stepContext; + this.event = event; + } + + /** + * Constructs the object using information from another step. This is used when + * constructing a preprocessing step. + * + * @param otherStep step whose information should be used + * @param actor actor name + * @param operation operation name + */ + public Step2(Step2 otherStep, String actor, String operation) { + super(otherStep, actor, operation); + this.stepContext = otherStep.stepContext; + this.event = otherStep.event; + } + + /** + * Determines if starting this step indicates acceptance of the event. The default + * method simply invokes {@link #isPolicyStep()}. + * + * @return {@code true} if this step accepts the event, {@code false} if it is still + * indeterminate + */ + public boolean acceptsEvent() { + return isPolicyStep(); + } + + /** + * Indicates that the step succeeded with the given outcome. Invoked by the rules. The + * default method invokes the post processors. + * + * @param outcome operation's outcome + */ + public void success(OperationOutcome outcome) { + for (Consumer proc : postProcessors) { + proc.accept(this); + } + } + + /** + * Gets the names of the properties required by the operation. The default method just + * delegates to the operation to identify the properties. + * + * @return the names of the properties required by the operation + */ + public List getPropertyNames() { + return getOperation().getPropertyNames(); + } + + /** + * Sets the operation's properties. This is invoked after any preprocessor + * steps have been performed. It also adds items to {@link #postProcessors}. + */ + public void setProperties() { + postProcessors.clear(); + + for (String propName : getPropertyNames()) { + // identify the saver, if any + Consumer saver = PROPERTY_SAVER.get(propName); + if (saver != null) { + postProcessors.add(saver); + } + + + // load data + if (propName.startsWith(ENRICHMENT_PREFIX)) { + loadEnrichment(propName); + continue; + } + + BiConsumer loader = PROPERTY_LOADER.get(propName); + if (loader == null) { + throw new IllegalArgumentException("unknown property " + propName + " needed by " + getActorName() + "." + + getOperationName()); + } + + loader.accept(this, propName); + } + } + + protected void loadCloudRegion(String propName) { + getOperation().setProperty(propName, getCloudRegion()); + } + + protected void loadTenant(String propName) { + getOperation().setProperty(propName, getTenant()); + } + + protected void loadPnf(String propName) { + getOperation().setProperty(propName, getPnf()); + } + + protected void loadResourceVnf(String propName) { + getOperation().setProperty(propName, getResourceVnf()); + } + + protected void loadService(String propName) { + getOperation().setProperty(propName, getService()); + } + + protected void loadServiceModel(String propName) { + getOperation().setProperty(propName, getServiceModel()); + } + + protected void loadTargetEntity(String propName) { + getOperation().setProperty(propName, getTargetEntity()); + } + + protected void loadVnf(String propName) { + getOperation().setProperty(propName, getVnf()); + } + + protected void loadVnfModel(String propName) { + getOperation().setProperty(propName, getVnfModel()); + } + + protected void loadVserverLink(String propName) { + getOperation().setProperty(propName, getVserverLink()); + } + + protected void loadVfCount(String propName) { + getOperation().setProperty(propName, getVfCount()); + } + + protected void loadEnrichment(String propName) { + getOperation().setProperty(propName, getEnrichment(propName)); + } + + protected void loadAdditionalEventParams(String propName) { + getOperation().setProperty(propName, getAdditionalEventParams()); + } + + protected void loadEventPayload(String propName) { + getOperation().setProperty(propName, getEventPayload()); + } + + protected void loadOptCdsGrpcAaiProperties(String propName) { + // do nothing + } + + protected void loadDefaultGenericVnf(String propName) { + getOperation().setProperty(propName, getDefaultGenericVnf()); + } + + protected CloudRegion getCloudRegion() { + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getDefaultCloudRegion(); + } + + protected Tenant getTenant() { + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getDefaultTenant(); + } + + protected StandardCoderObject getPnf() { + return stepContext.getProperty(AaiGetPnfOperation.getKey(getTargetEntity())); + } + + protected GenericVnf getResourceVnf() { + verifyNotNull(TARGET_INFO_MSG, params.getTarget()); + + String resourceId = params.getTarget().getResourceID(); + + verifyNotNull("Target resource ID", resourceId); + + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getGenericVnfByModelInvariantId(resourceId); + } + + protected ServiceInstance getService() { + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getServiceInstance(); + } + + protected ModelVer getServiceModel() { + AaiCqResponse aaicq = getCustomQueryData(); + ServiceInstance service = aaicq.getServiceInstance(); + return aaicq.getModelVerByVersionId(service.getModelVersionId()); + } + + /** + * The default method assumes there is only one target entity and that it's stored + * within the step's context. + */ + protected String getTargetEntity() { + return stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY); + } + + protected GenericVnf getVnf() { + verifyNotNull(TARGET_INFO_MSG, params.getTarget()); + + String modelInvariantId = params.getTarget().getModelInvariantId(); + + verifyNotNull("modelInvariantId", modelInvariantId); + + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getGenericVnfByVfModuleModelInvariantId(modelInvariantId); + } + + protected ModelVer getVnfModel() { + GenericVnf vnf = getVnf(); + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getModelVerByVersionId(vnf.getModelVersionId()); + } + + protected String getVserverLink() { + String vserver = event.getAai().get(VSERVER_VSERVER_NAME); + if (StringUtils.isBlank(vserver)) { + throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data"); + } + + StandardCoderObject tenant = stepContext.getProperty(AaiGetTenantOperation.getKey(vserver)); + verifyNotNull("tenant data", tenant); + + String resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK); + verifyNotNull("tenant data resource-link", resourceLink); + + return stripPrefix(resourceLink, 3); + } + + protected Integer getVfCount() { + if (stepContext.contains(OperationProperties.DATA_VF_COUNT)) { + return stepContext.getProperty(OperationProperties.DATA_VF_COUNT); + } + + verifyNotNull(TARGET_INFO_MSG, params.getTarget()); + + String modelCustomizationId = params.getTarget().getModelCustomizationId(); + String modelInvariantId = params.getTarget().getModelInvariantId(); + String modelVersionId = params.getTarget().getModelVersionId(); + + verifyNotNull("target modelCustomizationId", modelCustomizationId); + verifyNotNull("target modelInvariantId", modelInvariantId); + verifyNotNull("target modelVersionId", modelVersionId); + + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getVfModuleCount(modelCustomizationId, modelInvariantId, modelVersionId); + } + + protected String getEnrichment(String propName) { + String enrichmentKey = propName.substring(ENRICHMENT_PREFIX.length()); + String value = event.getAai().get(enrichmentKey); + verifyNotNull(propName, value); + + return value; + } + + protected Map getAdditionalEventParams() { + return event.getAdditionalEventParams(); + } + + protected String getEventPayload() { + return event.getPayload(); + } + + protected GenericVnf getDefaultGenericVnf() { + AaiCqResponse aaicq = getCustomQueryData(); + return aaicq.getDefaultGenericVnf(); + } + + protected AaiCqResponse getCustomQueryData() { + AaiCqResponse aaicq = stepContext.getProperty(AaiCqResponse.CONTEXT_KEY); + verifyNotNull("custom query data", aaicq); + + return aaicq; + } + + protected void storeVfCount() { + if (!getOperation().containsProperty(OperationProperties.DATA_VF_COUNT)) { + return; + } + + int vfcount = getOperation().getProperty(OperationProperties.DATA_VF_COUNT); + stepContext.setProperty(OperationProperties.DATA_VF_COUNT, vfcount); + } + + protected void verifyNotNull(String propName, Object value) { + if (value == null) { + throw new IllegalArgumentException( + "missing " + propName + " for " + getActorName() + "." + getOperationName()); + } + } + + protected static String stripPrefix(String resourceLink, int ncomponents) { + int previdx = -1; + for (int nslashes = 0; nslashes < ncomponents; ++nslashes) { + int idx = resourceLink.indexOf('/', previdx + 1); + if (idx < 0) { + break; + } + + previdx = idx; + } + + return resourceLink.substring(Math.max(0, previdx)); + } +} diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2Test.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2Test.java new file mode 100644 index 000000000..9869c2182 --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiCqStep2Test.java @@ -0,0 +1,131 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.aai.AaiActor; +import org.onap.policy.controlloop.actor.aai.AaiCustomQueryOperation; +import org.onap.policy.controlloop.actorserviceprovider.ActorService; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; +import org.onap.policy.controlloop.eventmanager.StepContext; + +public class AaiCqStep2Test { + private static final String MY_TARGET = "my-target"; + private static final UUID REQ_ID = UUID.randomUUID(); + + @Mock + private Operator policyOperator; + @Mock + private Operation policyOperation; + @Mock + private Actor policyActor; + @Mock + private ActorService actors; + @Mock + private ControlLoopOperationParams params; + @Mock + private StepContext stepContext; + @Mock + private VirtualControlLoopEvent event; + + private CompletableFuture future; + private Step2 master; + private AaiCqStep2 step; + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + future = new CompletableFuture<>(); + + when(params.toBuilder()).thenReturn(ControlLoopOperationParams.builder().actorService(actors) + .targetEntity(MY_TARGET).requestId(REQ_ID)); + + // configure policy operation + when(actors.getActor(AaiActor.NAME)).thenReturn(policyActor); + when(policyActor.getOperator(AaiCustomQueryOperation.NAME)).thenReturn(policyOperator); + when(policyOperator.buildOperation(any())).thenReturn(policyOperation); + when(policyOperation.start()).thenReturn(future); + + master = new Step2(stepContext, params, event); + step = new AaiCqStep2(master); + } + + @Test + public void testConstructor() { + assertEquals(AaiActor.NAME, step.getActorName()); + assertEquals(AaiCustomQueryOperation.NAME, step.getOperationName()); + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + } + + @Test + public void testStart() { + step.init(); + assertTrue(step.start(100)); + verify(policyOperation).start(); + } + + /** + * Tests start() when the data has already been retrieved. + */ + @Test + public void testStartAlreadyHaveData() { + when(stepContext.contains(AaiCqResponse.CONTEXT_KEY)).thenReturn(true); + + step.init(); + assertFalse(step.start(200)); + verify(policyOperation, never()).start(); + } + + @Test + public void testSuccess() { + AaiCqResponse data = new AaiCqResponse("{}"); + OperationOutcome outcome = new OperationOutcome(); + outcome.setResponse(data); + + step.success(outcome); + verify(stepContext).setProperty(AaiCqResponse.CONTEXT_KEY, data); + } +} diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2Test.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2Test.java new file mode 100644 index 000000000..7580c2c0c --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetPnfStep2Test.java @@ -0,0 +1,133 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.aai.AaiActor; +import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation; +import org.onap.policy.controlloop.actorserviceprovider.ActorService; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; +import org.onap.policy.controlloop.eventmanager.StepContext; + +public class AaiGetPnfStep2Test { + private static final String MY_TARGET = "my-target"; + private static final UUID REQ_ID = UUID.randomUUID(); + + @Mock + private Operator policyOperator; + @Mock + private Operation policyOperation; + @Mock + private Actor policyActor; + @Mock + private ActorService actors; + @Mock + private ControlLoopOperationParams params; + @Mock + private StepContext stepContext; + @Mock + private VirtualControlLoopEvent event; + + private CompletableFuture future; + private Step2 master; + private AaiGetPnfStep2 step; + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + future = new CompletableFuture<>(); + + when(params.toBuilder()).thenReturn(ControlLoopOperationParams.builder().actorService(actors) + .requestId(REQ_ID)); + + // configure policy operation + when(actors.getActor(AaiActor.NAME)).thenReturn(policyActor); + when(policyActor.getOperator(AaiGetPnfOperation.NAME)).thenReturn(policyOperator); + when(policyOperator.buildOperation(any())).thenReturn(policyOperation); + when(policyOperation.start()).thenReturn(future); + when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET); + + master = new Step2(stepContext, params, event); + step = new AaiGetPnfStep2(master); + } + + @Test + public void testConstructor() { + assertEquals(AaiActor.NAME, step.getActorName()); + assertEquals(AaiGetPnfOperation.NAME, step.getOperationName()); + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + } + + @Test + public void testStart() { + step.init(); + assertTrue(step.start(100)); + verify(policyOperation).start(); + } + + /** + * Tests start() when the data has already been retrieved. + */ + @Test + public void testStartAlreadyHaveData() { + when(stepContext.contains(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(true); + + step.init(); + assertFalse(step.start(200)); + verify(policyOperation, never()).start(); + } + + @Test + public void testSuccess() { + StandardCoderObject data = new StandardCoderObject(); + OperationOutcome outcome = new OperationOutcome(); + outcome.setResponse(data); + + step.success(outcome); + verify(stepContext).setProperty(AaiGetPnfOperation.getKey(MY_TARGET), data); + } +} diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2Test.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2Test.java new file mode 100644 index 000000000..65c27b45f --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/AaiGetTenantStep2Test.java @@ -0,0 +1,161 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.aai.AaiActor; +import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation; +import org.onap.policy.controlloop.actorserviceprovider.ActorService; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; +import org.onap.policy.controlloop.eventmanager.StepContext; + +public class AaiGetTenantStep2Test { + private static final String MY_VSERVER = "my-vserver"; + private static final UUID REQ_ID = UUID.randomUUID(); + + @Mock + private Operator policyOperator; + @Mock + private Operation policyOperation; + @Mock + private Actor policyActor; + @Mock + private ActorService actors; + @Mock + private ControlLoopOperationParams params; + @Mock + private StepContext stepContext; + @Mock + private VirtualControlLoopEvent event; + + private CompletableFuture future; + private Step2 master; + private AaiGetTenantStep2 step; + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + future = new CompletableFuture<>(); + + when(params.toBuilder()).thenReturn(ControlLoopOperationParams.builder().actorService(actors) + .targetEntity("my-target").requestId(REQ_ID)); + + // configure policy operation + when(actors.getActor(AaiActor.NAME)).thenReturn(policyActor); + when(policyActor.getOperator(AaiGetTenantOperation.NAME)).thenReturn(policyOperator); + when(policyOperator.buildOperation(any())).thenReturn(policyOperation); + when(policyOperation.start()).thenReturn(future); + + when(event.getAai()).thenReturn(Map.of(Step2.VSERVER_VSERVER_NAME, MY_VSERVER)); + + master = new Step2(stepContext, params, event); + step = new AaiGetTenantStep2(master); + } + + @Test + public void testConstructor() { + assertEquals(AaiActor.NAME, step.getActorName()); + assertEquals(AaiGetTenantOperation.NAME, step.getOperationName()); + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + + // empty vserver name + when(event.getAai()).thenReturn(Map.of(Step2.VSERVER_VSERVER_NAME, "")); + assertThatIllegalArgumentException().isThrownBy(() -> new AaiGetTenantStep2(master)) + .withMessage("missing " + Step2.VSERVER_VSERVER_NAME + " in enrichment data"); + + // missing vserver name + when(event.getAai()).thenReturn(Map.of()); + assertThatIllegalArgumentException().isThrownBy(() -> new AaiGetTenantStep2(master)) + .withMessage("missing " + Step2.VSERVER_VSERVER_NAME + " in enrichment data"); + } + + @Test + public void testGetPropertyNames() { + assertThat(step.getPropertyNames()).isEmpty(); + } + + @Test + public void testSetProperties() { + step.init(); + + step.setProperties(); + + verify(policyOperation).setProperty(OperationProperties.AAI_TARGET_ENTITY, MY_VSERVER); + } + + @Test + public void testStart() { + step.init(); + assertTrue(step.start(100)); + verify(policyOperation).start(); + } + + /** + * Tests start() when the data has already been retrieved. + */ + @Test + public void testStartAlreadyHaveData() { + when(stepContext.contains(AaiGetTenantOperation.getKey(MY_VSERVER))).thenReturn(true); + + step.init(); + assertFalse(step.start(200)); + verify(policyOperation, never()).start(); + } + + @Test + public void testSuccess() { + StandardCoderObject data = new StandardCoderObject(); + OperationOutcome outcome = new OperationOutcome(); + outcome.setResponse(data); + + step.success(outcome); + verify(stepContext).setProperty(AaiGetTenantOperation.getKey(MY_VSERVER), data); + } +} diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2Test.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2Test.java new file mode 100644 index 000000000..965d04d7f --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GetTargetEntityStep2Test.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.eventmanager.StepContext; +import org.onap.policy.drools.apps.controller.usecases.GetTargetEntityOperation2; +import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants; + +public class GetTargetEntityStep2Test { + @Mock + private ControlLoopOperationParams params; + @Mock + private StepContext stepContext; + @Mock + private VirtualControlLoopEvent event; + + private Step2 master; + private GetTargetEntityStep2 step; + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(params.toBuilder()).thenReturn(ControlLoopOperationParams.builder()); + + master = new Step2(stepContext, params, event); + step = new GetTargetEntityStep2(master); + } + + @Test + public void testConstructor() { + assertEquals(UsecasesConstants.GET_TARGET_ENTITY_ACTOR, step.getActorName()); + assertEquals(UsecasesConstants.GET_TARGET_ENTITY_OPERATION, step.getOperationName()); + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + } + + @Test + public void testBuildOperation() { + Operation oper = step.buildOperation(); + assertTrue(oper instanceof GetTargetEntityOperation2); + } + + @Test + public void testStart() { + assertThatIllegalStateException().isThrownBy(() -> step.start(200)) + .withMessage("step has not been initialized"); + + step.init(); + assertFalse(step.start(100)); + } +} diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2Test.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2Test.java new file mode 100644 index 000000000..43319efb3 --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/GuardStep2Test.java @@ -0,0 +1,166 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.guard.DecisionOperation; +import org.onap.policy.controlloop.actor.guard.GuardActor; +import org.onap.policy.controlloop.actor.so.VfModuleCreate; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.eventmanager.StepContext; + +public class GuardStep2Test { + private static final String CL_NAME = "my-closed-loop"; + private static final String MASTER_ACTOR = "master-actor"; + private static final String MASTER_OPERATION = "master-operation"; + private static final String MY_TARGET = "my-target"; + private static final UUID REQ_ID = UUID.randomUUID(); + private static final int VF_COUNT = 10; + + @Mock + private ControlLoopEventContext context; + @Mock + private StepContext stepContext; + @Mock + private VirtualControlLoopEvent event; + @Mock + private Operation policyOper; + + private ControlLoopOperationParams params; + private Step2 master; + private GuardStep2 step; + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(event.getRequestId()).thenReturn(REQ_ID); + + when(context.getEvent()).thenReturn(event); + + when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET); + when(stepContext.contains(OperationProperties.DATA_VF_COUNT)).thenReturn(true); + when(stepContext.getProperty(OperationProperties.DATA_VF_COUNT)).thenReturn(VF_COUNT); + + + params = ControlLoopOperationParams.builder().actor(MASTER_ACTOR).operation(MASTER_OPERATION) + .targetEntity(MY_TARGET).context(context).build(); + + master = new Step2(stepContext, params, event) { + @Override + protected Operation buildOperation() { + return policyOper; + } + }; + + // force it to build the operation + master.init(); + + step = new GuardStep2(master, CL_NAME); + } + + @Test + public void testConstructor() { + assertEquals(GuardActor.NAME, step.getActorName()); + assertEquals(DecisionOperation.NAME, step.getOperationName()); + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + + // test when master is uninitialized + master = new Step2(stepContext, params, event); + assertThatIllegalStateException().isThrownBy(() -> new GuardStep2(master, CL_NAME)); + + ControlLoopOperationParams params2 = step.getParams(); + + // @formatter:off + assertThat(params2.getPayload()).isEqualTo(Map.of( + "actor", MASTER_ACTOR, + "operation", MASTER_OPERATION, + "requestId", REQ_ID, + "clname", CL_NAME)); + // @formatter:on + } + + @Test + public void testAcceptsEvent() { + // it should always accept events + assertTrue(step.acceptsEvent()); + } + + @Test + public void testGetPropertyNames() { + // unmatching property names + when(policyOper.getPropertyNames()).thenReturn(List.of("propA", "propB")); + assertThat(step.getPropertyNames()).isEmpty(); + + // matching property names + when(policyOper.getPropertyNames()).thenReturn(List.of("propA", OperationProperties.DATA_VF_COUNT, "propB")); + assertThat(step.getPropertyNames()).isEqualTo(List.of(OperationProperties.DATA_VF_COUNT)); + } + + @Test + public void testLoadTargetEntity() { + step.loadTargetEntity(OperationProperties.AAI_TARGET_ENTITY); + assertThat(step.getParams().getPayload().get(GuardStep2.PAYLOAD_KEY_TARGET_ENTITY)).isEqualTo(MY_TARGET); + } + + /** + * Tests loadVfCount() when the policy operation is NOT "VF Module Create". + */ + @Test + public void testLoadVfCountNotVfModuleCreate() { + // should decrement the count + step.loadVfCount(""); + assertThat(step.getParams().getPayload().get(GuardStep2.PAYLOAD_KEY_VF_COUNT)).isEqualTo(VF_COUNT - 1); + } + + /** + * Tests loadVfCount() when the policy operation is "VF Module Create". + */ + @Test + public void testLoadVfCountVfModuleCreate() { + when(policyOper.getName()).thenReturn(VfModuleCreate.NAME); + + // should increment the count + step.loadVfCount(""); + assertThat(step.getParams().getPayload().get(GuardStep2.PAYLOAD_KEY_VF_COUNT)).isEqualTo(VF_COUNT + 1); + } +} diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2Test.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2Test.java new file mode 100644 index 000000000..2afd39547 --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/LockStep2Test.java @@ -0,0 +1,134 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.eventmanager.ActorConstants; +import org.onap.policy.controlloop.eventmanager.StepContext; + +public class LockStep2Test { + private static final String MY_TARGET = "my-target"; + + @Mock + private StepContext stepContext; + @Mock + private Operation policyOper; + @Mock + private VirtualControlLoopEvent event; + @Mock + private Consumer callback; + + private ControlLoopOperationParams params; + private CompletableFuture future; + private Step2 master; + private LockStep2 step; + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + future = new CompletableFuture<>(); + + when(stepContext.requestLock(MY_TARGET)).thenReturn(future); + when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET); + + params = ControlLoopOperationParams.builder().completeCallback(callback).build(); + + master = new Step2(stepContext, params, event) { + @Override + protected Operation buildOperation() { + return policyOper; + } + }; + + // force it to build the operation + master.init(); + + step = new LockStep2(master); + } + + @Test + public void testConstructor() { + assertEquals(ActorConstants.LOCK_ACTOR, step.getActorName()); + assertEquals(ActorConstants.LOCK_OPERATION, step.getOperationName()); + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + } + + @Test + public void testAcceptsEvent() { + // it should always accept events + assertTrue(step.acceptsEvent()); + } + + @Test + public void testStart() { + // start the operation + step.init(); + step.setProperties(); + assertTrue(step.start(100)); + + // complete the operation's future + OperationOutcome outcome = params.makeOutcome(); + outcome.setTarget(MY_TARGET); + + future.complete(outcome); + + // ensure it invoked the callback + verify(callback).accept(outcome); + } + + /** + * Tests start when the operation throws an exception. + */ + @Test + public void testStartNoFuture() { + // start the operation + step.init(); + + // force an exception by NOT invoking setProperties() + + assertTrue(step.start(100)); + + // should have already invoked the callback + verify(callback).accept(any()); + } +} diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/Step2Test.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/Step2Test.java new file mode 100644 index 000000000..75fe486ed --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/Step2Test.java @@ -0,0 +1,514 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.drools.apps.controller.usecases.step; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.LinkedBlockingQueue; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ModelVer; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.Tenant; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation; +import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation; +import org.onap.policy.controlloop.actorserviceprovider.ActorService; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; +import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager2; +import org.onap.policy.controlloop.eventmanager.StepContext; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants; + +public class Step2Test { + private static final UUID REQ_ID = UUID.randomUUID(); + private static final String POLICY_ID = "my-policy"; + private static final String POLICY_ACTOR = "my-actor"; + private static final String POLICY_OPERATION = "my-operation"; + private static final String MY_TARGET = "my-target"; + private static final String PAYLOAD_KEY = "payload-key"; + private static final String PAYLOAD_VALUE = "payload-value"; + private static final Integer POLICY_RETRY = 3; + private static final Integer POLICY_TIMEOUT = 20; + private static final String NO_SLASH = "noslash"; + private static final String ONE_SLASH = "/one"; + + @Mock + private Operator policyOperator; + @Mock + private Operation policyOperation; + @Mock + private Actor policyActor; + @Mock + private ActorService actors; + @Mock + private StepContext stepContext; + @Mock + private AaiCqResponse aaicq; + + private CompletableFuture future; + private Target target; + private Map payload; + private Policy policy; + private VirtualControlLoopEvent event; + private ControlLoopEventContext context; + private BlockingQueue starts; + private BlockingQueue completions; + private ControlLoopOperationParams params; + private Step2 step; + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + future = new CompletableFuture<>(); + + // configure policy operation + when(actors.getActor(POLICY_ACTOR)).thenReturn(policyActor); + when(policyActor.getOperator(POLICY_OPERATION)).thenReturn(policyOperator); + when(policyOperator.buildOperation(any())).thenReturn(policyOperation); + when(policyOperation.start()).thenReturn(future); + + when(policyOperation.getPropertyNames()).thenReturn(List.of()); + + when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(aaicq); + + target = new Target(); + target.setType(TargetType.VM); + + payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE); + + policy = new Policy(); + policy.setId(POLICY_ID); + policy.setActor(POLICY_ACTOR); + policy.setRecipe(POLICY_OPERATION); + policy.setTarget(target); + policy.setPayload(payload); + policy.setRetry(POLICY_RETRY); + policy.setTimeout(POLICY_TIMEOUT); + + event = new VirtualControlLoopEvent(); + event.setRequestId(REQ_ID); + event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME); + event.setAai(new TreeMap<>(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET))); + + context = new ControlLoopEventContext(event); + + starts = new LinkedBlockingQueue<>(); + completions = new LinkedBlockingQueue<>(); + + params = ControlLoopOperationParams.builder().actor(POLICY_ACTOR).actorService(actors) + .completeCallback(completions::add).context(context).executor(ForkJoinPool.commonPool()) + .operation(POLICY_OPERATION).payload(new TreeMap<>(payload)).startCallback(starts::add) + .target(target).targetEntity(MY_TARGET).build(); + + step = new Step2(stepContext, params, event); + step.init(); + } + + @Test + public void testConstructor() { + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + assertSame(actors, step.getParams().getActorService()); + } + + @Test + public void testConstructorStep2() { + step = new Step2(step, "actorB", "operationB"); + assertSame(stepContext, step.stepContext); + assertSame(event, step.event); + + assertEquals("actorB", step.getActorName()); + assertEquals("operationB", step.getOperationName()); + assertSame(actors, step.getParams().getActorService()); + } + + @Test + public void testAcceptsEvent() { + // it's a policy step, thus it accepts events + assertTrue(step.acceptsEvent()); + + step = new Step2(step, "actorB", "operationB"); + + // it's not a policy step, thus it does not accept events + assertFalse(step.acceptsEvent()); + } + + @Test + public void testSuccess() { + assertThatCode(() -> step.success(null)).doesNotThrowAnyException(); + } + + @Test + public void testGetPropertyNames() { + // empty property list + assertThat(step.getPropertyNames()).isEmpty(); + + // try with non-empty list + when(policyOperation.getPropertyNames()).thenReturn(List.of("propA", "propB")); + assertThat(step.getPropertyNames()).isEqualTo(List.of("propA", "propB")); + } + + @Test + public void testSetProperties() { + CloudRegion cloudRegion = new CloudRegion(); + when(aaicq.getDefaultCloudRegion()).thenReturn(cloudRegion); + + Tenant tenant = new Tenant(); + when(aaicq.getDefaultTenant()).thenReturn(tenant); + + when(policyOperation.getPropertyNames()).thenReturn( + List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT)); + + step.setProperties(); + + // should have been exactly two properties set + verify(policyOperation, times(2)).setProperty(any(), any()); + verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion); + verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant); + } + + /** + * Tests setProperties() when the property is unknown. + */ + @Test + public void testSetPropertiesUnknown() { + when(policyOperation.getPropertyNames()).thenReturn(List.of("unknown-property")); + + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessage("unknown property unknown-property needed by my-actor.my-operation"); + } + + @Test + public void testLoadCloudRegion_testGetCloudRegion() { + CloudRegion data = new CloudRegion(); + when(aaicq.getDefaultCloudRegion()).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data); + } + + @Test + public void testLoadTenant_testGetTenant() { + Tenant data = new Tenant(); + when(aaicq.getDefaultTenant()).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_TENANT)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data); + } + + @Test + public void testLoadPnf_testGetPnf() { + StandardCoderObject data = new StandardCoderObject(); + when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET); + when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_PNF)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data); + } + + @Test + public void testLoadResourceVnf_testGetResourceVnf() { + target.setResourceID("my-resource"); + GenericVnf data = new GenericVnf(); + when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_RESOURCE_VNF)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data); + + // missing resource ID + target.setResourceID(null); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing Target resource ID"); + + // missing target + params = params.toBuilder().target(null).build(); + step = new Step2(stepContext, params, event); + step.init(); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining(Step2.TARGET_INFO_MSG); + } + + @Test + public void testLoadService_testGetService() { + ServiceInstance data = new ServiceInstance(); + when(aaicq.getServiceInstance()).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data); + } + + @Test + public void testLoadServiceModel_testGetServiceModel() { + ServiceInstance service = new ServiceInstance(); + service.setModelVersionId("my-service-version"); + when(aaicq.getServiceInstance()).thenReturn(service); + + ModelVer data = new ModelVer(); + when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE_MODEL)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data); + } + + @Test + public void testLoadVnf_testGetVnf() { + target.setModelInvariantId("my-model-invariant"); + GenericVnf data = new GenericVnf(); + when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data); + + // missing model invariant ID + target.setModelInvariantId(null); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing modelInvariantId"); + + // missing target + params = params.toBuilder().target(null).build(); + step = new Step2(stepContext, params, event); + step.init(); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining(Step2.TARGET_INFO_MSG); + } + + @Test + public void testLoadVnfModel_testGetVnfModel() { + target.setModelInvariantId("my-model-invariant"); + GenericVnf vnf = new GenericVnf(); + when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(vnf); + + vnf.setModelVersionId("my-vnf-model-version-id"); + ModelVer data = new ModelVer(); + when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF_MODEL)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data); + } + + @Test + public void testLoadVserverLink_testGetVserverLink() { + event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "vserverB")); + + StandardCoderObject tenant = mock(StandardCoderObject.class); + when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(tenant); + + when(tenant.getString("result-data", 0, "resource-link")).thenReturn("/aai/v7/some/link/bbb"); + + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VSERVER_LINK)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.AAI_VSERVER_LINK, "/some/link/bbb"); + + // missing resource link + when(tenant.getString("result-data", 0, "resource-link")).thenReturn(null); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing tenant data resource-link"); + + // missing tenant data + when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(null); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing tenant data for"); + + // empty vserver name + event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "")); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing vserver.vserver-name"); + + // missing vserver name + event.setAai(Map.of()); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing vserver.vserver-name"); + } + + @Test + public void testLoadVfCount_testGetVfCount() { + target.setModelCustomizationId("vf-count-customization"); + target.setModelInvariantId("vf-count-invariant"); + target.setModelVersionId("vf-count-version"); + when(aaicq.getVfModuleCount("vf-count-customization", "vf-count-invariant", "vf-count-version")).thenReturn(11); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.DATA_VF_COUNT)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 11); + + // missing model version id + target.setModelVersionId(null); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing target modelVersionId"); + + // missing model invariant id + target.setModelInvariantId(null); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing target modelInvariantId"); + + // missing model customization id + target.setModelCustomizationId(null); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining("missing target modelCustomizationId"); + + // missing target + params = params.toBuilder().target(null).build(); + step = new Step2(stepContext, params, event); + step.init(); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()) + .withMessageContaining(Step2.TARGET_INFO_MSG); + + // get it from the step context + when(stepContext.contains(OperationProperties.DATA_VF_COUNT)).thenReturn(true); + when(stepContext.getProperty(OperationProperties.DATA_VF_COUNT)).thenReturn(22); + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 22); + } + + @Test + public void testLoadEnrichment_testGetEnrichment() { + event.setAai(Map.of("bandwidth", "bandwidth-value")); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.ENRICHMENT_BANDWIDTH)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, "bandwidth-value"); + + // missing enrichment data + event.setAai(Map.of()); + assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties()); + } + + @Test + public void testLoadAdditionalEventParams_testGetAdditionalEventParams() { + Map data = Map.of("addA", "add-valueA", "addB", "add-valueB"); + event.setAdditionalEventParams(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_ADDITIONAL_PARAMS)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, data); + } + + @Test + public void testLoadEventPayload_testGetEventPayload() { + event.setPayload("some-event-payload"); + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_PAYLOAD)); + + step.setProperties(); + verify(policyOperation).setProperty(OperationProperties.EVENT_PAYLOAD, "some-event-payload"); + } + + @Test + public void testLoadOptCdsGrpcAaiProperties() { + when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES)); + + step.setProperties(); + verify(policyOperation, never()).setProperty(any(), anyString()); + } + + @Test + public void testLoadDefaultGenericVnf_testGetDefaultGenericVnf() { + GenericVnf data = new GenericVnf(); + when(aaicq.getDefaultGenericVnf()).thenReturn(data); + when(policyOperation.getPropertyNames()).thenReturn(List.of(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF)); + + step.setProperties(); + verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data); + } + + @Test + public void testGetCustomQueryData() { + assertSame(aaicq, step.getCustomQueryData()); + + when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(null); + + assertThatIllegalArgumentException().isThrownBy(() -> step.getCustomQueryData()) + .withMessage("missing custom query data for my-actor.my-operation"); + } + + @Test + public void testVerifyNotNull() { + assertThatCode(() -> step.verifyNotNull("verifyA", "verify-value-A")).doesNotThrowAnyException(); + + assertThatIllegalArgumentException().isThrownBy(() -> step.verifyNotNull("verifyB", null)) + .withMessage("missing verifyB for my-actor.my-operation"); + } + + @Test + public void testStripPrefix() { + assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 0)); + assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 1)); + assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 2)); + + assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 1)); + assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 2)); + + assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 2)); + assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 3)); + + assertEquals("/and/more", Step2.stripPrefix("/three/slashes/and/more", 3)); + + assertEquals("/and/more", Step2.stripPrefix("prefix/three/slashes/and/more", 3)); + } + +} -- cgit 1.2.3-korg