Merge "move all bash to ash shell scripts"
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
index cf13c46..860986d 100644
--- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
@@ -24,6 +24,7 @@
 import java.util.List;
 import java.util.function.BiPredicate;
 import lombok.NonNull;
+import org.onap.policy.drools.policies.DomainMaker;
 import org.onap.policy.models.pdp.concepts.PdpResponseDetails;
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
@@ -161,6 +162,7 @@
     protected boolean syncPolicies(List<ToscaPolicy> policies,
                                    BiPredicate<PolicyTypeController, ToscaPolicy> sync) {
         boolean success = true;
+        DomainMaker domain = fsm.getDomainMaker();
         for (ToscaPolicy policy : policies) {
             ToscaPolicyTypeIdentifier policyType = policy.getTypeIdentifier();
             PolicyTypeController controller = fsm.getController(policyType);
@@ -170,7 +172,12 @@
                 continue;
             }
 
-            success = fsm.getDomainMaker().isConformant(policy) && sync.test(controller, policy) && success;
+            if (domain.isRegistered(policy.getTypeIdentifier())) {
+                success = domain.isConformant(policy) && sync.test(controller, policy) && success;
+            } else {
+                logger.info("no validator registered for policy type {}", policy.getTypeIdentifier());
+                success = sync.test(controller, policy) && success;
+            }
         }
 
         return success;
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java
index 957ecfa..b430533 100644
--- a/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java
@@ -286,8 +286,10 @@
         List<ToscaPolicy> policies =
                 LifecycleFeature.fsm.getPoliciesMap().values().stream().collect(Collectors.toList());
         policies.add(toscaPolicy);
-        return Response.status(Response.Status.OK)
-                       .entity(LifecycleFeature.fsm.update(getPolicyUpdate(policies)))
+
+        boolean updateResult = LifecycleFeature.fsm.update(getPolicyUpdate(policies));
+        return Response.status((updateResult ? Response.Status.OK : Response.Status.NOT_ACCEPTABLE))
+                       .entity(updateResult)
                        .build();
     }
 
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java
index ea48509..3a04c31 100644
--- a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java
+++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java
@@ -18,6 +18,7 @@
 
 package org.onap.policy.drools.server.restful;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -76,6 +77,18 @@
     private static final String EXAMPLE_NATIVE_ARTIFACT_POLICY_JSON =
             "src/test/resources/tosca-policy-native-artifact-example.json";
 
+    private static final String EXAMPLE_OTHER_UNVAL_POLICY_NAME = "other-unvalidated";
+    private static final String EXAMPLE_OTHER_UNVAL_POLICY_JSON =
+            "src/test/resources/tosca-policy-other-unvalidated.json";
+
+    private static final String EXAMPLE_OTHER_VAL_POLICY_NAME = "other-validated";
+    private static final String EXAMPLE_OTHER_VAL_POLICY_JSON =
+            "src/test/resources/tosca-policy-other-validated.json";
+
+    private static final String EXAMPLE_OTHER_VAL_ERROR_POLICY_NAME = "other-validation-error";
+    private static final String EXAMPLE_OTHER_VAL_ERROR_POLICY_JSON =
+            "src/test/resources/tosca-policy-other-validation-error.json";
+
     private static final String OP_POLICY_NAME_VCPE = "operational.restart";
     private static final String VCPE_OPERATIONAL_DROOLS_POLICY_JSON =
             "policies/vCPE.policy.operational.input.tosca.json";
@@ -212,11 +225,12 @@
 
         /* verify new supported operational policy types */
 
-        resourceLists("policyTypes", 4);
+        resourceLists("policyTypes", 5);
         get("policyTypes/onap.policies.native.drools.Artifact/1.0.0", Status.OK.getStatusCode());
         get("policyTypes/onap.policies.native.drools.Controller/1.0.0", Status.OK.getStatusCode());
         get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.OK.getStatusCode());
         get("policyTypes/onap.policies.type1.type2/1.0.0", Status.OK.getStatusCode());
+        get("policyTypes/onap.policies.typeA/1.0.0", Status.OK.getStatusCode());
 
         /* verify controller and artifact policies */
 
@@ -231,31 +245,26 @@
         if (StringUtils.isBlank(opPolicy.getName())) {
             opPolicy.setName(opPolicy.getMetadata().get("policy-id"));
         }
-        assertTrue(
-            listPost("policies/operations/validation", toString(opPolicy), Status.OK.getStatusCode()).isEmpty());
+        testNotNativePolicy(opPolicy);
 
-        booleanPost("policies", toString(opPolicy), Status.OK.getStatusCode(), Boolean.TRUE);
-        assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").isAlive());
-        assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained());
-        assertEquals(1,
-            PolicyControllerConstants
-                .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class).size());
+        /* add tosca policy "other-unvalidated" of policy type "type1.type2" with no attached type schema */
 
-        resourceLists("policies", 3);
-        get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.OK.getStatusCode());
-        get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
-        get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+        testNotNativePolicy(getPolicyFromFile(EXAMPLE_OTHER_UNVAL_POLICY_JSON, EXAMPLE_OTHER_UNVAL_POLICY_NAME));
 
-        booleanDelete("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(),
-                Status.OK.getStatusCode(), Boolean.TRUE);
-        assertEquals(0,
-            PolicyControllerConstants
-                .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class).size());
+        /* add tosca policy "other-validated" of policy type "typeA" with an attached type schema */
 
-        resourceLists("policies", 2);
-        get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
-        get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
-        get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+        testNotNativePolicy(getPolicyFromFile(EXAMPLE_OTHER_VAL_POLICY_JSON, EXAMPLE_OTHER_VAL_POLICY_NAME));
+
+        /* try to add invalid tosca policy "other-validation-error" of policy type "typeA" */
+
+        ToscaPolicy toscaPolicyValError =
+                getPolicyFromFile(EXAMPLE_OTHER_VAL_ERROR_POLICY_JSON, EXAMPLE_OTHER_VAL_ERROR_POLICY_NAME);
+        assertThat(
+                listPost("policies/operations/validation", toString(toscaPolicyValError),
+                        Status.NOT_ACCEPTABLE.getStatusCode())).isNotEmpty();
+
+        booleanPost("policies", toString(toscaPolicyValError),
+                Status.NOT_ACCEPTABLE.getStatusCode(), Boolean.FALSE);
 
         /* individual deploy/undeploy operations */
 
@@ -293,6 +302,7 @@
         get("policyTypes/onap.policies.native.drools.Controller/1.0.0", Status.OK.getStatusCode());
         get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.NOT_FOUND.getStatusCode());
         get("policyTypes/onap.policies.type1.type2/1.0.0", Status.NOT_FOUND.getStatusCode());
+        get("policyTypes/onap.policies.typeA/1.0.0", Status.NOT_FOUND.getStatusCode());
 
         resourceLists("policies", 1);
         get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
@@ -308,6 +318,7 @@
         get("policyTypes/onap.policies.native.drools.Controller/1.0.0", Status.OK.getStatusCode());
         get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.NOT_FOUND.getStatusCode());
         get("policyTypes/onap.policies.type1.type2/1.0.0", Status.NOT_FOUND.getStatusCode());
+        get("policyTypes/onap.policies.typeA/1.0.0", Status.NOT_FOUND.getStatusCode());
 
         resourceLists("policies", 0);
         get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
@@ -316,9 +327,38 @@
 
         assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("lifecycle"));
         opPolicy.getMetadata().remove("policy-id");
-        assertFalse(
+        assertThat(
             listPost("policies/operations/validation", toString(opPolicy),
-                    Status.NOT_ACCEPTABLE.getStatusCode()).isEmpty());
+                    Status.NOT_ACCEPTABLE.getStatusCode())).isNotEmpty();
+    }
+
+    private void testNotNativePolicy(ToscaPolicy toscaPolicy) throws CoderException {
+        assertThat(
+            listPost("policies/operations/validation", toString(toscaPolicy),
+                    Status.OK.getStatusCode())).isEmpty();
+
+        booleanPost("policies", toString(toscaPolicy), Status.OK.getStatusCode(), Boolean.TRUE);
+        assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").isAlive());
+        assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained());
+        assertEquals(1,
+            PolicyControllerConstants
+                .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class).size());
+
+        resourceLists("policies", 3);
+        get("policies/" + toscaPolicy.getName() + "/" + toscaPolicy.getVersion(), Status.OK.getStatusCode());
+        get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+        get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+
+        booleanDelete("policies/" + toscaPolicy.getName() + "/" + toscaPolicy.getVersion(),
+                Status.OK.getStatusCode(), Boolean.TRUE);
+        assertEquals(0,
+            PolicyControllerConstants
+                .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class).size());
+
+        resourceLists("policies", 2);
+        get("policies/" + toscaPolicy.getName() + "/" + toscaPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
+        get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+        get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
     }
 
     private Response get(String contextPath, int statusCode) {
diff --git a/feature-lifecycle/src/test/resources/lifecycle.kmodule b/feature-lifecycle/src/test/resources/lifecycle.kmodule
index 529730b..56ca092 100644
--- a/feature-lifecycle/src/test/resources/lifecycle.kmodule
+++ b/feature-lifecycle/src/test/resources/lifecycle.kmodule
@@ -3,7 +3,7 @@
   ============LICENSE_START=======================================================
   feature-controller-logging
   ================================================================================
-  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
   ================================================================================
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -20,8 +20,10 @@
   -->
 
 <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
-    <kbase name="onap.policies.controlloop.operational.common.Drools" default="false" equalsBehavior="equality"/>
+    <kbase name="onap.policies.typeA" default="false" equalsBehavior="equality"/>
+    <kbase name="onap.policies.controlloop.operational.common.Drools"
+        includes="onap.policies.typeA" default="false" equalsBehavior="equality"/>
     <kbase name="onap.policies.type1.type2" includes="onap.policies.controlloop.operational.common.Drools">
         <ksession name="junits" />
     </kbase>
-</kmodule>
+</kmodule>
\ No newline at end of file
diff --git a/feature-lifecycle/src/test/resources/schemas/onap.policies.typeA-1.0.0.schema.json b/feature-lifecycle/src/test/resources/schemas/onap.policies.typeA-1.0.0.schema.json
new file mode 100644
index 0000000..9171246
--- /dev/null
+++ b/feature-lifecycle/src/test/resources/schemas/onap.policies.typeA-1.0.0.schema.json
@@ -0,0 +1,106 @@
+{
+    "definitions": {},
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "$id": "http://www.onap.org/policy/models/schemas/onap.policies.typeA.schema.json",
+    "type": "object",
+    "title": "The Root Schema",
+    "required": [
+        "type",
+        "type_version",
+        "version",
+        "metadata",
+        "properties"
+    ],
+    "properties": {
+        "type": {
+            "$id": "#/properties/type",
+            "type": "string",
+            "title": "Policy Type",
+            "default": "onap.policies.typeA",
+            "examples": [
+                "onap.policies.typeA"
+            ],
+            "pattern": "^(.+)$"
+        },
+        "type_version": {
+            "$id": "#/properties/type_version",
+            "type": "string",
+            "title": "Policy Type Version",
+            "default": "1.0.0",
+            "examples": [
+                "1.0.0"
+            ],
+            "pattern": "^(.+)$"
+        },
+        "name": {
+            "$id": "#/properties/name",
+            "type": "string",
+            "title": "Policy Name",
+            "default": "",
+            "examples": [
+                "example"
+            ],
+            "pattern": "^(.*)$"
+        },
+        "version": {
+            "$id": "#/properties/version",
+            "type": "string",
+            "title": "Policy Version",
+            "default": "1.0.0",
+            "examples": [
+                "1.0.0"
+            ],
+            "pattern": "^(.+)$"
+        },
+        "metadata": {
+            "$id": "#/properties/metadata",
+            "type": "object",
+            "title": "Metadata",
+            "required": [
+                "policy-id"
+            ],
+            "properties": {
+                "policy-id": {
+                    "$id": "#/properties/metadata/properties/policy-id",
+                    "type": "string",
+                    "title": "Policy ID",
+                    "examples": [
+                        "operational.restart"
+                    ],
+                    "pattern": "^(.+)$"
+                }
+            }
+        },
+        "properties": {
+            "$id": "#/properties/properties",
+            "type": "object",
+            "title": "Properties",
+            "required": [
+                "fieldA",
+                "fieldB"
+            ],
+            "properties": {
+                "fieldA": {
+                    "$id": "#/properties/properties/properties/fieldA",
+                    "type": "string",
+                    "title": "Field A",
+                    "examples": [
+                        "FieldA"
+                    ],
+                    "pattern": "^(.+)$"
+                },
+                "fieldB": {
+                    "$id": "#/properties/properties/properties/fieldB",
+                    "type": "integer",
+                    "title": "Timeout in seconds",
+                    "minimum": 1,
+                    "maximum": 5,
+                    "default": 1,
+                    "examples": [
+                        3
+                    ]
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/feature-lifecycle/src/test/resources/tosca-policy-other-unvalidated.json b/feature-lifecycle/src/test/resources/tosca-policy-other-unvalidated.json
new file mode 100644
index 0000000..64a59b2
--- /dev/null
+++ b/feature-lifecycle/src/test/resources/tosca-policy-other-unvalidated.json
@@ -0,0 +1,22 @@
+{
+    "tosca_definitions_version": "tosca_simple_yaml_1_0_0",
+    "topology_template": {
+        "policies": [
+            {
+                "other-unvalidated": {
+                    "type": "onap.policies.type1.type2",
+                    "type_version": "1.0.0",
+                    "name": "other-unvalidated",
+                    "version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "other-unvalidated"
+                    },
+                    "properties": {
+                        "field1": "abc",
+                        "field2": 2
+                    }
+                }
+            }
+        ]
+    }
+}
diff --git a/feature-lifecycle/src/test/resources/tosca-policy-other-validated.json b/feature-lifecycle/src/test/resources/tosca-policy-other-validated.json
new file mode 100644
index 0000000..e79435c
--- /dev/null
+++ b/feature-lifecycle/src/test/resources/tosca-policy-other-validated.json
@@ -0,0 +1,22 @@
+{
+    "tosca_definitions_version": "tosca_simple_yaml_1_0_0",
+    "topology_template": {
+        "policies": [
+            {
+                "other-validated": {
+                    "type": "onap.policies.typeA",
+                    "type_version": "1.0.0",
+                    "name": "other-validated",
+                    "version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "other-validated"
+                    },
+                    "properties": {
+                        "fieldA": "abc",
+                        "fieldB": 2
+                    }
+                }
+            }
+        ]
+    }
+}
diff --git a/feature-lifecycle/src/test/resources/tosca-policy-other-validation-error.json b/feature-lifecycle/src/test/resources/tosca-policy-other-validation-error.json
new file mode 100644
index 0000000..f7af04b
--- /dev/null
+++ b/feature-lifecycle/src/test/resources/tosca-policy-other-validation-error.json
@@ -0,0 +1,21 @@
+{
+    "tosca_definitions_version": "tosca_simple_yaml_1_0_0",
+    "topology_template": {
+        "policies": [
+            {
+                "other-validation-error": {
+                    "type": "onap.policies.typeA",
+                    "type_version": "1.0.0",
+                    "name": "other-validation-error",
+                    "version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "other-validation-error"
+                    },
+                    "properties": {
+                        "fieldA": "abc"
+                    }
+                }
+            }
+        ]
+    }
+}