Initial lifecycle state machine. 55/83555/2
authorJorge Hernandez <jorge.hernandez-herrero@att.com>
Thu, 28 Mar 2019 06:12:10 +0000 (01:12 -0500)
committerjhh <jorge.hernandez-herrero@att.com>
Wed, 3 Apr 2019 01:48:41 +0000 (20:48 -0500)
Basic state machine and initial functionality to
transition to the Active state via Engine commands and
StateUpdate messages.

Change-Id: I8212bd264dbbea446d4e682918f9360e3984887f
Issue-ID: POLICY-1608
Signed-off-by: Jorge Hernandez <jorge.hernandez-herrero@att.com>
Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
29 files changed:
feature-lifecycle/lombok.config [new file with mode: 0644]
feature-lifecycle/pom.xml [new file with mode: 0644]
feature-lifecycle/src/assembly/zip.xml [new file with mode: 0644]
feature-lifecycle/src/main/feature/config/feature-lifecycle.properties [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateSafe.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTest.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java [new file with mode: 0644]
feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureAPI [new file with mode: 0644]
feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI [new file with mode: 0644]
feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI [new file with mode: 0644]
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java [new file with mode: 0644]
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java [new file with mode: 0644]
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateSafeTest.java [new file with mode: 0644]
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java [new file with mode: 0644]
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTestTest.java [new file with mode: 0644]
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupportedTest.java [new file with mode: 0644]
feature-lifecycle/src/test/resources/echo.drl [new file with mode: 0644]
feature-lifecycle/src/test/resources/echo.kmodule [new file with mode: 0644]
feature-lifecycle/src/test/resources/echo.pom [new file with mode: 0644]
feature-lifecycle/src/test/resources/feature-lifecycle.properties [new file with mode: 0644]
policy-management/pom.xml
pom.xml

diff --git a/feature-lifecycle/lombok.config b/feature-lifecycle/lombok.config
new file mode 100644 (file)
index 0000000..2384843
--- /dev/null
@@ -0,0 +1,3 @@
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = true
+lombok.nonNull.exceptionType = IllegalArgumentException
diff --git a/feature-lifecycle/pom.xml b/feature-lifecycle/pom.xml
new file mode 100644 (file)
index 0000000..fa3aff6
--- /dev/null
@@ -0,0 +1,126 @@
+<!--
+  ============LICENSE_START=======================================================
+  ONAP
+  ================================================================================
+  Copyright (C) 2019 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-pdp</groupId>
+        <artifactId>drools-pdp</artifactId>
+        <version>1.4.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>feature-lifecycle</artifactId>
+
+    <name>feature-lifecycle</name>
+    <description>Loadable module to support the lifecycle modes</description>
+
+    <properties>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+    </properties>
+
+    <build>
+        <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>true</excludeTransitive>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.onap.policy.drools-pdp</groupId>
+            <artifactId>policy-management</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</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/feature-lifecycle/src/assembly/zip.xml b/feature-lifecycle/src/assembly/zip.xml
new file mode 100644 (file)
index 0000000..a59418b
--- /dev/null
@@ -0,0 +1,70 @@
+<!--
+  ============LICENSE_START=======================================================
+  ONAP
+  ================================================================================
+  Copyright (C) 2019 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-lifecycle</id>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory>lib/feature</outputDirectory>
+            <includes>
+                <include>feature-lifecycle-${project.version}.jar</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target/assembly/lib</directory>
+            <outputDirectory>lib/dependencies</outputDirectory>
+            <includes>
+                <include>*.jar</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>src/main/feature/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/install</directory>
+            <outputDirectory>install</outputDirectory>
+            <fileMode>0755</fileMode>
+            <excludes/>
+        </fileSet>
+    </fileSets>
+
+</assembly>
diff --git a/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties b/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties
new file mode 100644 (file)
index 0000000..2cdc2ab
--- /dev/null
@@ -0,0 +1,34 @@
+# ============LICENSE_START=======================================================
+# ONAP
+# ================================================================================
+# Copyright (C) 2019 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=========================================================
+
+dmaap.source.topics=POLICY-PDP-PAP
+dmaap.sink.topics=POLICY-PDP-PAP
+
+dmaap.source.topics.POLICY-PDP-PAP.servers=${env:DMAAP_SERVERS}
+dmaap.source.topics.POLICY-PDP-PAP.effectiveTopic=${env:POLICY_PDP_PAP_TOPIC}
+dmaap.source.topics.POLICY-PDP-PAP.apiKey=${env:POLICY_PDP_PAP_API_KEY}
+dmaap.source.topics.POLICY-PDP-PAP.apiSecret=${env:POLICY_PDP_PAP_API_SECRET}
+dmaap.source.topics.POLICY-PDP-PAP.managed=false
+dmaap.source.topics.POLICY-PDP-PAP.https=true
+
+dmaap.sink.topics.POLICY-PDP-PAP.servers=${env:DMAAP_SERVERS}
+dmaap.sink.topics.POLICY-PDP-PAP.effectiveTopic=${env:POLICY_PDP_PAP_TOPIC}
+dmaap.sink.topics.POLICY-PDP-PAP.apiKey=${env:POLICY_PDP_PAP_API_KEY}
+dmaap.sink.topics.POLICY-PDP-PAP.apiSecret=${env:POLICY_PDP_PAP_API_SECRET}
+dmaap.sink.topics.POLICY-PDP-PAP.managed=false
+dmaap.sink.topics.POLICY-PDP-PAP.https=true
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java
new file mode 100644 (file)
index 0000000..5e1ddae
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import org.onap.policy.drools.features.DroolsControllerFeatureAPI;
+import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
+import org.onap.policy.drools.features.PolicyEngineFeatureAPI;
+import org.onap.policy.drools.system.PolicyEngine;
+
+/**
+ * This class hooks the Lifecycle State Machine to the PDP-D.
+ */
+public class LifecycleFeature
+    implements PolicyEngineFeatureAPI, DroolsControllerFeatureAPI, PolicyControllerFeatureAPI {
+    /**
+     * Lifecycle FSM.
+     */
+    protected static final LifecycleFsm fsm = new LifecycleFsm();
+
+    @Override
+    public int getSequenceNumber() {
+        return 10;
+    }
+
+    /**
+     * The 'afterStart' hook on the Policy Engine tell us when the engine is functional.
+     */
+    @Override
+    public boolean afterStart(PolicyEngine engine) {
+        fsm.start();
+        return false;
+    }
+
+    /**
+     * The 'afterStop' hook on the Policy Engine tell us when the engine is stopping.
+     */
+    @Override
+    public boolean afterStop(PolicyEngine engine) {
+        fsm.stop();
+        return false;
+    }
+
+    /**
+     * The 'beforeShutdown' hook on the Policy Engine tell us when the engine is going away.
+     */
+    @Override
+    public boolean beforeShutdown(PolicyEngine engine) {
+        fsm.shutdown();
+        return false;
+    }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
new file mode 100644 (file)
index 0000000..61f6de9
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.policy.common.capabilities.Startable;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient;
+import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher;
+import org.onap.policy.common.endpoints.listeners.ScoListener;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.common.utils.coder.StandardCoderObject;
+import org.onap.policy.common.utils.network.NetworkUtil;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.models.pdp.concepts.PolicyTypeIdent;
+import org.onap.policy.models.pdp.enums.PdpHealthStatus;
+import org.onap.policy.models.pdp.enums.PdpMessageType;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle FSM.
+ */
+public class LifecycleFsm implements Startable {
+
+    protected static final String CONFIGURATION_PROPERTIES_NAME = "feature-lifecycle";
+    protected static final String POLICY_TYPE_VERSION = "1.0.0";
+    protected static final long DEFAULT_STATUS_TIMER_SECONDS = 60L;
+    protected static final String PDP_MESSAGE_NAME = "messageName";
+
+    private static final Logger logger = LoggerFactory.getLogger(LifecycleFsm.class);
+
+    protected final Properties properties;
+
+    protected TopicSource source;
+    protected TopicSinkClient client;
+
+    protected volatile LifecycleState state = new LifecycleStateTerminated(this);
+
+    @GsonJsonIgnore
+    protected ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
+
+    @GsonJsonIgnore
+    protected ScheduledFuture<?> statusTask;
+
+    @GsonJsonIgnore
+    protected MessageTypeDispatcher sourceDispatcher = new MessageTypeDispatcher(new String[]{PDP_MESSAGE_NAME});
+
+    @GsonJsonIgnore
+    protected MessageNameDispatcher nameDispatcher = new MessageNameDispatcher(PdpStateChange.class, this);
+
+    @Getter
+    @Setter
+    protected long statusTimerSeconds = DEFAULT_STATUS_TIMER_SECONDS;
+
+    @Getter
+    protected String pdpGroup;
+
+    @Getter
+    protected String pdpSubgroup;
+
+    /**
+     * Constructor.
+     */
+    public LifecycleFsm() {
+        this.properties = SystemPersistence.manager.getProperties(CONFIGURATION_PROPERTIES_NAME);
+
+        scheduler.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
+        scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+        scheduler.setRemoveOnCancelPolicy(true);
+    }
+
+    @Override
+    public boolean isAlive() {
+        return client != null && client.getSink().isAlive();
+    }
+
+    /**
+     * Current state.
+     */
+    public PdpState state() {
+        return state.state();
+    }
+
+    /* ** FSM events - entry points of events into the FSM ** */
+
+    @Override
+    public synchronized boolean start() {
+        logger.info("lifecycle event: start");
+        return state.start();
+    }
+
+    @Override
+    public synchronized boolean stop() {
+        logger.info("lifecycle event: stop");
+        return state.stop();
+    }
+
+    @Override
+    public synchronized void shutdown() {
+        logger.info("lifecycle event: shutdown");
+        state.shutdown();
+    }
+
+    /**
+     * Status reporting event.
+     * @return true if successful
+     */
+    public synchronized boolean status() {
+        logger.info("lifecycle event: status");
+        return state.status();
+    }
+
+    public synchronized void stateChange(PdpStateChange stateChange) {
+        logger.info("lifecycle event: state-change");
+        state.stateChange(stateChange);
+    }
+
+    /* ** FSM State Actions ** */
+
+    protected boolean startAction() {
+        if (isAlive()) {
+            return true;
+        }
+
+        return startIo() && startTimers();
+    }
+
+    protected boolean stopAction() {
+        if (!isAlive()) {
+            return true;
+        }
+
+        boolean successTimers = stopTimers();
+        boolean successIo = stopIo();
+        return successTimers && successIo;
+    }
+
+    protected void shutdownAction() {
+        shutdownIo();
+        shutdownTimers();
+    }
+
+    protected boolean statusAction(PdpState state) {
+        if (!isAlive()) {
+            return false;
+        }
+
+        return client.send(statusPayload(state));
+    }
+
+    protected void setGroupAction(String group, String subgroup) {
+        this.pdpGroup = group;
+        this.pdpSubgroup = subgroup;
+    }
+
+    protected void transitionToAction(@NonNull LifecycleState newState) {
+        state = newState;
+    }
+
+    /* ** Action Helpers ** */
+
+    private boolean startIo() {
+        return source() && sink();
+    }
+
+    private boolean startTimers() {
+        statusTask =
+                this.scheduler.scheduleAtFixedRate(() -> status(), 0, statusTimerSeconds, TimeUnit.SECONDS);
+        return !statusTask.isCancelled() && !statusTask.isDone();
+    }
+
+    private boolean stopIo() {
+        source.unregister(sourceDispatcher);
+        boolean successSource = source.stop();
+        boolean successSink = client.getSink().stop();
+        return successSource && successSink;
+    }
+
+    private boolean stopTimers() {
+        boolean success = true;
+        if (statusTask != null) {
+            success = statusTask.cancel(false);
+        }
+
+        return success;
+    }
+
+    private void shutdownIo() {
+        client.getSink().shutdown();
+        source.shutdown();
+    }
+
+    private void shutdownTimers() {
+        scheduler.shutdownNow();
+    }
+
+    private PdpStatus statusPayload(PdpState state) {
+        PdpStatus status = new PdpStatus();
+        status.setRequestId(UUID.randomUUID().toString());
+        status.setTimestampMs(System.currentTimeMillis());
+        status.setInstance(NetworkUtil.getHostname());
+        status.setState(state);
+        status.setHealthy(isAlive() ? PdpHealthStatus.HEALTHY : PdpHealthStatus.NOT_HEALTHY);
+        status.setPdpType("drools");    // TODO: enum ?
+        return status;
+    }
+
+    private boolean source() {
+        List<TopicSource> sources = TopicEndpoint.manager.addTopicSources(properties);
+        if (sources.isEmpty()) {
+            return false;
+        }
+
+        if (sources.size() != 1) {
+            logger.warn("Lifecycle Manager: unexpected: more than one source configured ({})", sources.size());
+        }
+
+        this.source = sources.get(0);
+        this.source.register(this.sourceDispatcher);
+        this.sourceDispatcher.register(PdpMessageType.PDP_STATE_CHANGE.name(), nameDispatcher);
+        return source.start();
+    }
+
+    private boolean sink() {
+        List<TopicSink> sinks = TopicEndpoint.manager.addTopicSinks(properties);
+        if (sinks.isEmpty()) {
+            logger.error("Lifecycle Manager sinks have not been configured");
+            return false;
+        }
+
+        if (sinks.size() != 1) {
+            logger.warn("Lifecycle Manager: unexpected: more than one sink configured ({})", sinks.size());
+        }
+
+        this.client = new TopicSinkClient(sinks.get(0));
+        return this.client.getSink().start();
+    }
+
+    private List<PolicyTypeIdent> getCapabilities() {
+        List<PolicyTypeIdent> capabilities = new ArrayList<>();
+        for (DroolsController dc : DroolsController.factory.inventory()) {
+            if (!dc.isBrained()) {
+                continue;
+            }
+
+            for (String domain : dc.getBaseDomainNames()) {
+                // HACK: until legacy controllers are removed
+                if (StringUtils.countMatches(domain, ".") > 1) {
+                    capabilities.add(new PolicyTypeIdent(domain, POLICY_TYPE_VERSION));
+                } else {
+                    logger.info("legacy controller {} with domain {}", dc.getCanonicalSessionNames(), domain);
+                }
+            }
+        }
+        return capabilities;
+    }
+
+
+    /* **** IO listeners ***** */
+
+    /**
+     * PDP State Change Message Listener.
+     */
+    public static class MessageNameDispatcher extends ScoListener<PdpStateChange> {
+
+        protected final LifecycleFsm fsm;
+
+        /**
+         * Constructor.
+         */
+        public MessageNameDispatcher(Class<PdpStateChange> clazz, LifecycleFsm fsm) {
+            super(clazz);
+            this.fsm = fsm;
+        }
+
+        @Override
+        public void onTopicEvent(CommInfrastructure commInfrastructure, String topic,
+            StandardCoderObject standardCoderObject, PdpStateChange pdpStateChange) {
+
+            if (pdpStateChange == null) {
+                logger.warn("pdp-state-chage null from {}:{}", commInfrastructure, topic);
+                return;
+            }
+
+            fsm.stateChange(pdpStateChange);
+        }
+    }
+
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java
new file mode 100644 (file)
index 0000000..e07df15
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import lombok.NonNull;
+import org.onap.policy.common.capabilities.Startable;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle State.
+ */
+public abstract class LifecycleState implements Startable {
+
+    private static final Logger logger = LoggerFactory.getLogger(LifecycleState.class);
+
+    @GsonJsonIgnore
+    protected LifecycleFsm fsm;
+
+    /**
+     * Constructor.
+     * @param manager Lifecycle Manager.
+     */
+    public LifecycleState(@NonNull LifecycleFsm manager) {
+        this.fsm = manager;
+    }
+
+    /**
+     * change state.
+     * @param newState new state
+     */
+    public abstract boolean transitionToState(@NonNull LifecycleState newState);
+
+    /**
+     * current state.
+     * @return state
+     */
+    public abstract PdpState state();
+
+    /**
+     * status event.
+     */
+    public abstract boolean status();
+
+    /**
+     *  update event.
+     * @param update message
+     */
+    public abstract void update(@NonNull PdpUpdate update);
+
+    /**
+     * state change event .
+     * @param change message
+     */
+    public abstract void stateChange(@NonNull PdpStateChange change);
+}
\ No newline at end of file
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
new file mode 100644 (file)
index 0000000..d5be822
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle Active State.
+ */
+@ToString
+public class LifecycleStateActive extends LifecycleStateDefault {
+
+    private static final Logger logger = LoggerFactory.getLogger(LifecycleStateActive.class);
+
+    /**
+     * Constructor.
+     * @param manager fsm
+     */
+    public LifecycleStateActive(LifecycleFsm manager) {
+        super(manager);
+    }
+
+    @Override
+    public PdpState state() {
+        return PdpState.ACTIVE;
+    }
+
+    @Override
+    public void stateChange(PdpStateChange change) {
+        synchronized (fsm) {
+            if (change.getState() == PdpState.ACTIVE) {
+                fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
+                return;
+            }
+
+            if (change.getState() != PdpState.PASSIVE) {
+                logger.warn("{}: state-change: {}", this, change);
+                return;
+            }
+
+            fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
+            fsm.transitionToAction(new LifecycleStatePassive(fsm));
+        }
+    }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java
new file mode 100644 (file)
index 0000000..18e4001
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import lombok.NonNull;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Support class for default functionality for operational states.
+ */
+public abstract class LifecycleStateDefault extends LifecycleStateUnsupported {
+
+    private static final Logger logger = LoggerFactory.getLogger(LifecycleState.class);
+
+    public LifecycleStateDefault(LifecycleFsm manager) {
+        super(manager);
+    }
+
+
+    @Override
+    public boolean transitionToState(@NonNull LifecycleState newState) {
+        logger.info("{}: state-change from {} to {}", this, state(), newState.state());
+
+        synchronized (fsm) {
+            if (state() == newState.state()) {
+                return false;
+            }
+
+            fsm.transitionToAction(newState);
+            return true;
+        }
+    }
+
+    @Override
+    public boolean start() {
+        logger.warn("{}: start", this);
+        return false;
+    }
+
+    @Override
+    public boolean stop() {
+        synchronized (fsm) {
+            boolean success = fsm.statusAction(PdpState.TERMINATED);
+            success = fsm.stopAction() && success;
+            return transitionToState(new LifecycleStateTerminated(fsm)) && success;
+        }
+    }
+
+    @Override
+    public void shutdown() {
+        synchronized (fsm) {
+            stop();
+            fsm.shutdownAction();
+        }
+    }
+
+    @Override
+    public boolean isAlive() {
+        return true;
+    }
+
+    @Override
+    public boolean status() {
+        synchronized (fsm) {
+            return fsm.statusAction(state());
+        }
+    }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java
new file mode 100644 (file)
index 0000000..dc184e8
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle Passive State.
+ */
+
+@ToString
+public class LifecycleStatePassive extends LifecycleStateDefault {
+
+    private static final Logger logger = LoggerFactory.getLogger(LifecycleStatePassive.class);
+
+    /**
+     * Constructor.
+     * @param manager fsm
+     */
+    public LifecycleStatePassive(LifecycleFsm manager) {
+        super(manager);
+    }
+
+    @Override
+    public PdpState state() {
+        return PdpState.PASSIVE;
+    }
+
+    @Override
+    public void stateChange(PdpStateChange change) {
+        synchronized (fsm) {
+            if (change.getState() != PdpState.ACTIVE) {
+                logger.warn("{}: state-change: {}", this, change);
+                return;
+            }
+
+            fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
+            fsm.transitionToAction(new LifecycleStateActive(fsm));
+        }
+    }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateSafe.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateSafe.java
new file mode 100644 (file)
index 0000000..e0ea2b5
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * Lifecycle Safe State.
+ */
+
+@ToString
+public class LifecycleStateSafe extends LifecycleStateUnsupported {
+
+    public LifecycleStateSafe(LifecycleFsm manager) {
+        super(manager);
+    }
+
+    @Override
+    public PdpState state() {
+        return PdpState.SAFE;
+    }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java
new file mode 100644 (file)
index 0000000..7455349
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle Terminated State.
+ */
+
+@ToString
+public class LifecycleStateTerminated extends LifecycleStateDefault {
+
+    private static final Logger logger = LoggerFactory.getLogger(LifecycleStateTerminated.class);
+
+    protected LifecycleStateTerminated(LifecycleFsm manager) {
+        super(manager);
+    }
+
+    @Override
+    public PdpState state() {
+        return PdpState.TERMINATED;
+    }
+
+    @Override
+    public boolean start() {
+        synchronized (fsm) {
+            boolean success = fsm.startAction();
+            if (success) {
+                return transitionToState(new LifecycleStatePassive(fsm));
+            }
+
+            return false;
+        }
+    }
+
+    @Override
+    public boolean stop() {
+        logger.warn("{}: stop", this);
+        return true;
+    }
+
+    @Override
+    public void shutdown() {
+        logger.warn("{}: shutdown", this);
+    }
+
+    @Override
+    public boolean isAlive() {
+        return false;
+    }
+
+    @Override
+    public boolean status() {
+        logger.warn("{}: status", this);
+        return false;
+    }
+
+    @Override
+    public void stateChange(PdpStateChange change) {
+        logger.warn("{}: state-change: {}", this, change);
+        return;
+    }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTest.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTest.java
new file mode 100644 (file)
index 0000000..03ca377
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * Lifecycle Test State.
+ */
+@ToString
+public class LifecycleStateTest extends LifecycleStateUnsupported {
+
+    /**
+     * Constructor.
+     * @param manager fsm
+     */
+    public LifecycleStateTest(LifecycleFsm manager) {
+        super(manager);
+    }
+
+    @Override
+    public PdpState state() {
+        return PdpState.TEST;
+    }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java
new file mode 100644 (file)
index 0000000..ed6fa1a
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+
+/**
+ * Support class for those unsupported states not yet implemented.
+ */
+public abstract class LifecycleStateUnsupported extends LifecycleState {
+
+    /**
+     * Constructor.
+     * @param manager Lifecycle Manager.
+     */
+    public LifecycleStateUnsupported(LifecycleFsm manager) {
+        super(manager);
+    }
+
+    @Override
+    public boolean transitionToState(LifecycleState newState) {
+        throw new UnsupportedOperationException("transitionToAction: " + this);
+    }
+
+    @Override
+    public boolean start() {
+        throw new UnsupportedOperationException("start: " + this);
+    }
+
+    @Override
+    public boolean stop() {
+        throw new UnsupportedOperationException("stop: " + this);
+    }
+
+    @Override
+    public void shutdown() {
+        throw new UnsupportedOperationException("shutdown: " + this);
+    }
+
+    @Override
+    public boolean isAlive() {
+        throw new UnsupportedOperationException("isAlive: " + this);
+    }
+
+    @Override
+    public boolean status() {
+        throw new UnsupportedOperationException("status: " + this);
+    }
+
+    @Override
+    public void update(PdpUpdate update) {
+        throw new UnsupportedOperationException("start: " + this);
+    }
+
+    @Override
+    public void stateChange(PdpStateChange change) {
+        throw new UnsupportedOperationException("start: " + this);
+    }
+}
diff --git a/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureAPI b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureAPI
new file mode 100644 (file)
index 0000000..78cf97e
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.drools.lifecycle.LifecycleFeature
diff --git a/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI
new file mode 100644 (file)
index 0000000..78cf97e
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.drools.lifecycle.LifecycleFeature
diff --git a/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI
new file mode 100644 (file)
index 0000000..78cf97e
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.drools.lifecycle.LifecycleFeature
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java
new file mode 100644 (file)
index 0000000..eb83bc6
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * =============LICENSE_END========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.awaitility.Awaitility.await;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.drools.utils.logging.LoggerUtil;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.models.pdp.enums.PdpMessageType;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * Lifecycle State Active Test.
+ */
+public class LifecycleStateActiveTest {
+
+    private LifecycleFsm fsm;
+
+    @BeforeClass
+    public static void setUp() {
+        SystemPersistence.manager.setConfigurationDir("src/test/resources");
+        LoggerUtil.setLevel("org.onap.policy.common.endpoints", "WARN");
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        SystemPersistence.manager.setConfigurationDir(null);
+    }
+
+    /**
+     * Start tests in the Active state.
+     */
+    @Before
+    public void startActive() throws CoderException {
+        fsm = new LifecycleFsm();
+        fsm.setStatusTimerSeconds(15);
+        assertTrue(fsm.start());
+
+        goActive();
+        assertActive();
+    }
+
+    private void goActive() throws CoderException {
+        PdpStateChange change = new PdpStateChange();
+        change.setPdpGroup("A");
+        change.setPdpSubgroup("a");
+        change.setState(PdpState.ACTIVE);
+        change.setName("test");
+
+        fsm.source.offer(new StandardCoder().encode(change));
+    }
+
+    @Test
+    public void constructor() {
+        assertThatIllegalArgumentException().isThrownBy(() -> new LifecycleStateActive(null));
+        fsm.shutdown();
+    }
+
+    @Test
+    public void start() {
+        assertActive();
+        assertFalse(fsm.start());
+        assertActive();
+
+        fsm.shutdown();
+    }
+
+    private void assertActive() {
+        assertEquals(PdpState.ACTIVE, fsm.state());
+        assertEquals("A", fsm.getPdpGroup());
+        assertEquals("a", fsm.getPdpSubgroup());
+        assertTrue(fsm.isAlive());
+        await().atMost(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS).until(isStatus(PdpState.ACTIVE));
+    }
+
+    @Test
+    public void stop() {
+        assertTrue(fsm.stop());
+        assertBasicTerminated();
+
+        fsm.shutdown();
+    }
+
+    private void assertBasicTerminated() {
+        assertEquals(PdpState.TERMINATED, fsm.state());
+        assertFalse(fsm.isAlive());
+        assertFalse(fsm.state.isAlive());
+        await().atMost(1, TimeUnit.SECONDS).until(isStatus(PdpState.TERMINATED));
+    }
+
+    @Test
+    public void shutdown() {
+        fsm.shutdown();
+
+        assertBasicTerminated();
+
+        assertTrue(fsm.statusTask.isCancelled());
+        assertTrue(fsm.statusTask.isDone());
+    }
+
+    private Callable<Boolean> isStatus(PdpState state) {
+        return () -> {
+            if (fsm.client.getSink().getRecentEvents().length == 0) {
+                return false;
+            }
+
+            List<String> events = Arrays.asList(fsm.client.getSink().getRecentEvents());
+            PdpStatus status =
+                new StandardCoder().decode(events.get(events.size() - 1), PdpStatus.class);
+
+            return status.getMessageName() == PdpMessageType.PDP_STATUS && state == status.getState();
+        };
+    }
+
+    @Test
+    public void status() {
+        await().atMost(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS).until(isStatus(PdpState.ACTIVE));
+        int preCount = fsm.client.getSink().getRecentEvents().length;
+
+        assertTrue(fsm.status());
+        assertEquals(preCount + 1, fsm.client.getSink().getRecentEvents().length);
+
+        fsm.shutdown();
+    }
+
+    @Test
+    public void stateChange() throws CoderException {
+        assertActive();
+
+        /* dup */
+        PdpStateChange change = new PdpStateChange();
+        change.setPdpGroup("B");
+        change.setPdpSubgroup("b");
+        change.setState(PdpState.ACTIVE);
+        change.setName("test");
+
+        fsm.source.offer(new StandardCoder().encode(change));
+        assertEquals(PdpState.ACTIVE, fsm.state());
+        assertEquals("B", fsm.getPdpGroup());
+        assertEquals("b", fsm.getPdpSubgroup());
+
+        change.setState(PdpState.SAFE);
+        fsm.source.offer(new StandardCoder().encode(change));
+        assertEquals(PdpState.ACTIVE, fsm.state());
+
+        change.setState(PdpState.TERMINATED);
+        fsm.source.offer(new StandardCoder().encode(change));
+        assertEquals(PdpState.ACTIVE, fsm.state());
+
+        change.setState(PdpState.PASSIVE);
+        fsm.source.offer(new StandardCoder().encode(change));
+        assertEquals(PdpState.PASSIVE, fsm.state());
+        await().atMost(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS).until(isStatus(PdpState.PASSIVE));
+
+        fsm.shutdown();
+    }
+}
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java
new file mode 100644 (file)
index 0000000..fbc2eeb
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.awaitility.Awaitility.await;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import org.awaitility.core.ConditionTimeoutException;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.network.NetworkUtil;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.drools.utils.logging.LoggerUtil;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.models.pdp.enums.PdpHealthStatus;
+import org.onap.policy.models.pdp.enums.PdpMessageType;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * Lifecycle State Passive Tests.
+ */
+public class LifecycleStatePassiveTest {
+
+    private LifecycleFsm fsm;
+
+    @BeforeClass
+    public static void setUp() {
+        SystemPersistence.manager.setConfigurationDir("src/test/resources");
+        LoggerUtil.setLevel("org.onap.policy.common.endpoints", "WARN");
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        SystemPersistence.manager.setConfigurationDir(null);
+    }
+
+    /**
+     * Start tests in the Passive state.
+     */
+    @Before
+    public void startPassive() {
+        /* start every test in passive mode */
+        fsm = new LifecycleFsm();
+        fsm.setStatusTimerSeconds(15L);
+        simpleStart();
+
+        assertEquals(0, fsm.client.getSink().getRecentEvents().length);
+    }
+
+    @Test
+    public void constructor() {
+        assertThatIllegalArgumentException().isThrownBy(() -> new LifecycleStatePassive(null));
+        fsm.shutdown();
+    }
+
+    @Test
+    public void start() {
+        assertEquals(0, fsm.client.getSink().getRecentEvents().length);
+        assertFalse(fsm.start());
+        assertBasicPassive();
+
+        fsm.shutdown();
+    }
+
+    private Callable<Boolean> isStatus(PdpState state, int count) {
+        return () -> {
+            if (!fsm.client.getSink().isAlive()) {
+                return false;
+            }
+
+            if (fsm.client.getSink().getRecentEvents().length != count) {
+                return false;
+            }
+
+            String[] events = fsm.client.getSink().getRecentEvents();
+            PdpStatus status =
+                new StandardCoder().decode(events[events.length - 1], PdpStatus.class);
+
+            return status.getMessageName() == PdpMessageType.PDP_STATUS && state == status.getState();
+        };
+    }
+
+    @Test
+    public void stop() {
+        simpleStop();
+        assertBasicTerminated();
+    }
+
+    private void simpleStart() {
+        assertTrue(fsm.start());
+        assertBasicPassive();
+    }
+
+    private void simpleStop() {
+        assertTrue(fsm.stop());
+        assertBasicTerminated();
+    }
+
+    @Test
+    public void shutdown() throws CoderException {
+        simpleStop();
+
+        fsm.shutdown();
+        assertExtendedTerminated();
+    }
+
+    @Test
+    public void status() {
+        status(PdpState.PASSIVE);
+        fsm.shutdown();
+    }
+
+    private void status(PdpState state) {
+        await()
+            .atMost(5, TimeUnit.SECONDS)
+            .until(isStatus(state, 1));
+
+        await()
+            .atMost(fsm.statusTimerSeconds + 2, TimeUnit.SECONDS)
+            .until(isStatus(state, 2));
+
+        await()
+            .atMost(fsm.statusTimerSeconds + 2, TimeUnit.SECONDS)
+            .until(isStatus(state, 3));
+
+        assertTrue(fsm.status());
+        await()
+            .atMost(200, TimeUnit.MILLISECONDS)
+            .until(isStatus(state, 4));
+    }
+
+    @Test
+    public void update() {
+        // TODO
+        fsm.shutdown();
+    }
+
+    @Test
+    public void stateChange() throws CoderException {
+        PdpStateChange change = new PdpStateChange();
+        change.setPdpGroup("A");
+        change.setPdpSubgroup("a");
+        change.setState(PdpState.ACTIVE);
+        change.setName("test");
+
+        fsm.source.offer(new StandardCoder().encode(change));
+        assertEquals(PdpState.ACTIVE, fsm.state.state());
+        assertEquals("A", fsm.pdpGroup);
+        assertEquals("a", fsm.pdpSubgroup);
+
+        fsm.shutdown();
+    }
+
+    private void assertBasicTerminated() {
+        assertEquals(PdpState.TERMINATED, fsm.state.state());
+        assertFalse(fsm.isAlive());
+        assertFalse(fsm.state.isAlive());
+    }
+
+    private void assertExtendedTerminated() throws CoderException {
+        assertBasicTerminated();
+        assertTrue(fsm.statusTask.isCancelled());
+        assertTrue(fsm.statusTask.isDone());
+
+        assertEquals(1, fsm.client.getSink().getRecentEvents().length);
+        PdpStatus status = new StandardCoder().decode(fsm.client.getSink().getRecentEvents()[0], PdpStatus.class);
+        assertEquals("drools", status.getPdpType());
+        assertEquals(PdpState.TERMINATED, status.getState());
+        assertEquals(PdpHealthStatus.HEALTHY, status.getHealthy());
+        assertEquals(NetworkUtil.getHostname(), status.getInstance());
+        assertEquals(PdpMessageType.PDP_STATUS, status.getMessageName());
+
+        assertThatThrownBy( () -> await()
+            .atMost(fsm.statusTimerSeconds + 5, TimeUnit.SECONDS)
+            .until(isStatus(PdpState.TERMINATED, 2))).isInstanceOf(ConditionTimeoutException.class);
+    }
+
+    private void assertBasicPassive() {
+        assertEquals(PdpState.PASSIVE, fsm.state.state());
+        assertNotNull(fsm.source);
+        assertNotNull(fsm.client);
+        assertNotNull(fsm.statusTask);
+
+        assertTrue(fsm.isAlive());
+        assertTrue(fsm.source.isAlive());
+        assertTrue(fsm.client.getSink().isAlive());
+
+        assertFalse(fsm.statusTask.isCancelled());
+        assertFalse(fsm.statusTask.isDone());
+    }
+}
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateSafeTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateSafeTest.java
new file mode 100644 (file)
index 0000000..81ce85f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * TEST State Junits.
+ */
+public class LifecycleStateSafeTest extends LifecycleStateUnsupportedTest {
+
+    public LifecycleStateSafeTest() {
+        super(new LifecycleStateSafe(new LifecycleFsm()));
+    }
+
+    @Override
+    public LifecycleState create(LifecycleFsm fsm) {
+        return new LifecycleStateSafe(fsm);
+    }
+
+    @Test
+    public void constructor() {
+        super.constructor();
+        assertEquals(PdpState.SAFE, new LifecycleStateSafe(new LifecycleFsm()).state());
+    }
+
+    @Test
+    public void state() {
+        assertEquals(PdpState.SAFE, state.state());
+    }
+}
\ No newline at end of file
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java
new file mode 100644 (file)
index 0000000..b77fdcd
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+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.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.drools.utils.logging.LoggerUtil;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * Lifecycle State Terminated Tests.
+ */
+public class LifecycleStateTerminatedTest {
+    private LifecycleFsm fsm = new LifecycleFsm();
+
+    @BeforeClass
+    public static void setUp() {
+        SystemPersistence.manager.setConfigurationDir("src/test/resources");
+        LoggerUtil.setLevel("org.onap.policy.common.endpoints", "WARN");
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        SystemPersistence.manager.setConfigurationDir(null);
+    }
+
+    @Test
+    public void constructor() {
+        assertThatIllegalArgumentException().isThrownBy(() -> new LifecycleStateTerminated(null));
+
+        LifecycleState state = new LifecycleStateTerminated(new LifecycleFsm());
+        assertNull(state.fsm.source);
+        assertNull(state.fsm.client);
+        assertNull(state.fsm.statusTask);
+
+        assertEquals(PdpState.TERMINATED, state.state());
+        assertEquals(PdpState.TERMINATED, state.fsm.state.state());
+        assertFalse(state.isAlive());
+    }
+
+    @Test
+    public void stop() {
+        assertEquals(PdpState.TERMINATED, fsm.state.state());
+        assertFalse(fsm.isAlive());
+
+        simpleStop();
+    }
+
+    private void simpleStart() {
+        assertTrue(fsm.start());
+        assertBasicPassive();
+    }
+
+    private void simpleStop() {
+        assertTrue(fsm.stop());
+        assertBasicTerminated();
+    }
+
+    @Test
+    public void bounce() {
+        assertBasicTerminated();
+        simpleStart();
+        simpleStop();
+
+        assertFalse(fsm.source.isAlive());
+        assertFalse(fsm.client.getSink().isAlive());
+        assertExtendedTerminated();
+    }
+
+    @Test
+    public void doubleBounce() {
+        bounce();
+        bounce();
+    }
+
+    @Test
+    public void doubleStartBounce() {
+        simpleStart();
+        assertFalse(fsm.start());
+        assertBasicPassive();
+        simpleStop();
+    }
+
+    @Test
+    public void shutdown() {
+        assertBasicTerminated();
+        fsm.shutdown();
+        assertBasicTerminated();
+
+        fsm = new LifecycleFsm();
+    }
+
+    @Test
+    public void status() {
+        assertBasicTerminated();
+        assertFalse(fsm.status());
+        assertBasicTerminated();
+    }
+
+    @Test
+    public void changeState() {
+        assertFalse(fsm.state.transitionToState(new LifecycleStateTerminated(fsm)));
+        assertEquals(PdpState.TERMINATED, fsm.state.state());
+    }
+
+    @Test
+    public void update() {
+        // TODO
+    }
+
+    @Test
+    public void stateChange() {
+        PdpStateChange change = new PdpStateChange();
+        change.setPdpGroup("A");
+        change.setPdpSubgroup("a");
+        change.setState(PdpState.ACTIVE);
+        change.setName("test");
+
+        fsm.stateChange(change);
+
+        assertEquals(PdpState.TERMINATED, fsm.state.state());
+    }
+
+    private void assertBasicTerminated() {
+        assertEquals(PdpState.TERMINATED, fsm.state.state());
+        assertFalse(fsm.isAlive());
+        assertFalse(fsm.state.isAlive());
+    }
+
+    private void assertExtendedTerminated() {
+        assertBasicTerminated();
+        assertTrue(fsm.statusTask.isCancelled());
+        assertTrue(fsm.statusTask.isDone());
+        assertFalse(fsm.scheduler.isShutdown());
+    }
+
+    private void assertBasicPassive() {
+        assertEquals(PdpState.PASSIVE, fsm.state.state());
+        assertNotNull(fsm.source);
+        assertNotNull(fsm.client);
+        assertNotNull(fsm.statusTask);
+
+        assertTrue(fsm.isAlive());
+        assertTrue(fsm.source.isAlive());
+        assertTrue(fsm.client.getSink().isAlive());
+
+        assertFalse(fsm.statusTask.isCancelled());
+        assertFalse(fsm.statusTask.isDone());
+    }
+}
\ No newline at end of file
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTestTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTestTest.java
new file mode 100644 (file)
index 0000000..c086dfb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * TEST State Junits.
+ */
+public class LifecycleStateTestTest extends LifecycleStateUnsupportedTest {
+
+    public LifecycleStateTestTest() {
+        super(new LifecycleStateTest(new LifecycleFsm()));
+    }
+
+    @Override
+    public LifecycleState create(LifecycleFsm fsm) {
+        return new LifecycleStateTest(fsm);
+    }
+
+    @Test
+    public void constructor() {
+        super.constructor();
+        assertEquals(PdpState.TEST, new LifecycleStateTest(new LifecycleFsm()).state());
+    }
+
+    @Test
+    public void state() {
+        assertEquals(PdpState.TEST, state.state());
+    }
+}
\ No newline at end of file
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupportedTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupportedTest.java
new file mode 100644 (file)
index 0000000..01efca3
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.lifecycle;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.assertj.core.api.Java6Assertions.assertThatThrownBy;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+
+/**
+ * Lifecycle State Unsupported Test.
+ */
+public abstract class LifecycleStateUnsupportedTest {
+
+    protected final LifecycleState state;
+
+    @BeforeClass
+    public static void setUp() {
+        SystemPersistence.manager.setConfigurationDir("src/test/resources");
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        SystemPersistence.manager.setConfigurationDir(null);
+    }
+
+    public LifecycleStateUnsupportedTest(LifecycleState state) {
+        this.state = state;
+    }
+
+    public abstract LifecycleState create(LifecycleFsm fsm);
+
+    @Test
+    public void constructor() {
+        assertThatIllegalArgumentException().isThrownBy(() -> create(null));
+    }
+
+    @Test
+    public void start() {
+        assertThatThrownBy(() -> state.start())
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+
+    @Test
+    public void stop() {
+        assertThatThrownBy(() -> state.stop())
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+
+    @Test
+    public void shutdown() {
+        assertThatThrownBy(() -> state.shutdown())
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+
+    @Test
+    public void isAlive() {
+        assertThatThrownBy(() -> state.isAlive())
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+
+    @Test
+    public void status() {
+        assertThatThrownBy(() -> state.status())
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+
+    @Test
+    public void update() {
+        assertThatThrownBy(() -> state.update(new PdpUpdate()))
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+
+    @Test
+    public void stateChange() {
+        assertThatThrownBy(() -> state.stateChange(new PdpStateChange()))
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+
+    @Test
+    public void changeState() {
+        assertThatThrownBy(() -> state.transitionToState(new LifecycleStateActive(new LifecycleFsm())))
+            .isInstanceOf(UnsupportedOperationException.class);
+    }
+}
diff --git a/feature-lifecycle/src/test/resources/echo.drl b/feature-lifecycle/src/test/resources/echo.drl
new file mode 100644 (file)
index 0000000..c044f2c
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.test;
+
+rule "INIT"
+lock-on-active
+when
+then
+    insert("hello, I am up!");
+end
+
+rule "ECHO"
+when
+    $o : Object();
+then
+    System.out.println("ECHO: " + $o);
+    retract($o);
+end
diff --git a/feature-lifecycle/src/test/resources/echo.kmodule b/feature-lifecycle/src/test/resources/echo.kmodule
new file mode 100644 (file)
index 0000000..1019bd3
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  feature-controller-logging
+  ================================================================================
+  Copyright (C) 2019 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="controller-logs">
+        <ksession name="test" />
+    </kbase>
+</kmodule>
diff --git a/feature-lifecycle/src/test/resources/echo.pom b/feature-lifecycle/src/test/resources/echo.pom
new file mode 100644 (file)
index 0000000..7e65479
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  Copyright (C) 2019 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>
+
+    <groupId>org.onap.policy.drools.test</groupId>
+    <artifactId>echo</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+
+</project>
diff --git a/feature-lifecycle/src/test/resources/feature-lifecycle.properties b/feature-lifecycle/src/test/resources/feature-lifecycle.properties
new file mode 100644 (file)
index 0000000..a972016
--- /dev/null
@@ -0,0 +1,26 @@
+# ============LICENSE_START=======================================================
+# ONAP
+# ================================================================================
+# Copyright (C) 2019 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=========================================================
+
+noop.source.topics=POLICY-PDP-PAP
+noop.sink.topics=POLICY-PDP-PAP
+
+noop.source.topics.POLICY-PDP-PAP.servers=noop
+noop.source.topics.POLICY-PDP-PAP.managed=false
+
+noop.sink.topics.POLICY-PDP-PAP.servers=noop
+noop.sink.topics.POLICY-PDP-PAP.managed=false
index d48d3ff..fedfe7a 100644 (file)
@@ -70,7 +70,6 @@
                         </goals>
                         <phase>prepare-package</phase>
                         <configuration>
-                            <transitive>false</transitive>
                             <outputDirectory>${project.build.directory}/assembly/lib</outputDirectory>
                             <overWriteReleases>false</overWriteReleases>
                             <overWriteSnapshots>true</overWriteSnapshots>
                             </excludes>
                             <suppressionsLocation>${project.baseUri}checkstyle-suppressions.xml</suppressionsLocation>
                             <consoleOutput>true</consoleOutput>
-                            <failsOnViolation>true</failsOnViolation>
                             <violationSeverity>warning</violationSeverity>
                         </configuration>
                     </execution>
             <version>${policy.common.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.onap.policy.models</groupId>
+            <artifactId>policy-models-pdp</artifactId>
+            <version>${policy.models.version}</version>
+        </dependency>
+
         <dependency>
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-server</artifactId>
diff --git a/pom.xml b/pom.xml
index 8a41bed..79ed5be 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -63,6 +63,7 @@
         <commons.io.version>2.5</commons.io.version>
         <xml.apis.version>1.4.01</xml.apis.version>
         <policy.common.version>1.4.0-SNAPSHOT</policy.common.version>
+        <policy.models.version>2.0.0-SNAPSHOT</policy.models.version>
     </properties>
 
     <modules>
@@ -82,6 +83,7 @@
         <module>feature-distributed-locking</module>
         <module>feature-controller-logging</module>
         <module>feature-mdc-filters</module>
+        <module>feature-lifecycle</module>
         <module>packages</module>
     </modules>