From 43c1e8c7c820bc8004725355a4a5eb0ad519e680 Mon Sep 17 00:00:00 2001 From: jhh Date: Thu, 20 Feb 2020 18:19:36 -0600 Subject: Tosca compliant vFirewall Issue-ID: POLICY-2376 Signed-off-by: jhh Change-Id: I362ebbd941c400a6ffc3e952e66ca2d624afbfdd Signed-off-by: jhh --- .../java/org/onap/policy/controlloop/VfwTest.java | 42 ++++++++++++++-------- .../test/resources/vcpe/tosca-compliant-vcpe.json | 2 +- .../test/resources/vfw/tosca-compliant-vfw.json | 40 +++++++++++++++++++++ .../domain/operational/OperationalTarget.java | 11 +++--- ...oop.operational.common.Drools-1.0.0.schema.json | 22 +++++++----- .../domain/operational/OperationalPolicyTest.java | 4 +-- controlloop/common/eventmanager/pom.xml | 5 +++ .../processor/ControlLoopProcessor.java | 38 ++++++++++++++------ .../processor/ControlLoopProcessorTest.java | 14 +++++--- .../resources/tosca-policy-compliant-vcpe.json | 2 +- .../test/resources/tosca-policy-compliant-vfw.json | 40 +++++++++++++++++++++ 11 files changed, 173 insertions(+), 47 deletions(-) create mode 100644 controlloop/common/controller-usecases/src/test/resources/vfw/tosca-compliant-vfw.json create mode 100644 controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vfw.json diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java index 202bd3008..3796f0bfb 100644 --- a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-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. @@ -43,7 +43,8 @@ public class VfwTest extends UsecasesBase { /** * VFW Tosca Policy File. */ - private static final String TOSCA_POLICY_VFW = "src/test/resources/vfw/tosca-vfw.json"; + private static final String TOSCA_LEGACY_POLICY_VFW = "src/test/resources/vfw/tosca-vfw.json"; + private static final String TOSCA_COMPLIANT_POLICY_VFW = "src/test/resources/vfw/tosca-compliant-vfw.json"; /* * VFW Use case Messages. @@ -85,8 +86,7 @@ public class VfwTest extends UsecasesBase { /** * Sunny day scenario for the VFW use case. */ - @Test - public void sunnyDay() throws IOException { + private void sunnyDay() throws IOException { /* Inject an ONSET event over the DCAE topic */ injectOnTopic(DCAE_TOPIC, Paths.get(ONSET)); @@ -118,6 +118,30 @@ public class VfwTest extends UsecasesBase { waitForFinalSuccess(policy, policyClMgt); } + /** + * Sunny Day with Legacy Tosca Policy. + */ + @Test + public void sunnyDayLegacy() throws InterruptedException, CoderException, IOException { + assertEquals(0, usecases.getDrools().factCount(USECASES)); + policy = setupPolicy(TOSCA_LEGACY_POLICY_VFW); + assertEquals(2, usecases.getDrools().factCount(USECASES)); + + sunnyDay(); + } + + /** + * Sunny Day with Tosca Compliant Policy. + */ + @Test + public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException { + assertEquals(0, usecases.getDrools().factCount(USECASES)); + policy = setupPolicy(TOSCA_COMPLIANT_POLICY_VFW); + assertEquals(2, usecases.getDrools().factCount(USECASES)); + + sunnyDay(); + } + /** * Observe Topics. */ @@ -146,16 +170,6 @@ public class VfwTest extends UsecasesBase { } } - /** - * Install Policy. - */ - @Before - public void installPolicy() throws IOException, CoderException, InterruptedException { - assertEquals(0, usecases.getDrools().factCount(USECASES)); - policy = setupPolicy(TOSCA_POLICY_VFW); - assertEquals(2, usecases.getDrools().factCount(USECASES)); - } - /** * Uninstall Policy. */ diff --git a/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-compliant-vcpe.json b/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-compliant-vcpe.json index c01f6898c..61fb8a648 100644 --- a/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-compliant-vcpe.json +++ b/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-compliant-vcpe.json @@ -19,7 +19,7 @@ "actor": "APPC", "operation": "Restart", "target": { - "type": "VM" + "targetType": "VM" } }, "timeout": 1200, diff --git a/controlloop/common/controller-usecases/src/test/resources/vfw/tosca-compliant-vfw.json b/controlloop/common/controller-usecases/src/test/resources/vfw/tosca-compliant-vfw.json new file mode 100644 index 000000000..c96b49c7e --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/resources/vfw/tosca-compliant-vfw.json @@ -0,0 +1,40 @@ +{ + "type": "onap.policies.controlloop.operational.common.Drools", + "type_version": "1.0.0", + "name": "operational.modifyconfig", + "version": "1.0.0", + "metadata": { + "policy-id": "operational.modifyconfig" + }, + "properties": { + "id": "ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a", + "timeout": 60, + "abatement": false, + "trigger": "unique-policy-id-1-modifyConfig", + "operations": [ + { + "id": "unique-policy-id-1-modifyConfig", + "description": "Modify the packet generator", + "operation": { + "actor": "APPC", + "operation": "ModifyConfig", + "target": { + "targetType": "VNF", + "entityIds": { + "resourceID": "bbb3cefd-01c8-413c-9bdd-2b92f9ca3d38" + } + } + }, + "timeout": 300, + "retries": 0, + "success": "final_success", + "failure": "final_failure", + "failure_timeout": "final_failure_timeout", + "failure_retries": "final_failure_retries", + "failure_exception": "final_failure_exception", + "failure_guard": "final_failure_guard" + } + ], + "controllerName": "usecases" + } +} diff --git a/controlloop/common/domains/src/main/java/org/onap/policy/drools/models/domain/operational/OperationalTarget.java b/controlloop/common/domains/src/main/java/org/onap/policy/drools/models/domain/operational/OperationalTarget.java index 9e570ba7d..66ae337d6 100644 --- a/controlloop/common/domains/src/main/java/org/onap/policy/drools/models/domain/operational/OperationalTarget.java +++ b/controlloop/common/domains/src/main/java/org/onap/policy/drools/models/domain/operational/OperationalTarget.java @@ -20,8 +20,9 @@ package org.onap.policy.drools.models.domain.operational; -import com.google.gson.annotations.SerializedName; import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; import lombok.Builder; import lombok.Data; @@ -38,11 +39,11 @@ public class OperationalTarget implements Serializable { /** * Target Type. */ - private String type; + private String targetType; /** - * Resource ID. + * Payload. */ - @SerializedName("resourceID") - private String resourceId; + @Builder.Default + private Map entityIds = new HashMap<>(); } diff --git a/controlloop/common/domains/src/main/resources/schemas/onap.policies.controlloop.operational.common.Drools-1.0.0.schema.json b/controlloop/common/domains/src/main/resources/schemas/onap.policies.controlloop.operational.common.Drools-1.0.0.schema.json index e3569f122..5d032f066 100644 --- a/controlloop/common/domains/src/main/resources/schemas/onap.policies.controlloop.operational.common.Drools-1.0.0.schema.json +++ b/controlloop/common/domains/src/main/resources/schemas/onap.policies.controlloop.operational.common.Drools-1.0.0.schema.json @@ -190,11 +190,11 @@ "type": "object", "title": "Target", "required": [ - "type" + "targetType" ], "properties": { - "type": { - "$id": "#/properties/properties/properties/operations/items/properties/operation/properties/target/properties/type", + "targetType": { + "$id": "#/properties/properties/properties/operations/items/properties/operation/properties/target/properties/targetType", "type": "string", "title": "Target Type", "examples": [ @@ -202,14 +202,17 @@ ], "pattern": "^(.+)$" }, - "resourceID": { - "$id": "#/properties/properties/properties/operations/items/properties/operation/properties/target/properties/resourceID", - "type": "string", - "title": "Resource ID", + "entityIds": { + "$id": "#/properties/properties/properties/operations/items/properties/operation/properties/target/properties/entityIds", + "type": "object", + "title": "Arbitrary Resource Identities", "examples": [ "Eace933104d443b496b8.nodes.heat.vpg" ], - "pattern": "^(.+)$" + "additionalProperties": { + "type": "string", + "pattern": "^(.+)$" + } } } }, @@ -218,7 +221,8 @@ "type": "object", "title": "Payload", "additionalProperties": { - "type": "string" + "type": "string", + "pattern": "^(.+)$" } } } diff --git a/controlloop/common/domains/src/test/java/org/onap/policy/drools/models/domain/operational/OperationalPolicyTest.java b/controlloop/common/domains/src/test/java/org/onap/policy/drools/models/domain/operational/OperationalPolicyTest.java index bab22d9ba..7fc60f2f1 100644 --- a/controlloop/common/domains/src/test/java/org/onap/policy/drools/models/domain/operational/OperationalPolicyTest.java +++ b/controlloop/common/domains/src/test/java/org/onap/policy/drools/models/domain/operational/OperationalPolicyTest.java @@ -86,7 +86,7 @@ public class OperationalPolicyTest { } @Test - public void testToscaLegacyOperationalPolicyType() throws CoderException, IOException { + public void testToscaLegacyOperationalPolicyType() throws IOException { String rawVcpeToscaPolicy = getJsonFromFile(VCPE_OPERATIONAL_LEGACY_POLICY_JSON); // valid "known" policy type with implicit schema @@ -119,7 +119,7 @@ public class OperationalPolicyTest { .actorOperation(ActorOperation.builder() .operation("Restart") .actor("APPC") - .target(OperationalTarget.builder().type("VNF").build()) + .target(OperationalTarget.builder().targetType("VNF").build()) .build()) .build())) .controllerName("usecases") diff --git a/controlloop/common/eventmanager/pom.xml b/controlloop/common/eventmanager/pom.xml index 23ac4a227..4f9bfb789 100644 --- a/controlloop/common/eventmanager/pom.xml +++ b/controlloop/common/eventmanager/pom.xml @@ -44,6 +44,11 @@ 2.5 provided + + + commons-beanutils + commons-beanutils + org.onap.policy.models.policy-models-interactions.model-actors actorServiceProvider diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java index 4cff616a0..0015e4dd7 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/processor/ControlLoopProcessor.java @@ -22,9 +22,11 @@ package org.onap.policy.controlloop.processor; import java.io.Serializable; import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; import java.net.URLDecoder; import java.util.stream.Collectors; import lombok.Getter; +import org.apache.commons.beanutils.BeanUtils; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.controlloop.ControlLoopException; import org.onap.policy.controlloop.drl.legacy.ControlLoopParams; @@ -39,13 +41,17 @@ import org.onap.policy.controlloop.policy.TargetType; import org.onap.policy.drools.domain.models.DroolsPolicy; import org.onap.policy.drools.models.domain.legacy.LegacyPolicy; import org.onap.policy.drools.models.domain.operational.OperationalPolicy; +import org.onap.policy.drools.models.domain.operational.OperationalTarget; import org.onap.policy.drools.system.PolicyEngineConstants; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; public class ControlLoopProcessor implements Serializable { private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory.getLogger(ControlLoopProcessor.class); private final ControlLoopPolicy policy; private String currentNestedPolicyId = null; @@ -107,6 +113,16 @@ public class ControlLoopProcessor implements Serializable { ControlLoopPolicy.class, ControlLoopPolicy.class.getClassLoader())).load(decodedPolicy); } + private Target toStandardTarget(OperationalTarget opTarget) { + Target target = new Target(TargetType.valueOf(opTarget.getTargetType())); + try { + BeanUtils.populate(target, opTarget.getEntityIds()); + } catch (IllegalAccessException | InvocationTargetException e) { + logger.warn("target entityIds cannot be mapped (unexpected): {}", opTarget, e); + } + return target; + } + protected ControlLoopPolicy buildPolicyFromToscaCompliant(ToscaPolicy policy) throws CoderException { OperationalPolicy domainPolicy = PolicyEngineConstants.getManager().getDomainMaker().convertTo(policy, OperationalPolicy.class); @@ -116,17 +132,17 @@ public class ControlLoopProcessor implements Serializable { // @formatter:off backwardsCompatiblePolicy.setPolicies( domainPolicy.getProperties().getOperations().stream().map(operation -> new Policy( - PolicyParam.builder() - .id(operation.getId()) - .name(operation.getActorOperation().getOperation()) - .description(operation.getDescription()) - .actor(operation.getActorOperation().getActor()) - .payload(operation.getActorOperation().getPayload()) - .recipe(operation.getActorOperation().getOperation()) - .retries(operation.getRetries()) - .timeout(operation.getTimeout()) - .target(new Target(TargetType.valueOf(operation.getActorOperation().getTarget().getType()), - operation.getActorOperation().getTarget().getResourceId())).build())) + PolicyParam.builder() + .id(operation.getId()) + .name(operation.getActorOperation().getOperation()) + .description(operation.getDescription()) + .actor(operation.getActorOperation().getActor()) + .payload(operation.getActorOperation().getPayload()) + .recipe(operation.getActorOperation().getOperation()) + .retries(operation.getRetries()) + .timeout(operation.getTimeout()) + .target(toStandardTarget(operation.getActorOperation().getTarget())) + .build())) .collect(Collectors.toList())); // @formatter:on diff --git a/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/processor/ControlLoopProcessorTest.java b/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/processor/ControlLoopProcessorTest.java index f76c0060c..a30914781 100644 --- a/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/processor/ControlLoopProcessorTest.java +++ b/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/processor/ControlLoopProcessorTest.java @@ -45,6 +45,7 @@ import org.slf4j.LoggerFactory; public class ControlLoopProcessorTest { private static final Logger logger = LoggerFactory.getLogger(ControlLoopProcessorTest.class); + private static final StandardCoder coder = new StandardCoder(); @Test public void testControlLoopProcessor() throws IOException, ControlLoopException { @@ -59,22 +60,27 @@ public class ControlLoopProcessorTest { String policy = new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-legacy-vcpe.json"))); assertNotNull( - new ControlLoopProcessor(new StandardCoder().decode(policy, ToscaPolicy.class)).getCurrentPolicy()); + new ControlLoopProcessor(coder.decode(policy, ToscaPolicy.class)).getCurrentPolicy()); } @Test public void testControlLoopFromToscaCompliant() throws IOException, CoderException, ControlLoopException { String policy = - new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-compliant-vcpe.json"))); + new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-compliant-vcpe.json"))); + assertNotNull( + new ControlLoopProcessor(coder.decode(policy, ToscaPolicy.class)).getCurrentPolicy()); + + policy = + new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-compliant-vfw.json"))); assertNotNull( - new ControlLoopProcessor(new StandardCoder().decode(policy, ToscaPolicy.class)).getCurrentPolicy()); + new ControlLoopProcessor(coder.decode(policy, ToscaPolicy.class)).getCurrentPolicy()); } @Test public void testControlLoopFromToscaCompliantBad() throws IOException, CoderException, ControlLoopException { String policy = new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-compliant-vcpe.json"))); - ToscaPolicy toscaPolicy = new StandardCoder().decode(policy, ToscaPolicy.class); + ToscaPolicy toscaPolicy = coder.decode(policy, ToscaPolicy.class); toscaPolicy.setType("onap.policies.controlloop.Operational"); assertThatThrownBy(() -> new ControlLoopProcessor(toscaPolicy)).hasCauseInstanceOf(CoderException.class); } diff --git a/controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vcpe.json b/controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vcpe.json index c01f6898c..61fb8a648 100644 --- a/controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vcpe.json +++ b/controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vcpe.json @@ -19,7 +19,7 @@ "actor": "APPC", "operation": "Restart", "target": { - "type": "VM" + "targetType": "VM" } }, "timeout": 1200, diff --git a/controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vfw.json b/controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vfw.json new file mode 100644 index 000000000..c96b49c7e --- /dev/null +++ b/controlloop/common/eventmanager/src/test/resources/tosca-policy-compliant-vfw.json @@ -0,0 +1,40 @@ +{ + "type": "onap.policies.controlloop.operational.common.Drools", + "type_version": "1.0.0", + "name": "operational.modifyconfig", + "version": "1.0.0", + "metadata": { + "policy-id": "operational.modifyconfig" + }, + "properties": { + "id": "ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a", + "timeout": 60, + "abatement": false, + "trigger": "unique-policy-id-1-modifyConfig", + "operations": [ + { + "id": "unique-policy-id-1-modifyConfig", + "description": "Modify the packet generator", + "operation": { + "actor": "APPC", + "operation": "ModifyConfig", + "target": { + "targetType": "VNF", + "entityIds": { + "resourceID": "bbb3cefd-01c8-413c-9bdd-2b92f9ca3d38" + } + } + }, + "timeout": 300, + "retries": 0, + "success": "final_success", + "failure": "final_failure", + "failure_timeout": "final_failure_timeout", + "failure_retries": "final_failure_retries", + "failure_exception": "final_failure_exception", + "failure_guard": "final_failure_guard" + } + ], + "controllerName": "usecases" + } +} -- cgit 1.2.3-korg