diff options
15 files changed, 1155 insertions, 0 deletions
diff --git a/controlloop/common/feature-controlloop-management/pom.xml b/controlloop/common/feature-controlloop-management/pom.xml new file mode 100644 index 000000000..aed6563b2 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/pom.xml @@ -0,0 +1,304 @@ +<!-- + ============LICENSE_START======================================================= + ONAP + ================================================================================ + Copyright (C) 2018 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========================================================= +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> + <artifactId>common</artifactId> + <version>1.4.0-SNAPSHOT</version> + </parent> + + <artifactId>feature-controlloop-management</artifactId> + + <description> + Extensions to the PDP-D to improve control loop specific management capabilities. + </description> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + + <build> + <resources> + <resource> + <directory>src/main/feature</directory> + <filtering>true</filtering> + </resource> + </resources> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>zipfile</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${project.artifactId}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <outputDirectory>${project.build.directory}/assembly/lib</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>false</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <includeScope>runtime</includeScope> + <excludeTransitive>false</excludeTransitive> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>events</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>appc</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>appclcm</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>sdnr</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>vfc</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>sdnc</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>so</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>aai</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>sdc</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>trafficgenerator</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> + <artifactId>eventmanager</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> + <artifactId>guard</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actorServiceProvider</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actor.appc</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actor.appclcm</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actor.sdnr</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actor.so</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actor.vfc</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId> + <artifactId>actor.sdnc</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> + <artifactId>policy-yaml</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + <exclusion> + <artifactId>snakeyaml</artifactId> + <groupId>org.yaml</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.att.research.xacml</groupId> + <artifactId>xacml-pdp</artifactId> + <version>1.0.2</version> + <exclusions> + <exclusion> + <artifactId>commons-codec</artifactId> + <groupId>commons-codec</groupId> + </exclusion> + <exclusion> + <artifactId>commons-logging</artifactId> + <groupId>commons-logging</groupId> + </exclusion> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + <exclusion> + <artifactId>commons-lang3</artifactId> + <groupId>org.apache.commons</groupId> + </exclusion> + <exclusion> + <artifactId>jackson-databind</artifactId> + <groupId>com.fasterxml.jackson.core</groupId> + </exclusion> + <exclusion> + <artifactId>commons-collections</artifactId> + <groupId>commons-collections</groupId> + </exclusion> + <exclusion> + <artifactId>commons-lang</artifactId> + <groupId>commons-lang</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-pdp</groupId> + <artifactId>policy-management</artifactId> + <version>${version.policy.drools-pdp}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.awaitility</groupId> + <artifactId>awaitility</artifactId> + <version>3.0.0</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/controlloop/common/feature-controlloop-management/src/assembly/zip.xml b/controlloop/common/feature-controlloop-management/src/assembly/zip.xml new file mode 100644 index 000000000..b540101bb --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/assembly/zip.xml @@ -0,0 +1,76 @@ +<!-- + ============LICENSE_START======================================================= + ONAP + ================================================================================ + Copyright (C) 2018 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========================================================= +--> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + + <id>feature-controlloop-management-package</id> + <formats> + <format>zip</format> + </formats> + + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target</directory> + <outputDirectory>lib/feature</outputDirectory> + <includes> + <include>feature-controlloop-management-${project.version}.jar</include> + </includes> + </fileSet> + <fileSet> + <directory>target/assembly/lib</directory> + <outputDirectory>lib/dependencies</outputDirectory> + <includes> + <include>*.jar</include> + </includes> + </fileSet> + <fileSet> + <directory>target/classes/config</directory> + <outputDirectory>config</outputDirectory> + <fileMode>0644</fileMode> + <excludes/> + </fileSet> + <fileSet> + <directory>src/main/feature/bin</directory> + <outputDirectory>bin</outputDirectory> + <fileMode>0755</fileMode> + <excludes/> + </fileSet> + <fileSet> + <directory>src/main/feature/db</directory> + <outputDirectory>db</outputDirectory> + <fileMode>0744</fileMode> + <excludes/> + </fileSet> + <fileSet> + <directory>src/main/feature/install</directory> + <outputDirectory>install</outputDirectory> + <fileMode>0755</fileMode> + <excludes/> + </fileSet> + </fileSets> + +</assembly> diff --git a/controlloop/common/feature-controlloop-management/src/main/java/org/onap/policy/drools/apps/controlloop/feature/management/ControlLoopManagementFeature.java b/controlloop/common/feature-controlloop-management/src/main/java/org/onap/policy/drools/apps/controlloop/feature/management/ControlLoopManagementFeature.java new file mode 100644 index 000000000..e9fb811c7 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/main/java/org/onap/policy/drools/apps/controlloop/feature/management/ControlLoopManagementFeature.java @@ -0,0 +1,92 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 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.controlloop.feature.management; + +import java.util.stream.Stream; +import org.onap.policy.controlloop.params.ControlLoopParams; +import org.onap.policy.drools.features.PolicyEngineFeatureAPI; +import org.onap.policy.drools.system.PolicyController; + +/** + * Control Loop Management Feature. + */ +public class ControlLoopManagementFeature implements PolicyEngineFeatureAPI { + + private static final String FEATURE_NAME = "controlloop-management"; + private static final int SEQNO = 1000; + + /** + * retrieves control loops. + * + * @param controllerName controller name. + * @param sessionName session name. + * @return control loops. + */ + public static Stream<ControlLoopParams> controlLoops(String controllerName, String sessionName) { + PolicyController controller = PolicyController.factory.get(controllerName); + if (controller == null) { + throw new IllegalArgumentException("Invalid Controller Name"); + } + + if (controller.getDrools().getSessionNames().stream().filter(sessionName::equals).count() <= 0) { + throw new IllegalArgumentException("Invalid Session Name"); + } + + return controller.getDrools() + .facts(sessionName, ControlLoopParams.class.getCanonicalName(), false) + .stream() + .filter(c -> c instanceof ControlLoopParams) + .map(c -> (ControlLoopParams) c); + } + + /** + * retrieves a control loop. + * + * @param controllerName controller name. + * @param sessionName session name. + * @param controlLoopName control loop name + * + * @return control loops. + */ + public static ControlLoopParams controlLoop(String controllerName, String sessionName, String controlLoopName) { + return controlLoops(controllerName, sessionName) + .filter(c -> c.getClosedLoopControlName().equals(controlLoopName)) + .findFirst() + .orElse(null); + } + + /** + * {@inheritDoc}. + */ + @Override + public int getSequenceNumber() { + return SEQNO; + } + + /** + * {@inheritDoc}. + */ + @Override + public String getName() { + return FEATURE_NAME; + } + +} diff --git a/controlloop/common/feature-controlloop-management/src/main/java/org/onap/policy/drools/server/restful/RestControlLoopManager.java b/controlloop/common/feature-controlloop-management/src/main/java/org/onap/policy/drools/server/restful/RestControlLoopManager.java new file mode 100644 index 000000000..0b4005a17 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/main/java/org/onap/policy/drools/server/restful/RestControlLoopManager.java @@ -0,0 +1,215 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 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.server.restful; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.List; +import java.util.stream.Collectors; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import org.onap.policy.controlloop.ControlLoopException; +import org.onap.policy.controlloop.params.ControlLoopParams; +import org.onap.policy.controlloop.processor.ControlLoopProcessor; +import org.onap.policy.drools.apps.controlloop.feature.management.ControlLoopManagementFeature; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.system.PolicyController; + +/** + * Telemetry Extensions for Control Loops in the PDP-D. + */ + +@Path("/policy/pdp") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@Api +public class RestControlLoopManager { + + /** + * GET control loops. + * + * @param controllerName controller name. + * @param sessionName session name. + * @return list of controller names. + */ + @GET + @Path("engine/controllers/{controller}/drools/facts/{session}/controlloops") + @ApiOperation(value = "Control Loops", notes = "Compact list", responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = 404, message = "Control Loops cannot be found")}) + public Response controlLoops( + @ApiParam(value = "Policy Controller Name", required = true) @PathParam("controller") String controllerName, + @ApiParam(value = "Drools Session Name", required = true) @PathParam("session") String sessionName) { + + try { + List<String> controlLoopNames = + ControlLoopManagementFeature.controlLoops(controllerName, sessionName) + .map(ControlLoopParams::getClosedLoopControlName) + .collect(Collectors.toList()); + + return Response.status(Response.Status.OK).entity(controlLoopNames).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } + } + + /** + * GET control loop. + * + * @param controllerName controller name. + * @param sessionName session name. + * @param controlLoopName control loop name. + * @return control loop. + */ + @GET + @Path("engine/controllers/{controller}/drools/facts/{session}/controlloops/{controlLoopName}") + @ApiOperation( value = "Control Loop", notes = "Control Loop Parameters", responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = 404, message = "The Control Loop cannot be found")}) + public Response controlLoop( + @ApiParam(value = "Policy Controller Name", required = true) @PathParam("controller") String controllerName, + @ApiParam(value = "Drools Session Name", required = true) @PathParam("session") String sessionName, + @ApiParam(value = "Control Loop Name", required = true) @PathParam("controlLoopName") String controlLoopName) { + + try { + List<ControlLoopParams> controlLoopParams = + ControlLoopManagementFeature.controlLoops(controllerName, sessionName) + .filter(c -> c.getClosedLoopControlName().equals(controlLoopName)) + .collect(Collectors.toList()); + + return Response.status(Response.Status.OK).entity(controlLoopParams).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } + } + + /** + * GET operational policy. + * + * @param controllerName controller name. + * @param sessionName session name. + * @param controlLoopName control loop name. + * @return operational policy. + */ + @GET + @Path("engine/controllers/{controller}/drools/facts/{session}/controlloops/{controlLoopName}/policy") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation( value = "Operational Policy", notes = "The policy is in yaml format") + @ApiResponses(value = {@ApiResponse(code = 404, message = "The Control Loop cannot be found"), + @ApiResponse(code = 500, message = "The Control Loop has invalid data")}) + public Response policy( + @ApiParam(value = "Policy Controller Name", required = true) @PathParam("controller") String controllerName, + @ApiParam(value = "Drools Session Name", required = true) @PathParam("session") String sessionName, + @ApiParam(value = "Control Loop Name", required = true) @PathParam("controlLoopName") String controlLoopName) { + + try { + ControlLoopParams controlLoopParams = + ControlLoopManagementFeature.controlLoops(controllerName, sessionName) + .filter(c -> c.getClosedLoopControlName().equals(controlLoopName)) + .findFirst() + .orElse(null); + + if (controlLoopParams == null || controlLoopParams.getControlLoopYaml() == null) { + return Response.status(Response.Status.NOT_FOUND).entity("Policy not found").build(); + } + + return Response.status(Status.OK) + .entity(URLDecoder.decode(controlLoopParams.getControlLoopYaml(), "UTF-8")).build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } catch (UnsupportedEncodingException e) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Unreadable Policy").build(); + } + } + + /** + * PUT an Operational Policy. + * + * @param controllerName controller name. + * @param sessionName session name. + * @param controlLoopName control loop name. + * @param policy operational policy. + * + * @return operational policy. + */ + + @PUT + @Path("engine/controllers/{controller}/drools/facts/{session}/controlloops/{controlLoopName}/policy") + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( value = "Add Operational Policy", notes = "The Operational Policy should be syntactically correct") + @ApiResponses(value = {@ApiResponse(code = 404, message = "The Control Loop cannot be found"), + @ApiResponse(code = 409, message = "The Control Loop exists"), + @ApiResponse(code = 412, message = "The Control Loop Name must be matched in the URL"), + @ApiResponse(code = 406, message = "The Operational Policy is invalid")}) + public Response opOffer( + @ApiParam(value = "Policy Controller Name", required = true) @PathParam("controller") String controllerName, + @ApiParam(value = "Drools Session Name", required = true) @PathParam("session") String sessionName, + @ApiParam(value = "Control Loop Name", required = true) @PathParam("controlLoopName") String controlLoopName, + @ApiParam(value = "Operational Policy", required = true) String policy) { + + try { + ControlLoopParams controlLoop = + ControlLoopManagementFeature.controlLoop(controllerName, sessionName, controlLoopName); + + if (controlLoop != null) { + return Response.status(Status.CONFLICT).entity(controlLoop).build(); + } + + /* validation */ + + ControlLoopProcessor controlLoopProcessor = new ControlLoopProcessor(policy); + + if (!controlLoopName.equals(controlLoopProcessor.getControlLoop().getControlLoopName())) { + return Response.status(Status.PRECONDITION_FAILED) + .entity("Control Loop Name in URL does not match the Operational Policy") + .build(); + } + + DroolsController controller = PolicyController.factory.get(controllerName).getDrools(); + + controlLoop = new ControlLoopParams(); + controlLoop.setPolicyScope(controller.getGroupId()); + controlLoop.setPolicyName(controller.getArtifactId()); + controlLoop.setPolicyVersion(controller.getVersion()); + controlLoop.setClosedLoopControlName(controlLoopName); + controlLoop.setControlLoopYaml(URLEncoder.encode(policy, "UTF-8")); + + controller.getContainer().insertAll(controlLoop); + return Response.status(Status.OK).entity(controlLoop).build(); + + } catch (IllegalArgumentException i) { + return Response.status(Response.Status.NOT_FOUND).entity(i).build(); + } catch (ControlLoopException | UnsupportedEncodingException e) { + return Response.status(Status.NOT_ACCEPTABLE).entity(e).build(); + } + } +} diff --git a/controlloop/common/feature-controlloop-management/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI b/controlloop/common/feature-controlloop-management/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI new file mode 100644 index 000000000..9f6b69fda --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI @@ -0,0 +1 @@ +org.onap.policy.drools.apps.controlloop.feature.management.ControlLoopManagementFeature diff --git a/controlloop/common/feature-controlloop-management/src/test/java/org/onap/policy/drools/apps/controlloop/feature/management/ControlLoopManagementFeatureTest.java b/controlloop/common/feature-controlloop-management/src/test/java/org/onap/policy/drools/apps/controlloop/feature/management/ControlLoopManagementFeatureTest.java new file mode 100644 index 000000000..ac9bff93b --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/java/org/onap/policy/drools/apps/controlloop/feature/management/ControlLoopManagementFeatureTest.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 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.controlloop.feature.management; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Control Loop Management Feature Test. + */ +public class ControlLoopManagementFeatureTest { + + /** + * Sequence Number Test. + */ + @Test + public void getSequenceNumber() { + Assert.assertEquals(1000, new ControlLoopManagementFeature().getSequenceNumber()); + } + + /** + * Name Test. + */ + @Test + public void getName() { + Assert.assertEquals("controlloop-management", new ControlLoopManagementFeature().getName()); + } +}
\ No newline at end of file diff --git a/controlloop/common/feature-controlloop-management/src/test/java/org/onap/policy/drools/server/restful/RestControlLoopManagerTest.java b/controlloop/common/feature-controlloop-management/src/test/java/org/onap/policy/drools/server/restful/RestControlLoopManagerTest.java new file mode 100644 index 000000000..3ed1adfe3 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/java/org/onap/policy/drools/server/restful/RestControlLoopManagerTest.java @@ -0,0 +1,183 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 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.server.restful; + +import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Response.Status; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.kie.api.builder.ReleaseId; +import org.onap.policy.common.endpoints.http.client.HttpClient; +import org.onap.policy.common.utils.network.NetworkUtil; +import org.onap.policy.drools.persistence.SystemPersistence; +import org.onap.policy.drools.properties.DroolsProperties; +import org.onap.policy.drools.system.PolicyController; +import org.onap.policy.drools.system.PolicyEngine; +import org.onap.policy.drools.util.KieUtils; +import org.onap.policy.drools.utils.logging.LoggerUtil; + +/** + * Test RestControlLoopManager. + */ +public class RestControlLoopManagerTest { + + private static final String KSESSION = "op"; + private static final String KMODULE_DRL_PATH = "src/test/resources/op.drl"; + private static final String KMODULE_POM_PATH = "src/test/resources/op.pom"; + private static final String KMODULE_PATH = "src/test/resources/op.kmodule"; + private static final String KJAR_DRL_PATH = "src/main/resources/kbop/org/onap/policy/drools/test/op.drl"; + + private static final String CONTROLLER = KSESSION; + private static final String CONTROLOOP_NAME = "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e"; + + private static final String CLIENT_CONFIG = "op-http"; + + private static final String URL_CONTEXT_PATH_CONTROLLERS = "controllers/"; + private static final String URL_CONTEXT_PATH_CONTROLLER = URL_CONTEXT_PATH_CONTROLLERS + CONTROLLER; + private static final String URL_CONTEXT_PATH_KSESSION = URL_CONTEXT_PATH_CONTROLLER + "/drools/facts/" + KSESSION; + private static final String URL_CONTEXT_PATH_CONTROLLOOPS = URL_CONTEXT_PATH_KSESSION + "/controlloops/"; + private static final String URL_CONTEXT_PATH_CONTROLLOOP = URL_CONTEXT_PATH_CONTROLLOOPS + CONTROLOOP_NAME; + private static final String URL_CONTEXT_PATH_CONTROLLOOP_POLICY = URL_CONTEXT_PATH_CONTROLLOOP + "/policy"; + + private static final String POLICY = "src/test/resources/vCPE.yaml"; + + private static final String CONTROLLER_FILE = "op-controller.properties"; + private static final String CONTROLLER_FILE_BAK = "op-controller.properties.bak"; + + /** + * test set up. + * + * @throws Exception if failure to complete the set up. + */ + @BeforeClass + public static void setUp() throws Exception { + System.setProperty("kie.maven.settings.custom", "src/test/resources/settings.xml"); + LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "WARN"); + + SystemPersistence.manager.setConfigurationDir("src/test/resources"); + PolicyEngine.manager.configure(PolicyEngine.manager.defaultTelemetryConfig()); + + ReleaseId releaseId = + KieUtils.installArtifact(Paths.get(KMODULE_PATH).toFile(), Paths.get(KMODULE_POM_PATH).toFile(), + KJAR_DRL_PATH, Paths.get(KMODULE_DRL_PATH).toFile()); + + Properties controllerProperties = new Properties(); + controllerProperties.put(DroolsProperties.RULES_GROUPID, releaseId.getGroupId()); + controllerProperties.put(DroolsProperties.RULES_ARTIFACTID, releaseId.getArtifactId()); + controllerProperties.put(DroolsProperties.RULES_VERSION, releaseId.getVersion()); + + PolicyEngine.manager.createPolicyController(CONTROLLER, controllerProperties); + PolicyEngine.manager.start(); + + HttpClient.factory.build(SystemPersistence.manager.getProperties(CLIENT_CONFIG)); + + if (!NetworkUtil.isTcpPortOpen("localhost", 9696, 6, 10000L)) { + throw new IllegalStateException("cannot connect to port 9696"); + } + + await().atMost(1, TimeUnit.MINUTES).until(isContainerAlive()); + } + + /** + * test tear down. + */ + @AfterClass + public static void tearDown() { + PolicyController.factory.get(CONTROLLER).stop(); + await().atMost(1, TimeUnit.MINUTES).until(isContainerAlive(), equalTo(Boolean.FALSE)); + + PolicyEngine.manager.removePolicyController(CONTROLLER); + PolicyEngine.manager.stop(); + + final Path controllerPath = + Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), CONTROLLER_FILE); + try { + Files.deleteIfExists(controllerPath); + } catch (Exception ignored) { + /* to satisfy checkstyle */ + ; + } + + Path controllerBakPath = + Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), CONTROLLER_FILE_BAK); + + try { + Files.deleteIfExists(controllerBakPath); + } catch (Exception ignored) { + /* to satisfy checkstyle */ + ; + } + } + + /** + * Test Operational Policies. + */ + @Test + public void testOperationalPolicy() throws IOException { + assertEquals(Status.OK.getStatusCode(), + HttpClient.factory.get(CONTROLLER).get(URL_CONTEXT_PATH_CONTROLLOOPS).getStatus()); + + assertEquals(Status.OK.getStatusCode(), + HttpClient.factory.get(CONTROLLER).get(URL_CONTEXT_PATH_CONTROLLOOP).getStatus()); + + assertEquals(Status.NOT_FOUND.getStatusCode(), + HttpClient.factory.get(CONTROLLER).get(URL_CONTEXT_PATH_CONTROLLOOP_POLICY).getStatus()); + + String policyFromFile = new String(Files.readAllBytes(Paths.get(POLICY))); + HttpClient.factory.get(CONTROLLER) + .put(URL_CONTEXT_PATH_CONTROLLOOP_POLICY, Entity.text(policyFromFile), Collections.emptyMap()); + + assertEquals(Status.OK.getStatusCode(), + HttpClient.factory.get(CONTROLLER).get(URL_CONTEXT_PATH_CONTROLLOOP_POLICY).getStatus()); + + String policyFromPdpD = HttpClient.factory.get(CONTROLLER) + .get(URL_CONTEXT_PATH_CONTROLLOOP_POLICY) + .readEntity(String.class); + + assertEquals(policyFromFile, policyFromPdpD); + + assertEquals(Status.CONFLICT.getStatusCode(), + HttpClient.factory.get(CONTROLLER).put(URL_CONTEXT_PATH_CONTROLLOOP_POLICY, + Entity.text(policyFromFile), Collections.emptyMap()).getStatus()); + } + + /** + * Test if the session is alive + * + * @return if the container is alive. + */ + private static Callable<Boolean> isContainerAlive() { + return () -> PolicyController.factory.get(CONTROLLER).getDrools().getContainer().isAlive(); + } +} diff --git a/controlloop/common/feature-controlloop-management/src/test/resources/op-http.properties b/controlloop/common/feature-controlloop-management/src/test/resources/op-http.properties new file mode 100644 index 000000000..b96c5d133 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/resources/op-http.properties @@ -0,0 +1,5 @@ +http.client.services=op + +http.client.services.op.host=localhost +http.client.services.op.port=9696 +http.client.services.op.contextUriPath=policy/pdp/engine diff --git a/controlloop/common/feature-controlloop-management/src/test/resources/op.drl b/controlloop/common/feature-controlloop-management/src/test/resources/op.drl new file mode 100644 index 000000000..48ed09929 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/resources/op.drl @@ -0,0 +1,29 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 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.controlloop.feature.management; + +import org.onap.policy.controlloop.params.ControlLoopParams; + +rule "PARAMS" +when + $params : ControlLoopParams() +then +end diff --git a/controlloop/common/feature-controlloop-management/src/test/resources/op.kmodule b/controlloop/common/feature-controlloop-management/src/test/resources/op.kmodule new file mode 100644 index 000000000..8b49eb6a0 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/resources/op.kmodule @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP + ================================================================================ + Copyright (C) 2018 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========================================================= + --> + +<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> + <kbase name="kbop"> + <ksession name="op"/> + </kbase> +</kmodule>
\ No newline at end of file diff --git a/controlloop/common/feature-controlloop-management/src/test/resources/op.pom b/controlloop/common/feature-controlloop-management/src/test/resources/op.pom new file mode 100644 index 000000000..133387217 --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/resources/op.pom @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP + ================================================================================ + Copyright (C) 2018 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========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>model-impl</artifactId> + <version>1.4.0-SNAPSHOT</version> + </parent> + + <groupId>org.onap.policy.drools.apps.test</groupId> + <artifactId>op</artifactId> + <version>1.4.0-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId> + <artifactId>events</artifactId> + <version>1.4.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/controlloop/common/feature-controlloop-management/src/test/resources/settings.xml b/controlloop/common/feature-controlloop-management/src/test/resources/settings.xml new file mode 100644 index 000000000..3d49366bb --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/resources/settings.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP + ================================================================================ + Copyright (C) 2018 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========================================================= + --> + + +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> + + <profiles> + + <profile> + <id>onap-releases</id> + <repositories> + <repository> + <id>onap-releases</id> + <name>onap-releases</name> + <url>https://nexus.onap.org/content/repositories/releases/</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + </profile> + + <profile> + <id>onap-staging</id> + <repositories> + <repository> + <id>onap-staging</id> + <name>onap-staging</name> + <url>https://nexus.onap.org/content/repositories/staging/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>always</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + </profile> + + <profile> + <id>onap-snapshots</id> + <repositories> + <repository> + <id>onap-snapshots</id> + <name>onap-snapshots</name> + <url>https://nexus.onap.org/content/repositories/snapshots/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + <updatePolicy>always</updatePolicy> + </snapshots> + </repository> + </repositories> + </profile> + </profiles> + + <activeProfiles> + <activeProfile>onap-releases</activeProfile> + <activeProfile>onap-staging</activeProfile> + <activeProfile>onap-snapshots</activeProfile> + </activeProfiles> + +</settings> diff --git a/controlloop/common/feature-controlloop-management/src/test/resources/vCPE.yaml b/controlloop/common/feature-controlloop-management/src/test/resources/vCPE.yaml new file mode 100644 index 000000000..9ab15c60e --- /dev/null +++ b/controlloop/common/feature-controlloop-management/src/test/resources/vCPE.yaml @@ -0,0 +1,37 @@ +# Copyright 2018 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. + +controlLoop: + version: 2.0.0 + controlLoopName: ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e + trigger_policy: unique-policy-id-1-restart + timeout: 3600 + abatement: false + +policies: +- id: unique-policy-id-1-restart + name: Restart the VM + description: + actor: APPC + recipe: Restart + target: + type: VM + retry: 3 + timeout: 1200 + 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
\ No newline at end of file diff --git a/controlloop/common/pom.xml b/controlloop/common/pom.xml index 294929214..c9927183d 100644 --- a/controlloop/common/pom.xml +++ b/controlloop/common/pom.xml @@ -41,6 +41,7 @@ <module>controller-casablanca</module> <module>feature-controlloop-utils</module> <module>feature-controlloop-trans</module> + <module>feature-controlloop-management</module> <module>feature-controlloop-amsterdam</module> <module>feature-controlloop-casablanca</module> <module>msb</module> diff --git a/controlloop/packages/apps-controlloop/pom.xml b/controlloop/packages/apps-controlloop/pom.xml index 4a5ac21a8..31875fc3e 100644 --- a/controlloop/packages/apps-controlloop/pom.xml +++ b/controlloop/packages/apps-controlloop/pom.xml @@ -71,6 +71,12 @@ </dependency> <dependency> <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> + <artifactId>feature-controlloop-management</artifactId> + <version>${project.version}</version> + <type>zip</type> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications.controlloop.common</groupId> <artifactId>feature-controlloop-utils</artifactId> <version>${project.version}</version> <type>zip</type> |