Merge "Use a logger to log this exception-AafConnection"
authorvarun gudisena <varuneshwar.gudisena@att.com>
Tue, 22 Jan 2019 18:55:05 +0000 (18:55 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 22 Jan 2019 18:55:05 +0000 (18:55 +0000)
34 files changed:
INFO.yaml [new file with mode: 0644]
docs/api.rst
pom.xml
src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java [new file with mode: 0644]
src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java [new file with mode: 0644]
src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java
src/main/java/org/onap/dmaap/dbcapi/aaf/AafUserRole.java [new file with mode: 0644]
src/main/java/org/onap/dmaap/dbcapi/authentication/AafLurAndFish.java
src/main/java/org/onap/dmaap/dbcapi/authentication/ApiPerms.java
src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java
src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java
src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java
src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java
src/main/java/org/onap/dmaap/dbcapi/model/DmaapObject.java
src/main/java/org/onap/dmaap/dbcapi/model/Feed.java
src/main/java/org/onap/dmaap/dbcapi/model/MR_Client.java
src/main/java/org/onap/dmaap/dbcapi/model/Topic.java
src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java
src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java
src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java
src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java
src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java
src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java
src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java
src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java
src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java
src/main/java/org/onap/dmaap/dbcapi/service/MR_ClientService.java
src/main/java/org/onap/dmaap/dbcapi/service/MR_ClusterService.java
src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java
src/main/java/org/onap/dmaap/dbcapi/util/Graph.java
src/main/resources/schema_11.sql [new file with mode: 0644]
src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java
src/test/java/org/onap/dmaap/dbcapi/util/FqdnTest.java [new file with mode: 0644]
version.properties

diff --git a/INFO.yaml b/INFO.yaml
new file mode 100644 (file)
index 0000000..172026d
--- /dev/null
+++ b/INFO.yaml
@@ -0,0 +1,42 @@
+---
+project: 'dmaap-dbcapi'
+project_creation_date: '2017-08-29'
+lifecycle_state: 'Incubation'
+project_lead: &onap_releng_ptl
+    name: 'Ram Koya'
+    email: 'rk541m@att.com'
+    id: 'rampi_k'
+    company: 'ATT'
+    timezone: 'America/Dallas'
+primary_contact: *onap_releng_ptl
+issue_tracking:
+    type: 'jira'
+    url: 'https://jira.onap.org/projects/DMAAP'
+    key: 'DMAAP'
+meetings:
+    - type: 'zoom'
+        agenda: ''
+        url: 'https://wiki.onap.org/pages/viewpage.action?pageId=13599275'
+        server: 'n/a'
+        channel: 'n/a'
+        repeats: 'weekly'
+        time: '13:00 UTC'
+committers:
+    - <<: *onap_releng_ptl
+    - name: 'Ramdas Sawant'
+        email: 'rs873m@att.com'
+        company: 'ATT'
+        id: 'rs873m'
+        timezone: 'America/Dallas'
+    - name: 'Varun Gudisena'
+        email: 'vg411h@att.com'
+        company: 'ATT'
+        id: 'vg411h'
+        timezone: 'America/Dallas'
+tsc:
+    approval: 'https://lists.onap.org/pipermail/onap-tsc'
+    changes:
+        - type: 'Removal'
+          name: 'Habib Madani'
+          name: 'Xinhui Li'
+          name: 'Jing Wang'
index 5ba2eef..9eab4da 100644 (file)
@@ -289,7 +289,6 @@ Type: :ref:`DcaeLocation <d_47d80e451933beb623fcf5257867cbcb>`
         "local": true, 
         "openStackAvailabilityZone": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subnet": "somestring"
     }
 
@@ -371,7 +370,6 @@ Type: :ref:`DcaeLocation <d_47d80e451933beb623fcf5257867cbcb>`
         "local": true, 
         "openStackAvailabilityZone": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subnet": "somestring"
     }
 
@@ -396,7 +394,6 @@ Type: :ref:`DcaeLocation <d_47d80e451933beb623fcf5257867cbcb>`
         "local": true, 
         "openStackAvailabilityZone": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subnet": "somestring"
     }
 
@@ -478,7 +475,6 @@ Type: :ref:`DcaeLocation <d_47d80e451933beb623fcf5257867cbcb>`
         "local": true, 
         "openStackAvailabilityZone": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subnet": "somestring"
     }
 
@@ -550,7 +546,6 @@ Type: :ref:`DcaeLocation <d_47d80e451933beb623fcf5257867cbcb>`
         "local": true, 
         "openStackAvailabilityZone": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subnet": "somestring"
     }
 
@@ -632,7 +627,6 @@ Type: :ref:`DcaeLocation <d_47d80e451933beb623fcf5257867cbcb>`
         "local": true, 
         "openStackAvailabilityZone": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subnet": "somestring"
     }
 
@@ -662,7 +656,7 @@ DMAAP
 ~~~~~
 
 
-Endpoint for this instance of DMaaP object containing values for this OpenDCAE deployment
+V2 Endpoint for this instance of DMaaP object containing values for this OpenDCAE deployment
 
 
 
@@ -713,7 +707,6 @@ Type: :ref:`Dmaap <d_4ea0e7758a1f8502222793e4a13b04f7>`
         "loggingUrl": "somestring", 
         "nodeKey": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicNsRoot": "somestring", 
         "version": "somestring"
     }
@@ -786,7 +779,6 @@ Type: :ref:`Dmaap <d_4ea0e7758a1f8502222793e4a13b04f7>`
         "loggingUrl": "somestring", 
         "nodeKey": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicNsRoot": "somestring", 
         "version": "somestring"
     }
@@ -859,7 +851,6 @@ Type: :ref:`Dmaap <d_4ea0e7758a1f8502222793e4a13b04f7>`
         "loggingUrl": "somestring", 
         "nodeKey": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicNsRoot": "somestring", 
         "version": "somestring"
     }
@@ -932,7 +923,6 @@ Type: :ref:`Dmaap <d_4ea0e7758a1f8502222793e4a13b04f7>`
         "loggingUrl": "somestring", 
         "nodeKey": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicNsRoot": "somestring", 
         "version": "somestring"
     }
@@ -1005,7 +995,6 @@ Type: :ref:`Dmaap <d_4ea0e7758a1f8502222793e4a13b04f7>`
         "loggingUrl": "somestring", 
         "nodeKey": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicNsRoot": "somestring", 
         "version": "somestring"
     }
@@ -1078,7 +1067,6 @@ Type: :ref:`Dmaap <d_4ea0e7758a1f8502222793e4a13b04f7>`
         "loggingUrl": "somestring", 
         "nodeKey": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicNsRoot": "somestring", 
         "version": "somestring"
     }
@@ -1157,7 +1145,6 @@ Type: :ref:`DR_Node <d_d15e2cee407536866c875375e3f705e0>`
         "hostName": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "version": "somestring"
     }
 
@@ -1236,7 +1223,6 @@ Type: :ref:`DR_Node <d_d15e2cee407536866c875375e3f705e0>`
         "hostName": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "version": "somestring"
     }
 
@@ -1258,7 +1244,6 @@ Type: :ref:`DR_Node <d_d15e2cee407536866c875375e3f705e0>`
         "hostName": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "version": "somestring"
     }
 
@@ -1337,7 +1322,6 @@ Type: :ref:`DR_Node <d_d15e2cee407536866c875375e3f705e0>`
         "hostName": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "version": "somestring"
     }
 
@@ -1406,7 +1390,6 @@ Type: :ref:`DR_Node <d_d15e2cee407536866c875375e3f705e0>`
         "hostName": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "version": "somestring"
     }
 
@@ -1485,7 +1468,6 @@ Type: :ref:`DR_Node <d_d15e2cee407536866c875375e3f705e0>`
         "hostName": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "version": "somestring"
     }
 
@@ -1563,7 +1545,6 @@ Type: :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>`
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "pubId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "username": "somestring", 
         "userpwd": "somestring"
     }
@@ -1643,7 +1624,6 @@ Type: :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>`
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "pubId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "username": "somestring", 
         "userpwd": "somestring"
     }
@@ -1666,7 +1646,6 @@ Type: :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>`
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "pubId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "username": "somestring", 
         "userpwd": "somestring"
     }
@@ -1746,7 +1725,6 @@ Type: :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>`
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "pubId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "username": "somestring", 
         "userpwd": "somestring"
     }
@@ -1816,7 +1794,6 @@ Type: :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>`
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "pubId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "username": "somestring", 
         "userpwd": "somestring"
     }
@@ -1896,7 +1873,6 @@ Type: :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>`
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "pubId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "username": "somestring", 
         "userpwd": "somestring"
     }
@@ -1981,7 +1957,6 @@ Type: :ref:`DR_Sub <d_48cf328d246f41e1d11a09251b042f02>`
         "logURL": "somestring", 
         "owner": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subId": "somestring", 
         "suspended": true, 
         "use100": true, 
@@ -2070,7 +2045,6 @@ Type: :ref:`DR_Sub <d_48cf328d246f41e1d11a09251b042f02>`
         "logURL": "somestring", 
         "owner": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subId": "somestring", 
         "suspended": true, 
         "use100": true, 
@@ -2159,7 +2133,6 @@ Type: :ref:`DR_Sub <d_48cf328d246f41e1d11a09251b042f02>`
         "logURL": "somestring", 
         "owner": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subId": "somestring", 
         "suspended": true, 
         "use100": true, 
@@ -2238,7 +2211,6 @@ Type: :ref:`DR_Sub <d_48cf328d246f41e1d11a09251b042f02>`
         "logURL": "somestring", 
         "owner": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subId": "somestring", 
         "suspended": true, 
         "use100": true, 
@@ -2327,7 +2299,6 @@ Type: :ref:`DR_Sub <d_48cf328d246f41e1d11a09251b042f02>`
         "logURL": "somestring", 
         "owner": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subId": "somestring", 
         "suspended": true, 
         "use100": true, 
@@ -2435,7 +2406,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }, 
@@ -2445,13 +2415,11 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }
         ], 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subs": [
             {
                 "bytes": [
@@ -2465,7 +2433,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -2484,7 +2451,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -2587,7 +2553,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }, 
@@ -2597,13 +2562,11 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }
         ], 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subs": [
             {
                 "bytes": [
@@ -2617,7 +2580,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -2636,7 +2598,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -2682,7 +2643,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }, 
@@ -2692,13 +2652,11 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }
         ], 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subs": [
             {
                 "bytes": [
@@ -2712,7 +2670,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -2731,7 +2688,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -2818,7 +2774,6 @@ Type: :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>`
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "pubId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "username": "somestring", 
         "userpwd": "somestring"
     }
@@ -2916,7 +2871,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }, 
@@ -2926,13 +2880,11 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }
         ], 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subs": [
             {
                 "bytes": [
@@ -2946,7 +2898,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -2965,7 +2916,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -3068,7 +3018,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }, 
@@ -3078,13 +3027,11 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "pubId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "username": "somestring", 
                 "userpwd": "somestring"
             }
         ], 
         "status": "EMPTY", 
-        "statusValid": true, 
         "subs": [
             {
                 "bytes": [
@@ -3098,7 +3045,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -3117,7 +3063,6 @@ Type: :ref:`Feed <d_289ad39619725df26c9ff382d4c97c75>`
                 "logURL": "somestring", 
                 "owner": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "subId": "somestring", 
                 "suspended": true, 
                 "use100": true, 
@@ -3206,7 +3151,6 @@ Type: :ref:`Dmaap <d_4ea0e7758a1f8502222793e4a13b04f7>`
         "loggingUrl": "somestring", 
         "nodeKey": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicNsRoot": "somestring", 
         "version": "somestring"
     }
@@ -3250,14 +3194,14 @@ POST ``/mr_clients``
 Summary
 +++++++
 
-return MR_Client details
+Associate an MR_Client object to a Topic
 
 Description
 +++++++++++
 
 .. raw:: html
 
-    Create a  `MR_Client` object.
+    Create a  `MR_Client` object.The `dcaeLocation` attribute is used to match an `MR_Cluster` object with the same value, with the intent of localizing message traffic.  In legacy implementation, the `clientRole` is granted appropriate permission in AAF.  Newer implementions may instead specify an AAF Identity, which will be added to the appropriate `Topic` role.
 
 
 Request
@@ -3284,13 +3228,13 @@ Type: :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>`
             "somestring", 
             "somestring"
         ], 
+        "clientIdentity": "somestring", 
         "clientRole": "somestring", 
         "dcaeLocationName": "somestring", 
         "fqtn": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "mrClientId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicURL": "somestring"
     }
 
@@ -3324,7 +3268,7 @@ DELETE ``/mr_clients/{subId}``
 Summary
 +++++++
 
-return MR_Client details
+Delete an MR_Client object
 
 Description
 +++++++++++
@@ -3368,13 +3312,13 @@ Type: :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>`
             "somestring", 
             "somestring"
         ], 
+        "clientIdentity": "somestring", 
         "clientRole": "somestring", 
         "dcaeLocationName": "somestring", 
         "fqtn": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "mrClientId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicURL": "somestring"
     }
 
@@ -3395,13 +3339,13 @@ Type: :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>`
             "somestring", 
             "somestring"
         ], 
+        "clientIdentity": "somestring", 
         "clientRole": "somestring", 
         "dcaeLocationName": "somestring", 
         "fqtn": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "mrClientId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicURL": "somestring"
     }
 
@@ -3469,13 +3413,13 @@ Type: :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>`
             "somestring", 
             "somestring"
         ], 
+        "clientIdentity": "somestring", 
         "clientRole": "somestring", 
         "dcaeLocationName": "somestring", 
         "fqtn": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "mrClientId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicURL": "somestring"
     }
 
@@ -3553,13 +3497,13 @@ Type: :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>`
             "somestring", 
             "somestring"
         ], 
+        "clientIdentity": "somestring", 
         "clientRole": "somestring", 
         "dcaeLocationName": "somestring", 
         "fqtn": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "mrClientId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicURL": "somestring"
     }
 
@@ -3593,7 +3537,7 @@ PUT ``/mr_clients/{clientId}``
 Summary
 +++++++
 
-return MR_Client details
+Update an MR_Client object
 
 Description
 +++++++++++
@@ -3637,13 +3581,13 @@ Type: :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>`
             "somestring", 
             "somestring"
         ], 
+        "clientIdentity": "somestring", 
         "clientRole": "somestring", 
         "dcaeLocationName": "somestring", 
         "fqtn": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
         "mrClientId": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "topicURL": "somestring"
     }
 
@@ -3722,7 +3666,6 @@ Type: :ref:`MR_Cluster <d_eec7176a0080debe1b19c2dad2e97c24>`
         "replicationGroup": "somestring", 
         "sourceReplicationPort": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "targetReplicationPort": "somestring", 
         "topicPort": "somestring", 
         "topicProtocol": "somestring"
@@ -3804,7 +3747,6 @@ Type: :ref:`MR_Cluster <d_eec7176a0080debe1b19c2dad2e97c24>`
         "replicationGroup": "somestring", 
         "sourceReplicationPort": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "targetReplicationPort": "somestring", 
         "topicPort": "somestring", 
         "topicProtocol": "somestring"
@@ -3829,7 +3771,6 @@ Type: :ref:`MR_Cluster <d_eec7176a0080debe1b19c2dad2e97c24>`
         "replicationGroup": "somestring", 
         "sourceReplicationPort": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "targetReplicationPort": "somestring", 
         "topicPort": "somestring", 
         "topicProtocol": "somestring"
@@ -3911,7 +3852,6 @@ Type: :ref:`MR_Cluster <d_eec7176a0080debe1b19c2dad2e97c24>`
         "replicationGroup": "somestring", 
         "sourceReplicationPort": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "targetReplicationPort": "somestring", 
         "topicPort": "somestring", 
         "topicProtocol": "somestring"
@@ -3983,7 +3923,6 @@ Type: :ref:`MR_Cluster <d_eec7176a0080debe1b19c2dad2e97c24>`
         "replicationGroup": "somestring", 
         "sourceReplicationPort": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "targetReplicationPort": "somestring", 
         "topicPort": "somestring", 
         "topicProtocol": "somestring"
@@ -4065,7 +4004,6 @@ Type: :ref:`MR_Cluster <d_eec7176a0080debe1b19c2dad2e97c24>`
         "replicationGroup": "somestring", 
         "sourceReplicationPort": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true, 
         "targetReplicationPort": "somestring", 
         "topicPort": "somestring", 
         "topicProtocol": "somestring"
@@ -4110,14 +4048,14 @@ POST ``/topics``
 Summary
 +++++++
 
-return Topic details
+Create a Topic object
 
 Description
 +++++++++++
 
 .. raw:: html
 
-    Create  `Topic` object.
+    Create  `Topic` object.For convenience, the message body may populate the `clients` array, in which case each entry will be added as an `MR_Client`.  Beginning in ONAP Dublin Release, dbcapi will create two AAF Roles by default, one each for the publisher and subscriber per topic.  MR_Clients can then specify an AAF Identity to be added to the appropriate default Role, avoiding the need to create Role(s) in advance.
 
 Parameters
 ++++++++++
@@ -4150,23 +4088,19 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
 .. code-block:: javascript
 
     {
-        "bytes": [
-            "somestring", 
-            "somestring"
-        ], 
         "clients": [
             {
                 "action": [
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }, 
             {
@@ -4174,13 +4108,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }
         ], 
@@ -4189,13 +4123,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
         "fqtnStyle": "FQTN_NOT_SPECIFIED", 
         "globalMrURL": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
-        "numClients": 1, 
         "owner": "somestring", 
         "partitionCount": "somestring", 
+        "publisherRole": "somestring", 
         "replicationCase": "REPLICATION_NOT_SPECIFIED", 
         "replicationCount": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true
+        "subscriberRole": "somestring"
         "tnxEnabled": "somestring", 
         "topicDescription": "somestring", 
         "topicName": "somestring", 
@@ -4272,23 +4206,19 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
 .. code-block:: javascript
 
     {
-        "bytes": [
-            "somestring", 
-            "somestring"
-        ], 
         "clients": [
             {
                 "action": [
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }, 
             {
@@ -4296,13 +4226,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }
         ], 
@@ -4311,13 +4241,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
         "fqtnStyle": "FQTN_NOT_SPECIFIED", 
         "globalMrURL": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
-        "numClients": 1, 
         "owner": "somestring", 
         "partitionCount": "somestring", 
+        "publisherRole": "somestring", 
         "replicationCase": "REPLICATION_NOT_SPECIFIED", 
         "replicationCount": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true
+        "subscriberRole": "somestring"
         "tnxEnabled": "somestring", 
         "topicDescription": "somestring", 
         "topicName": "somestring", 
@@ -4337,23 +4267,19 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
 .. code-block:: javascript
 
     {
-        "bytes": [
-            "somestring", 
-            "somestring"
-        ], 
         "clients": [
             {
                 "action": [
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }, 
             {
@@ -4361,13 +4287,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }
         ], 
@@ -4376,13 +4302,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
         "fqtnStyle": "FQTN_NOT_SPECIFIED", 
         "globalMrURL": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
-        "numClients": 1, 
         "owner": "somestring", 
         "partitionCount": "somestring", 
+        "publisherRole": "somestring", 
         "replicationCase": "REPLICATION_NOT_SPECIFIED", 
         "replicationCount": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true
+        "subscriberRole": "somestring"
         "tnxEnabled": "somestring", 
         "topicDescription": "somestring", 
         "topicName": "somestring", 
@@ -4459,23 +4385,19 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
 .. code-block:: javascript
 
     {
-        "bytes": [
-            "somestring", 
-            "somestring"
-        ], 
         "clients": [
             {
                 "action": [
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }, 
             {
@@ -4483,13 +4405,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }
         ], 
@@ -4498,13 +4420,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
         "fqtnStyle": "FQTN_NOT_SPECIFIED", 
         "globalMrURL": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
-        "numClients": 1, 
         "owner": "somestring", 
         "partitionCount": "somestring", 
+        "publisherRole": "somestring", 
         "replicationCase": "REPLICATION_NOT_SPECIFIED", 
         "replicationCount": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true
+        "subscriberRole": "somestring"
         "tnxEnabled": "somestring", 
         "topicDescription": "somestring", 
         "topicName": "somestring", 
@@ -4571,23 +4493,19 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
 .. code-block:: javascript
 
     {
-        "bytes": [
-            "somestring", 
-            "somestring"
-        ], 
         "clients": [
             {
                 "action": [
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }, 
             {
@@ -4595,13 +4513,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }
         ], 
@@ -4610,13 +4528,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
         "fqtnStyle": "FQTN_NOT_SPECIFIED", 
         "globalMrURL": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
-        "numClients": 1, 
         "owner": "somestring", 
         "partitionCount": "somestring", 
+        "publisherRole": "somestring", 
         "replicationCase": "REPLICATION_NOT_SPECIFIED", 
         "replicationCount": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true
+        "subscriberRole": "somestring"
         "tnxEnabled": "somestring", 
         "topicDescription": "somestring", 
         "topicName": "somestring", 
@@ -4693,23 +4611,19 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
 .. code-block:: javascript
 
     {
-        "bytes": [
-            "somestring", 
-            "somestring"
-        ], 
         "clients": [
             {
                 "action": [
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }, 
             {
@@ -4717,13 +4631,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
                     "somestring", 
                     "somestring"
                 ], 
+                "clientIdentity": "somestring", 
                 "clientRole": "somestring", 
                 "dcaeLocationName": "somestring", 
                 "fqtn": "somestring", 
                 "lastMod": "2015-01-01T15:00:00.000Z", 
                 "mrClientId": "somestring", 
                 "status": "EMPTY", 
-                "statusValid": true, 
                 "topicURL": "somestring"
             }
         ], 
@@ -4732,13 +4646,13 @@ Type: :ref:`Topic <d_2e99841971da81b9d240071b86bf168d>`
         "fqtnStyle": "FQTN_NOT_SPECIFIED", 
         "globalMrURL": "somestring", 
         "lastMod": "2015-01-01T15:00:00.000Z", 
-        "numClients": 1, 
         "owner": "somestring", 
         "partitionCount": "somestring", 
+        "publisherRole": "somestring", 
         "replicationCase": "REPLICATION_NOT_SPECIFIED", 
         "replicationCount": "somestring", 
         "status": "EMPTY", 
-        "statusValid": true
+        "subscriberRole": "somestring"
         "tnxEnabled": "somestring", 
         "topicDescription": "somestring", 
         "topicName": "somestring", 
@@ -4813,9 +4727,8 @@ DR_Node Model Structure
         dcaeLocationName | No | string |  |  | 
         fqdn | No | string |  |  | 
         hostName | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
+        lastMod | No | string | date-time |  | datestamp for last update to this object
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         version | No | string |  |  | 
 
 .. _d_e926d3fa8701e0cc9c8ed1761b3255cd:
@@ -4830,10 +4743,9 @@ DR_Pub Model Structure
 
         dcaeLocationName | No | string |  |  | 
         feedId | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
+        lastMod | No | string | date-time |  | datestamp for last update to this object
         pubId | No | string |  |  | 
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         username | No | string |  |  | 
         userpwd | No | string |  |  | 
 
@@ -4851,11 +4763,10 @@ DR_Sub Model Structure
         dcaeLocationName | No | string |  |  | 
         deliveryURL | No | string |  |  | 
         feedId | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
+        lastMod | No | string | date-time |  | datestamp for last update to this object
         logURL | No | string |  |  | 
         owner | No | string |  |  | 
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         subId | No | string |  |  | 
         suspended | No | boolean |  |  | 
         use100 | No | boolean |  |  | 
@@ -4876,11 +4787,10 @@ DcaeLocation Model Structure
         clli | No | string |  |  | 
         dcaeLayer | No | string |  |  | 
         dcaeLocationName | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
+        lastMod | No | string | date-time |  | datestamp for last update to this object
         local | No | boolean |  |  | 
         openStackAvailabilityZone | No | string |  |  | 
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         subnet | No | string |  |  | 
 
 .. _d_4ea0e7758a1f8502222793e4a13b04f7:
@@ -4897,11 +4807,10 @@ Dmaap Model Structure
         bridgeAdminTopic | No | string |  |  | 
         dmaapName | No | string |  |  | 
         drProvUrl | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
+        lastMod | No | string | date-time |  | datestamp for last update to this object
         loggingUrl | No | string |  |  | 
         nodeKey | No | string |  |  | 
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         topicNsRoot | No | string |  |  | 
         version | No | string |  |  | 
 
@@ -4922,13 +4831,12 @@ Feed Model Structure
         feedName | No | string |  |  | 
         feedVersion | No | string |  |  | 
         formatUuid | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
+        lastMod | No | string | date-time |  | datestamp for last update to this object
         logURL | No | string |  |  | 
         owner | No | string |  |  | 
         publishURL | No | string |  |  | 
         pubs | No | array of :ref:`DR_Pub <d_e926d3fa8701e0cc9c8ed1761b3255cd>` |  |  | 
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         subs | No | array of :ref:`DR_Sub <d_48cf328d246f41e1d11a09251b042f02>` |  |  | 
         subscribeURL | No | string |  |  | 
         suspended | No | boolean |  |  | 
@@ -4943,15 +4851,15 @@ MR_Client Model Structure
     :header: "Name", "Required", "Type", "Format", "Properties", "Description"
     :widths: 20, 10, 15, 15, 30, 25
 
-        action | No | array of string |  |  | 
-        clientRole | No | string |  |  | 
-        dcaeLocationName | No | string |  |  | 
-        fqtn | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
-        mrClientId | No | string |  |  | 
+        action | No | array of string |  |  | one or more actions from the set ('pub', 'sub', 'view') for which this client needs Permission
+        clientIdentity | No | string |  |  | an AAF identity to be associated to an appropriate topic Role
+        clientRole | No | string |  |  | an AAF Role to be granted an appropriate Permission.  If specified, takes precedence over clientIdentity, for backwards compatibility.
+        dcaeLocationName | No | string |  |  | a tag indicating a logical deployment site
+        fqtn | No | string |  |  | Fully Qualified Topic Name constructed by dbcapi
+        lastMod | No | string | date-time |  | datestamp for last update to this object
+        mrClientId | No | string |  |  | a unique identifier generated by dbcapi for this client
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
-        topicURL | No | string |  |  | 
+        topicURL | No | string |  |  | the URL for a MR instance - typically in the same dcaeLocation - that this client should use to access the topic
 
 .. _d_eec7176a0080debe1b19c2dad2e97c24:
 
@@ -4969,7 +4877,6 @@ MR_Cluster Model Structure
         replicationGroup | No | string |  |  | 
         sourceReplicationPort | No | string |  |  | 
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         targetReplicationPort | No | string |  |  | 
         topicPort | No | string |  |  | 
         topicProtocol | No | string |  |  | 
@@ -4984,11 +4891,10 @@ MirrorMaker Model Structure
     :header: "Name", "Required", "Type", "Format", "Properties", "Description"
     :widths: 20, 10, 15, 15, 30, 25
 
-        lastMod | No | string | date-time |  | 
+        lastMod | No | string | date-time |  | datestamp for last update to this object
         mmName | No | string |  |  | 
         sourceCluster | No | string |  |  | 
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
         targetCluster | No | string |  |  | 
         topicCount | No | integer | int32 |  | 
         topics | No | array of string |  |  | 
@@ -5004,22 +4910,21 @@ Topic Model Structure
     :header: "Name", "Required", "Type", "Format", "Properties", "Description"
     :widths: 20, 10, 15, 15, 30, 25
 
-        bytes | No | array of string |  |  | 
-        clients | No | array of :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>` |  |  | 
-        formatUuid | No | string |  |  | 
-        fqtn | No | string |  |  | 
-        fqtnStyle | No | string |  | {'enum': ['FQTN_NOT_SPECIFIED', 'FQTN_LEGACY_FORMAT', 'FQTN_PROJECTID_FORMAT', 'FQTN_PROJECTID_VERSION_FORMAT']} | 
-        globalMrURL | No | string |  |  | 
-        lastMod | No | string | date-time |  | 
-        numClients | No | integer | int32 |  | 
-        owner | No | string |  |  | 
-        partitionCount | No | string |  |  | 
-        replicationCase | No | string |  | {'enum': ['REPLICATION_NOT_SPECIFIED', 'REPLICATION_NONE', 'REPLICATION_EDGE_TO_CENTRAL', 'REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL', 'REPLICATION_CENTRAL_TO_EDGE', 'REPLICATION_CENTRAL_TO_GLOBAL', 'REPLICATION_GLOBAL_TO_CENTRAL', 'REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE', 'REPLICATION_EDGE_TO_FQDN', 'REPLICATION_FQDN_TO_EDGE', 'REPLICATION_FQDN_TO_GLOBAL', 'REPLICATION_GLOBAL_TO_FQDN', 'REPLICATION_EDGE_TO_FQDN_TO_GLOBAL', 'REPLICATION_GLOBAL_TO_FQDN_TO_EDGE']} | 
-        replicationCount | No | string |  |  | 
+        clients | No | array of :ref:`MR_Client <d_56ff81dc98986e27074d9be2731e3f4c>` |  |  | an array of `MR_Client` objects associated to this `Topic`
+        formatUuid | No | string |  |  | a reference to an identifier that describes a data format used for this `Topic`
+        fqtn | No | string |  |  | Fully Qualified Topic Name constructed by dbcapi, following the rules for `fqtnStyle`
+        fqtnStyle | No | string |  | {'enum': ['FQTN_NOT_SPECIFIED', 'FQTN_LEGACY_FORMAT', 'FQTN_PROJECTID_FORMAT', 'FQTN_PROJECTID_VERSION_FORMAT']} | the construction rule for the `fqtn` field
+        globalMrURL | No | string |  |  | the URL of an outside MR instance
+        lastMod | No | string | date-time |  | datestamp for last update to this object
+        owner | No | string |  |  | a label used to identify who requested this `Topic` to be provisioned.  In the future this may be an AAF Identity.
+        partitionCount | No | string |  |  | the kafka attribute for specifying the number of partitions
+        publisherRole | No | string |  |  | a value generated by dbcapi, this AAF Role has permission to publish to this `Topic`
+        replicationCase | No | string |  | {'enum': ['REPLICATION_NOT_SPECIFIED', 'REPLICATION_NONE', 'REPLICATION_EDGE_TO_CENTRAL', 'REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL', 'REPLICATION_CENTRAL_TO_EDGE', 'REPLICATION_CENTRAL_TO_GLOBAL', 'REPLICATION_GLOBAL_TO_CENTRAL', 'REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE', 'REPLICATION_EDGE_TO_FQDN', 'REPLICATION_FQDN_TO_EDGE', 'REPLICATION_FQDN_TO_GLOBAL', 'REPLICATION_GLOBAL_TO_FQDN', 'REPLICATION_EDGE_TO_FQDN_TO_GLOBAL', 'REPLICATION_GLOBAL_TO_FQDN_TO_EDGE']} | An indicator for how this `Topic` should be replicated when there are more than one `MR_Cluster` instances
+        replicationCount | No | string |  |  | the kafka attribute for specifying replication within an `MR_Cluster` instance
         status | No | string |  | {'enum': ['EMPTY', 'NEW', 'STAGED', 'VALID', 'INVALID', 'DELETED']} | 
-        statusValid | No | boolean |  |  | 
+        subscriberRole | No | string |  |  | a value generated by dbcapi, this AAF Role has permission to subscribe to this `Topic`
         tnxEnabled | No | string |  |  | 
-        topicDescription | No | string |  |  | 
-        topicName | No | string |  |  | 
-        version | No | string |  |  | 
+        topicDescription | No | string |  |  | a description of what this Topic is used for
+        topicName | No | string |  |  | the short name used by humans, and utilized to construct the `FQTN`
+        version | No | string |  |  | a hook for any versioning needed for managing a `Topic` over time
 
diff --git a/pom.xml b/pom.xml
index fdef5cb..975866c 100644 (file)
--- a/pom.xml
+++ b/pom.xml
            <jackson.version>2.9.5</jackson.version>
                <jersey.version>2.26</jersey.version>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-               <jettyVersion>9.3.8.RC0</jettyVersion> 
+               <jettyVersion>9.4.12.RC2</jettyVersion> 
                <eelf.version>1.0.0</eelf.version>
-               <artifact.version>1.0.19-SNAPSHOT</artifact.version>
+               <artifact.version>1.0.20-SNAPSHOT</artifact.version>
                <!-- SONAR -->
                <jacoco.version>0.7.7.201606060606</jacoco.version>
                <sonar-jacoco-listeners.version>3.2</sonar-jacoco-listeners.version>
diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java
new file mode 100644 (file)
index 0000000..aa4fb89
--- /dev/null
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2017 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.dmaap.dbcapi.aaf;
+
+import java.util.ArrayList;
+
+import org.apache.log4j.Logger;
+import org.onap.dmaap.dbcapi.util.DmaapConfig;
+
+
+public class AafNamespace extends AafObject  {
+       static final Logger logger = Logger.getLogger(AafNamespace.class);
+       
+       private String  name;
+       private ArrayList<String>       admin;
+       private ArrayList<String>       responsible;
+       
+       // in some environments, an AAF Namespace must be owned by a human.
+       // So, when needed, this var can be set via a property
+       static private String NsOwnerIdentity;
+       
+       public AafNamespace(String ns, String identity ) {
+               super();
+               DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
+               NsOwnerIdentity = p.getProperty( "aaf.NsOwnerIdentity", "");
+               this.admin = new ArrayList<String>();
+               this.responsible = new ArrayList<String>();
+               
+               this.name = ns;
+               this.admin.add( identity );
+               this.responsible.add( NsOwnerIdentity );
+       }
+       public void setName( String ns ) {
+               this.name = ns;
+       }
+       public String getName() {
+               return name;
+       }
+       public ArrayList<String> getAdmin() {
+               return admin;
+       }
+       public void setAdmin(ArrayList<String> admin) {
+               this.admin = admin;
+       }
+       public ArrayList<String> getResponsible() {
+               return responsible;
+       }
+       public void setResponsible(ArrayList<String> responsible) {
+               this.responsible = responsible;
+       }
+
+
+       // given an Array of Strings, return a String that is a separated list of quoted strings.
+       // e.g. input [ a, b, c ]
+       //       output  "a", "b", "c"
+       private String separatedList( ArrayList<String> list, String sep ) {
+               if (list.isEmpty()) return null;
+               String aList = new String();
+               String delim = "";
+               for( String item: list) {
+                       if( ! item.isEmpty()) {
+                               aList += String.format( "%s\"%s\"", delim, item );
+                               delim = sep;
+                       }
+               }
+               return aList;
+       }
+
+       public String toJSON() {
+
+               String postJSON = String.format(" { \"name\": \"%s\", \"admin\": [", 
+                               this.getName()
+                                );
+               postJSON += separatedList( this.getAdmin(), "," );
+               postJSON += "], \"responsible\":[";
+               postJSON += separatedList( this.getResponsible(), ",");
+               postJSON += "]}";
+               logger.info( "returning JSON: " + postJSON);
+                       
+               return postJSON;
+       }
+       
+       
+       
+       
+}
diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java
new file mode 100644 (file)
index 0000000..6acbefd
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2017 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.dmaap.dbcapi.aaf;
+
+import org.apache.log4j.Logger;
+
+
+public class AafRole extends AafObject  {
+       static final Logger logger = Logger.getLogger(AafRole.class);
+       
+       private String  namespace;
+       private String  role;
+       
+       public AafRole(String ns,  String role) {
+               super();
+               this.namespace = ns;
+               this.role = role;
+       }
+       public void setNamespace( String ns ) {
+               this.namespace = ns;
+       }
+       public String getNamespace() {
+               return namespace;
+       }
+       public void setRole(String role) {
+               this.role = role;
+       }
+       public String getRole() {
+               return role;
+       }
+       public String getFullyQualifiedRole() {
+               return namespace + "." + role;
+       }
+
+       public String toJSON() {
+
+               String postJSON = String.format(" { \"name\": \"%s.%s\"}", 
+                               this.getNamespace(), 
+                               this.getRole() );
+               logger.info( "returning JSON: " + postJSON);
+                       
+               return postJSON;
+       }
+       
+       
+       
+       
+}
index 112ab11..253ad11 100644 (file)
@@ -36,9 +36,21 @@ public class AafService extends BaseLoggingClass {
        private AafConnection aaf;
        private ServiceType ctype;
        private String aafURL ;
+       private String identity;
        private boolean useAAF = false;
        
        
+       
+       public String getIdentity() {
+               return identity;
+       }
+
+
+       public void setIdentity(String identity) {
+               this.identity = identity;
+       }
+
+
        private String getCred( boolean wPwd ) {
                String mechIdProperty = null;
                String pwdProperty = null;
@@ -55,7 +67,7 @@ public class AafService extends BaseLoggingClass {
                        logger.error( "Unexpected case for AAF credential type: " + ctype );
                        return null;
                }
-               String user = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" );
+               identity = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" );
 
                String pwd = "";
                String encPwd = p.getProperty( pwdProperty, "notSet" );
@@ -64,14 +76,15 @@ public class AafService extends BaseLoggingClass {
                pwd = decryptor.decrypt(encPwd);
                
                if ( wPwd ) {
-                       return user + ":" + pwd;
+                       return identity + ":" + pwd;
                } else {
-                       return user;
+                       return identity;
                }
                
                
        }
        
+       
        public AafService(ServiceType t ) {
                DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
                aafURL = p.getProperty( "aaf.URL", "https://authentication.domain.netset.com:8095/proxy/");
@@ -92,70 +105,16 @@ public class AafService extends BaseLoggingClass {
        }
        
        public int addPerm(DmaapPerm perm) {
-
-               int rc = -1;
                logger.info( "entry: addPerm() "  );
-               String pURL = aafURL + "authz/perm";
-               logger.info( "addPerm=" + useAAF );
-               if ( useAAF ) {
-                       logger.info( "addPerm: " + perm.toJSON());
-                       rc = aaf.postAaf( perm, pURL );
-               } else {
-                       rc = 201;
-               }
-        switch( rc ) {
-       case 401:
-       case 403:
-                       errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR,  getCred( false ) );
-               System.exit(1);
-       case 409:
-               logger.warn( "Perm already exists. Possible conflict.");
-               break;
-               
-       case 201:
-               logger.info( "expected response: " + rc);
-               break;
-               default :
-               logger.error( "Unexpected response: " + rc );
-               break;
-        }
-               
-               return rc;
+               return doPost( perm, "authz/perm", 201);
        }
        public int addGrant(DmaapGrant grant ) {
-
-               int rc = -1;
                logger.info( "entry: addGrant() "  );
-
-               String pURL = aafURL + "authz/role/perm";
-               logger.info( "addGrant: useAAF=" + useAAF );
-               if ( useAAF ) {
-                       logger.info( "addGrant: " + grant.toJSON() );
-                       rc = aaf.postAaf( grant, pURL );
-               } else {
-                       rc = 201;
-               }
-               
-        switch( rc ) {
-       case 401:
-       case 403:
-                       errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR,  getCred( false ) );
-               System.exit(1);
-               break;
-
-       case 409:
-               logger.warn( "Perm already exists. Possible conflict.");
-               break;
-               
-       case 201:
-               logger.info( "expected response" );
-               break;
-               default :
-               logger.error( "Unexpected response: " + rc );
-               break;
-        }
-               
-               return rc;
+               return doPost( grant, "authz/role/perm", 201 );
+       }
+       public int addUserRole( AafUserRole ur ) {
+               logger.info( "entry: addUserRole() "  );
+               return doPost( ur, "authz/userRole", 201 );
        }
 
        public int delGrant( DmaapGrant grant ) {
@@ -191,5 +150,49 @@ public class AafService extends BaseLoggingClass {
                return rc;
        }
 
+       public int addRole(AafRole role) {
+               logger.info( "entry: addRole() "  );
+               return doPost( role, "authz/role", 201 );
+       }
+
+       
+       
+       public int addNamespace(AafNamespace ns) {
+               logger.info( "entry: addNamespace() "  );
+               return doPost( ns, "authz/ns", 201 );
+       }
+
+       
+       private int doPost( AafObject obj, String uri, int expect ) {
+               int rc = -1;
+               logger.info( "entry: doPost() "  );
+               String pURL = aafURL + uri;
+               logger.info( "doPost: useAAF=" + useAAF );
+               if ( useAAF ) {
+                       logger.info( "doPost: " + obj.toJSON());
+                       rc = aaf.postAaf( obj, pURL );
+               } else {
+                       rc = expect;
+               }
+        switch( rc ) {
+       case 401:
+       case 403:
+                       errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR,  getCred( false ) );
+               System.exit(1);
+       case 409:
+               logger.warn( "Object for " + uri + " already exists. Possible conflict.");
+               break;
+               
 
+               default :
+                       if ( rc == expect ) {
+                               logger.info( "expected response: " + rc);
+                       } else {
+                               logger.error( "Unexpected response: " + rc );
+                       }
+               break;
+        }
+        
+        return rc;
+       }
 }
diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafUserRole.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafUserRole.java
new file mode 100644 (file)
index 0000000..7b4f882
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2017 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.dmaap.dbcapi.aaf;
+
+import org.apache.log4j.Logger;
+
+
+public class AafUserRole extends AafObject  {
+       static final Logger logger = Logger.getLogger(AafUserRole.class);
+
+       private String  identity;
+       private String  role;
+
+
+       
+       public AafUserRole(String identity,  String role ) {
+               super();
+               this.identity = identity;
+               this.role = role;
+       }
+
+       public void setRole(String role) {
+               this.role = role;
+       }
+       public String getRole() {
+               return role;
+       }
+
+       public String getIdentity() {
+               return identity;
+       }
+
+       public void setIdentity(String identity) {
+               this.identity = identity;
+       }
+
+       public String toJSON() {
+
+               String postJSON = String.format(" { \"user\": \"%s\", \"role\": \"%s\" }",  
+                               this.getIdentity(), 
+                               this.getRole()
+                               );
+               logger.info( "returning JSON: " + postJSON);
+                       
+               return postJSON;
+       }
+       
+       
+       
+       
+}
index 5b4d7de..9defe34 100644 (file)
@@ -3,7 +3,7 @@
   * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2018 IBM.
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -98,10 +98,10 @@ public class AafLurAndFish implements ApiAuthorizationCheckInterface {
                try {
                        alaf.check("mmanager@people.osaaf.org", "demo123456!", p);
                } catch (AuthenticationErrorException aee ) {
+                       logger.error(aee);
                        logger.error( "Check failed for: " + p.toJSON());
-                       System.exit(-1);
+                       System.exit(-1);
                }
-               logger.info( "Check succeeded for: " + p.toJSON() );
-               
+               logger.info("Check succeeded for: " + p.toJSON());
            }
 }
index f3b9ebc..bcadf40 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * 
+ * Modifications Copyright (C) 2018 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -172,8 +174,8 @@ public  class ApiPerms extends BaseLoggingClass {
        }
        
        public void setEnvMap() {
-               Dmaap dmaap = new DmaapService().getDmaap();
-               String dmaapName = dmaap.getDmaapName();
+               Dmaap dmaapVar = new DmaapService().getDmaap();
+               String dmaapName = dmaapVar.getDmaapName();
                PermissionMap.initMap( envMap, dmaapName );
        }
        
index 34d36ba..cc6f02c 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.dmaap.dbcapi.client;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.ConnectException;
-import java.net.ProtocolException;
-import java.net.SocketException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import javax.net.ssl.HttpsURLConnection;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
 import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum;
 import org.onap.dmaap.dbcapi.model.ApiError;
-import org.onap.dmaap.dbcapi.model.DR_Pub;
 import org.onap.dmaap.dbcapi.model.DR_Sub;
 import org.onap.dmaap.dbcapi.model.Feed;
 import org.onap.dmaap.dbcapi.service.DmaapService;
-import org.onap.dmaap.dbcapi.util.RandomInteger;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.*;
+import java.net.ConnectException;
+import java.net.ProtocolException;
+import java.net.SocketException;
+import java.net.URL;
+import java.util.Arrays;
 
 
 
index 94d671f..51bad4f 100644 (file)
@@ -3,7 +3,7 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2018 IBM.
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.dmaap.dbcapi.client;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.ConnectException;
-import java.net.HttpURLConnection;
-import java.net.ProtocolException;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-
-import javax.net.ssl.HttpsURLConnection;
-
 import org.apache.commons.codec.binary.Base64;
-import org.apache.log4j.Logger;
 import org.onap.dmaap.dbcapi.aaf.AafDecrypt;
 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
 import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum;
@@ -45,6 +30,11 @@ import org.onap.dmaap.dbcapi.model.MR_Cluster;
 import org.onap.dmaap.dbcapi.model.Topic;
 import org.onap.dmaap.dbcapi.util.DmaapConfig;
 
+import javax.net.ssl.HttpsURLConnection;
+import java.io.*;
+import java.net.*;
+import java.util.Arrays;
+
 public class MrProvConnection extends BaseLoggingClass{
            
        private String provURL;
index 492037c..a92dbc7 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -63,7 +65,7 @@ public class MrTopicConnection extends BaseLoggingClass  {
 
                topicURL = cluster.getTopicProtocol() + "://" + fqdn + ":" + cluster.getTopicPort() + "/events/" + topic ;
 
-               if ( cluster.getTopicProtocol().equals( "https")) {
+               if ( "https".equals(cluster.getTopicProtocol())) {
                        return makeSecureConnection( topicURL );
                }
                return makeConnection( topicURL );
index 11b0d15..934b7bb 100644 (file)
@@ -200,22 +200,18 @@ public class DatabaseClass extends BaseLoggingClass {
                        mirrors = new HashMap<>();
                }
                dmaap.init(new Dmaap("0", "", "", "", "", "", "", ""));
-               // check for, and set up initial data, if it isn't already there
+               // force initial read from DB, if it exists
+               @SuppressWarnings("unused")
                Dmaap dmx = dmaap.get();
-               if ("0".equals(dmx.getVersion())) {
-
-                       dmx = new Dmaap("0", "", "", "", "", "", "", "");
-                       dmx.setDmaapName(p.getProperty("DmaapName"));
-                       dmx.setDrProvUrl("https://" + p.getProperty("DR.provhost", "notSet"));
-                       dmx.setTopicNsRoot(p.getProperty("topicNsRoot"));
-                       dmx.setBridgeAdminTopic("DCAE_MM_AGENT");
+               
+               // old code in this spot would read from properties file as part of init.
+               // but all those properties are now set via /dmaap API
 
-                       dmaap.update(dmx);
-               }
                } catch (Exception e) {
                        errorLogger.error("Error", e);
                        errorLogger.error(DmaapbcLogMessageEnum.DB_UPDATE_ERROR, e.getMessage());
                }
+
        }
        
        public static synchronized String getNextClientId() {
index 8e804b2..1b3f824 100644 (file)
@@ -30,8 +30,11 @@ import javax.xml.bind.annotation.XmlRootElement;
 
 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
 
+import io.swagger.annotations.ApiModelProperty;
+
 @XmlRootElement
 public abstract class DmaapObject extends BaseLoggingClass {
+       @ApiModelProperty( value = "datestamp for last update to this object")
        protected Date lastMod;
        protected       DmaapObject_Status      status;
        
@@ -81,6 +84,7 @@ public abstract class DmaapObject extends BaseLoggingClass {
                }
        }
        
+       @ApiModelProperty( hidden=true )
        public boolean isStatusValid() {
                if ( this.status == DmaapObject_Status.VALID ) {
                        return true;
index 648812f..b78377b 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -262,8 +264,7 @@ public class Feed extends DmaapObject {
                }
                
                public static String getSubProvURL( String feedId ) {
-                       String ret = new String();
-                       ret = new DmaapService().getDmaap().getDrProvUrl() + "/subscribe/" + feedId ;
+                       String ret = new DmaapService().getDmaap().getDrProvUrl() + "/subscribe/" + feedId ;
                        return ret;
                }
 
index 580800c..f182fd6 100644 (file)
@@ -26,15 +26,25 @@ import javax.xml.bind.annotation.XmlRootElement;
 
 import org.onap.dmaap.dbcapi.database.DatabaseClass;
 
+import io.swagger.annotations.ApiModelProperty;
+
 @XmlRootElement
 public class MR_Client extends DmaapObject {
 
+       @ApiModelProperty( value="a tag indicating a logical deployment site")
        private String dcaeLocationName;
+       @ApiModelProperty( value="the URL for a MR instance - typically in the same dcaeLocation - that this client should use to access the topic")
        private String  topicURL;
+       @ApiModelProperty( value="Fully Qualified Topic Name constructed by dbcapi")
        private String fqtn;
+       @ApiModelProperty( value="an AAF Role to be granted an appropriate Permission.  If specified, takes precedence over clientIdentity, for backwards compatibility.")
        private String clientRole;
+       @ApiModelProperty( value="one or more actions from the set (\"pub\", \"sub\", \"view\") for which this client needs Permission")
        private String[] action;
+       @ApiModelProperty( value="a unique identifier generated by dbcapi for this client")
        private String mrClientId;
+       @ApiModelProperty( value="an AAF identity to be associated to an appropriate topic Role")
+       private String clientIdentity;
        
 
        public MR_Client() {
@@ -97,7 +107,24 @@ public class MR_Client extends DmaapObject {
        public void setAction(String[] action) {
                this.action = action;
        }
-
+       
+       @ApiModelProperty( hidden=true )
+       public boolean isPublisher() {
+               return hasAction( "pub");
+       }
+       @ApiModelProperty( hidden=true )
+       public boolean isSubscriber() {
+               return hasAction( "sub");
+       }
+       
+       public boolean hasAction( String val ) {
+               for (String s: this.action) {
+                       if ( s!= null && s.equals(val)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
        public String getMrClientId() {
                return mrClientId;
        }
@@ -115,5 +142,21 @@ public class MR_Client extends DmaapObject {
        public void setTopicURL(String topicURL) {
                this.topicURL = topicURL;
        }
+
+       public String getClientIdentity() {
+               return clientIdentity;
+       }
+
+       public void setClientIdentity(String clientIdentity) {
+               this.clientIdentity = clientIdentity;
+       }
+       public boolean hasClientIdentity() {
+               if ( this.clientIdentity == null || this.clientIdentity.isEmpty() ) {
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+
        
 }
index c2f278d..7eea5f1 100644 (file)
@@ -30,6 +30,8 @@ import javax.xml.bind.annotation.XmlRootElement;
 
 import org.onap.dmaap.dbcapi.util.DmaapConfig;
 
+import io.swagger.annotations.ApiModelProperty;
+
 import org.onap.dmaap.dbcapi.service.DmaapService;
 import org.onap.dmaap.dbcapi.service.TopicService;
 
@@ -37,20 +39,36 @@ import org.onap.dmaap.dbcapi.service.TopicService;
 @XmlRootElement
 public class Topic extends DmaapObject  {
 
+       @ApiModelProperty( value="Fully Qualified Topic Name constructed by dbcapi, following the rules for `fqtnStyle`")
        private String fqtn;
+       @ApiModelProperty( value="the short name used by humans, and utilized to construct the `FQTN`")
        private String topicName;
+       @ApiModelProperty( value="a description of what this Topic is used for")
        private String  topicDescription;
        private String  tnxEnabled;
+       @ApiModelProperty( value="a label used to identify who requested this `Topic` to be provisioned.  In the future this "
+                       + "may be an AAF Identity.")
        private String  owner;
+       @ApiModelProperty( value="a reference to an identifier that describes a data format used for this `Topic`")
        private String  formatUuid;
+       @ApiModelProperty( value="An indicator for how this `Topic` should be replicated when there are more than one `MR_Cluster` instances")
        private ReplicationType replicationCase;  
+       @ApiModelProperty( value="the URL of an outside MR instance")
        private String  globalMrURL;            // optional: URL of global MR to replicate to/from
+       @ApiModelProperty( value="the construction rule for the `fqtn` field")
        private FqtnType  fqtnStyle;
-       private String  version;        
+       @ApiModelProperty( value="a hook for any versioning needed for managing a `Topic` over time")
+       private String  version;
+       @ApiModelProperty( value="the kafka attribute for specifying the number of partitions")
        private String  partitionCount;
+       @ApiModelProperty( value="the kafka attribute for specifying replication within an `MR_Cluster` instance")
        private String  replicationCount;
+       @ApiModelProperty( value="a value generated by dbcapi, this AAF Role has permission to publish to this `Topic`")
+       private String  publisherRole;
+       @ApiModelProperty( value="a value generated by dbcapi, this AAF Role has permission to subscribe to this `Topic`")
+       private String  subscriberRole;
 
-
+       @ApiModelProperty( value="an array of `MR_Client` objects associated to this `Topic`")
        private ArrayList<MR_Client> clients;
 
 
@@ -220,6 +238,7 @@ public class Topic extends DmaapObject  {
                return clients;
        }
 
+       @ApiModelProperty( hidden=true )
        public int getNumClients() {
                if ( this.clients == null ) {
                        return 0;
@@ -282,6 +301,18 @@ public class Topic extends DmaapObject  {
 
 
 
+       public String getPublisherRole() {
+               return publisherRole;
+       }
+       public void setPublisherRole(String publisherRole) {
+               this.publisherRole = publisherRole;
+       }
+       public String getSubscriberRole() {
+               return subscriberRole;
+       }
+       public void setSubscriberRole(String subscriberRole) {
+               this.subscriberRole = subscriberRole;
+       }
        public String toProvJSON() {
                StringBuilder str = new StringBuilder();
                str.append("{ \"topicName\": \"");
@@ -297,7 +328,7 @@ public class Topic extends DmaapObject  {
                logger.info( str.toString() );
                return str.toString();
        }
-       
+       @ApiModelProperty( hidden=true )
        public byte[] getBytes() {
                return toProvJSON().getBytes(StandardCharsets.UTF_8);
        }
index e6fede7..192b63d 100644 (file)
@@ -4,6 +4,8 @@
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
  * 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
@@ -121,7 +123,7 @@ public class BridgeResource extends BaseLoggingClass {
                        }
                        logger.info( "Count for "+ key + ": " + mCnt);
                        totCnt += mCnt;
-                       if (showDetail) {
+                       if (showDetail && mm!=null) {
                                brTopic[s] =  new BrTopic();
                                brTopic[s].setBrSource( mm.getSourceCluster());
                                brTopic[s].setBrTarget(mm.getTargetCluster());
index 58a39df..28bfdc5 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -120,8 +122,6 @@ public class DR_SubResource extends BaseLoggingClass {
                
                fnew.setSubs(subs);
                logger.info( "update feed");
-               //feeds.updateFeed( fnew, err );                        
-               
                return resp.success(Status.CREATED.getStatusCode(), snew);
 
        }
index 1ca4a53..a621338 100644 (file)
@@ -79,8 +79,11 @@ public class MR_ClientResource extends BaseLoggingClass {
        }
                
        @POST
-       @ApiOperation( value = "return MR_Client details", 
-       notes = "Create a  `MR_Client` object.", 
+       @ApiOperation( value = "Associate an MR_Client object to a Topic", 
+       notes = "Create a  `MR_Client` object."
+                       + "The `dcaeLocation` attribute is used to match an `MR_Cluster` object with the same value, with the intent of localizing message traffic."
+                       + "  In legacy implementation, the `clientRole` is granted appropriate permission in AAF."
+                       + "  Newer implementions may instead specify an AAF Identity, which will be added to the appropriate `Topic` role.", 
        response = MR_Client.class)
        @ApiResponses( value = {
            @ApiResponse( code = 200, message = "Success", response = MR_Client.class),
@@ -94,7 +97,11 @@ public class MR_ClientResource extends BaseLoggingClass {
                try {
                        resp.required( "fqtn", client.getFqtn(), "");
                        resp.required( "dcaeLocationName", client.getDcaeLocationName(), "");
-                       resp.required( "clientRole", client.getClientRole(), "" );
+                       String s = client.getClientRole();
+                       if ( s == null ) {
+                               s = client.getClientIdentity();
+                       }
+                       resp.required( "clientRole or clientIdentity", s, "" );
                        resp.required( "action", client.getAction(), "");
 
                } catch ( RequiredFieldException rfe ) {
@@ -139,7 +146,7 @@ public class MR_ClientResource extends BaseLoggingClass {
        }
                
        @PUT
-       @ApiOperation( value = "return MR_Client details", 
+       @ApiOperation( value = "Update an MR_Client object", 
        notes = "Update a  `MR_Client` object, specified by clientId", 
        response = MR_Client.class)
        @ApiResponses( value = {
@@ -175,7 +182,7 @@ public class MR_ClientResource extends BaseLoggingClass {
        }
                
        @DELETE
-       @ApiOperation( value = "return MR_Client details", 
+       @ApiOperation( value = "Delete an MR_Client object", 
        notes = "Delete a  `MR_Client` object, specified by clientId", 
        response = MR_Client.class)
        @ApiResponses( value = {
index 5f027aa..be1b3ac 100644 (file)
@@ -91,8 +91,11 @@ public class TopicResource extends BaseLoggingClass {
        }
                
        @POST
-       @ApiOperation( value = "return Topic details", 
-       notes = "Create  `Topic` object.", 
+       @ApiOperation( value = "Create a Topic object", 
+       notes = "Create  `Topic` object."
+                       + "For convenience, the message body may populate the `clients` array, in which case each entry will be added as an `MR_Client`."
+                       + "  Beginning in ONAP Dublin Release, dbcapi will create two AAF Roles by default, one each for the publisher and subscriber per topic."
+                       + "  MR_Clients can then specify an AAF Identity to be added to the appropriate default Role, avoiding the need to create Role(s) in advance.", 
        response = Topic.class)
        @ApiResponses( value = {
            @ApiResponse( code = 200, message = "Success", response = Topic.class),
index 748eedc..81c08b2 100644 (file)
@@ -2,7 +2,9 @@
  * ============LICENSE_START=======================================================
  * org.onap.dmaap
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 AT&T Intellectual Property.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 package org.onap.dmaap.dbcapi.server;
 
 
-import java.util.Properties;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.log4j.Logger;
-import org.eclipse.jetty.security.SecurityHandler;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.SecureRequestCustomizer;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.server.*;
 import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-
-
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
-
-import org.onap.dmaap.dbcapi.database.LoadSchema;
 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
+
+import java.util.Properties;
 /**
  * A  Jetty server which supports:
  *     - http and https (simultaneously for dev env)
index cf8c7c1..b478dca 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dcae
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -58,7 +60,7 @@ public class DR_NodeService extends BaseLoggingClass {
                private void setX( String X, String list, ApiError apiError ) {
                        DrProvConnection prov = new DrProvConnection();
                        prov.makeNodesConnection( X, list );    
-                       String resp = prov.doPutNodes( apiError );
+                       prov.doPutNodes( apiError );
                }
                
                private String removeFromList( String aNode, String aList ) {
index d6012a7..2fd75d0 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -94,7 +96,7 @@ public class DR_SubService extends BaseLoggingClass {
                prov = new DrProvConnection();
                prov.makeSubPostConnection( provURL );
                String resp = prov.doPostDr_Sub( sub, apiError );
-               if ( unit_test.equals( "Yes" ) ) {
+               if ( "Yes".equals(unit_test) ) {
                        resp = simulateResp( sub, "POST" );
                        apiError.setCode(200);
                }
index 5c2c8a3..408d000 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 package org.onap.dmaap.dbcapi.service;
 
 import java.util.ArrayList;
-
-
-
-
-
-
-
-
-
-
 import org.onap.dmaap.dbcapi.aaf.AafService;
 import org.onap.dmaap.dbcapi.aaf.DmaapGrant;
 import org.onap.dmaap.dbcapi.aaf.DmaapPerm;
@@ -43,7 +35,6 @@ import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum;
 import org.onap.dmaap.dbcapi.model.ApiError;
 import org.onap.dmaap.dbcapi.model.Dmaap;
 import org.onap.dmaap.dbcapi.model.MR_Client;
-import org.onap.dmaap.dbcapi.model.ReplicationType;
 import org.onap.dmaap.dbcapi.model.Topic;
 import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status;
 import org.onap.dmaap.dbcapi.util.DmaapConfig;
@@ -58,7 +49,7 @@ public class DmaapService  extends BaseLoggingClass  {
        
        String topicFactory; // = "org.openecomp.dcae.dmaap.topicFactory";
        String topicMgrRole; // = "org.openecomp.dmaapBC.TopicMgr";
-       String dcaeTopicNs; // = "org.openecomp.dcae.dmaap";
+       
        private boolean multiSite;
        
        
@@ -66,14 +57,14 @@ public class DmaapService  extends BaseLoggingClass  {
                DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
                topicFactory = p.getProperty("MR.TopicFactoryNS", "MR.topicFactoryNS.not.set");
                topicMgrRole = p.getProperty("MR.TopicMgrRole", "MR.TopicMgrRole.not.set" );
-               dcaeTopicNs = dmaapholder.get().getTopicNsRoot();
+
                multiSite = "true".equalsIgnoreCase(p.getProperty("MR.multisite", "true"));
                noEnvironmentPrefix = p.getProperty( "AAF.NoEnvironmentPrefix", "org.onap");
                
                logger.info( "DmaapService settings: " + 
                                " topicFactory=" + topicFactory +
                                " topicMgrRole=" + topicMgrRole +
-                               " dcaeTopicNs=" + dcaeTopicNs +
+                               
                                " multisite=" + multiSite +
                                " noEnvironmentPrefix=" + noEnvironmentPrefix
                                );
@@ -93,7 +84,7 @@ public class DmaapService  extends BaseLoggingClass  {
 
                        nd.setLastMod();
                        dmaapholder.update(nd);
-
+                       
                        AafService aaf = new AafService( ServiceType.AAF_Admin);
                        ApiPolicy apiPolicy = new ApiPolicy();
                        if ( apiPolicy.getUseAuthClass() ) {
@@ -137,7 +128,7 @@ public class DmaapService  extends BaseLoggingClass  {
                if ( ! dmaap.isStatusValid()  || ! nd.getDmaapName().equals(dmaap.getDmaapName()) || dmaap.getVersion().equals( "0") ) {
                        nd.setLastMod();
                        dmaapholder.update(nd);  //need to set this so the following perms will pick up any new vals.
-                       dcaeTopicNs = dmaapholder.get().getTopicNsRoot();
+                       //dcaeTopicNs = dmaapholder.get().getTopicNsRoot();
                        ApiPolicy apiPolicy = new ApiPolicy();
                        if ( apiPolicy.getUseAuthClass()) {
                                ApiPerms p = new ApiPerms();
@@ -168,6 +159,8 @@ public class DmaapService  extends BaseLoggingClass  {
        public String getTopicPerm( String val ) {
                Dmaap dmaap = dmaapholder.get();
                String nsRoot = dmaap.getTopicNsRoot();
+               if ( nsRoot == null ) { return null; }
+               
                String t;
                // in ONAP Casablanca, we assume no distinction of environments reflected in topic namespace
                if ( nsRoot.startsWith(noEnvironmentPrefix) ) {
@@ -192,7 +185,7 @@ public class DmaapService  extends BaseLoggingClass  {
 
        private boolean setTopicMgtPerms( Dmaap nd, AafService aaf ){
                String[] actions = { "create", "destroy" };
-               String instance = ":" + dcaeTopicNs + "." + nd.getDmaapName() + ".mr.topic:" + dcaeTopicNs + "." + nd.getDmaapName();
+               String instance = ":" + nd.getTopicNsRoot() + "." + nd.getDmaapName() + ".mr.topic:" + nd.getTopicNsRoot() + "." + nd.getDmaapName();
                
                for( String action : actions ) {
 
@@ -212,7 +205,7 @@ public class DmaapService  extends BaseLoggingClass  {
                        }
                }
                
-               String t = dcaeTopicNs +"." + nd.getDmaapName() + ".mr.topic";
+               String t = nd.getTopicNsRoot() +"." + nd.getDmaapName() + ".mr.topic";
                String[] s = { "view", "pub", "sub" };
                actions = s;
                instance = "*";
index baf6f2f..de18d95 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -73,7 +75,7 @@ public class FeedService  extends BaseLoggingClass {
                for( Feed f:  feeds.values() ) {
                        boolean keep = true;
                        if ( name != null ) {
-                               if ( match != null && match.equals("startsWith") ) {
+                               if ( match != null && "startsWith".equals(match) ) {
                                        if ( ! f.getFeedName().startsWith( name ) ) {
                                                logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't start with=" + name);
                                                keep = false;
index 5bd62cb..186a003 100644 (file)
@@ -38,6 +38,7 @@ import org.onap.dmaap.dbcapi.aaf.AafService;
 import org.onap.dmaap.dbcapi.aaf.DmaapGrant;
 import org.onap.dmaap.dbcapi.aaf.DmaapPerm;
 import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType;
+import org.onap.dmaap.dbcapi.aaf.AafUserRole;
 import org.onap.dmaap.dbcapi.client.MrProvConnection;
 import org.onap.dmaap.dbcapi.database.DatabaseClass;
 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
@@ -128,7 +129,22 @@ public class MR_ClientService extends BaseLoggingClass{
                        logger.info( "Client  dcaeLocation that doesn't exist or not specified" );
                        return null;
                }
-               grantClientPerms(  client,  err);
+               // original style: clients specified Role.  This has precedence for backwards
+               //                 compatibility.
+               // ONAP style: clients specify Identity to be assigned to generated Role
+               String role = client.getClientRole();
+               if ( role != null ) {
+                       grantClientRolePerms(  client,  err);
+               } else if ( client.hasClientIdentity() ){
+                       if ( client.isSubscriber() ) {
+                               role = topic.getSubscriberRole();
+                               assignIdentityToRole( client, role, err );
+                       } 
+                       if (client.isPublisher() ) {
+                               role = topic.getPublisherRole();
+                               assignIdentityToRole( client, role, err );
+                       }       
+               } 
                if ( ! client.isStatusValid()) {
                        return null;
                }
@@ -189,26 +205,46 @@ public class MR_ClientService extends BaseLoggingClass{
                return DmaapObject_Status.INVALID;
        }
        
-       private void grantClientPerms( MR_Client client, ApiError err) {
+       private void grantClientRolePerms( MR_Client client, ApiError err) {
                AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
                
                String instance = ":topic." + client.getFqtn();
                client.setStatus( DmaapObject_Status.VALID);
+               String role = client.getClientRole();
                for( String want : client.getAction() ) {
                        int rc;
                        DmaapPerm perm = new DmaapPerm( dmaap.getTopicPerm(), instance, want );
-                       DmaapGrant g = new DmaapGrant( perm, client.getClientRole() );
-                       rc = aaf.addGrant( g );
-                       if ( rc != 201 && rc != 409 ) {
-                               client.setStatus( DmaapObject_Status.INVALID);
-                               err.setCode(rc);
-                               err.setMessage( "Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + client.getClientRole() );
-                               logger.warn( err.getMessage());
-                               return;
-                       } 
+                       if ( role != null ) {
+                               DmaapGrant g = new DmaapGrant( perm, role );
+                               rc = aaf.addGrant( g );
+                               if ( rc != 201 && rc != 409 ) {
+                                       client.setStatus( DmaapObject_Status.INVALID);
+                                       err.setCode(rc);
+                                       err.setMessage( "Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + role );
+                                       logger.warn( err.getMessage());
+                                       return;
+                               } 
+                       } else {
+                               logger.warn( "No Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " because role is null " );
+                       }
                }
        }
        
+       private void assignIdentityToRole( MR_Client client, String role, ApiError err ) {
+               AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
+
+               AafUserRole ur = new AafUserRole( client.getClientIdentity(), role );
+               int rc = aaf.addUserRole( ur );
+               if ( rc != 201 && rc != 409 ) {
+                       client.setStatus( DmaapObject_Status.INVALID);
+                       err.setCode(rc);
+                       err.setMessage( "Failed to add user " + client.getClientIdentity()+  "  to " + role );
+                       logger.warn( err.getMessage());
+                       return;
+               }
+               client.setStatus( DmaapObject_Status.VALID);
+
+       }
        private void revokeClientPerms( MR_Client client, ApiError err) {
                AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
                
index dea5d83..db6389e 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -156,7 +158,7 @@ public class MR_ClusterService extends BaseLoggingClass {
                        cluster.setLastMod();
                        cluster.setStatus(DmaapObject_Status.INVALID);
                        mr_clusters.put( cluster.getDcaeLocationName(), cluster );
-               } else if ( loc.isCentral()  & multiSite ) {
+               } else if ( loc.isCentral() && multiSite ) {
                        ApiError resp = TopicService.setBridgeClientPerms( cluster );
                        if ( ! resp.is2xx() ) {
                                logger.error( "Unable to provision Bridge to " + cluster.getDcaeLocationName() );
index 49966d7..cfec54e 100644 (file)
@@ -29,7 +29,10 @@ import java.util.Set;
 
 import javax.ws.rs.core.Response.Status;
 
+import org.onap.dmaap.dbcapi.aaf.AafNamespace;
+import org.onap.dmaap.dbcapi.aaf.AafRole;
 import org.onap.dmaap.dbcapi.aaf.AafService;
+import org.onap.dmaap.dbcapi.aaf.DmaapGrant;
 import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType;
 import org.onap.dmaap.dbcapi.aaf.DmaapPerm;
 import org.onap.dmaap.dbcapi.database.DatabaseClass;
@@ -58,7 +61,6 @@ public class TopicService extends BaseLoggingClass {
        private Map<String, Topic> mr_topics = DatabaseClass.getTopics();
        
        private static DmaapService dmaapSvc = new DmaapService();
-       private static Dmaap dmaap = new DmaapService().getDmaap();
        private MR_ClientService clientService = new MR_ClientService();
        private MR_ClusterService clusters = new MR_ClusterService();
        private DcaeLocationService locations = new DcaeLocationService();
@@ -112,6 +114,94 @@ public class TopicService extends BaseLoggingClass {
                apiError.setCode(Status.OK.getStatusCode());
                return t;
        }
+       
+       private void aafTopicSetup(Topic topic, ApiError err ) {
+
+               String t = dmaapSvc.getTopicPerm();
+               if ( t == null ) {
+                       err.setCode(500);
+                       err.setMessage("Unable to establish AAF namespace root: (check /dmaap object)"  );
+                       err.setFields("topicNsRoot");
+                       return;
+               }
+
+               // establish AAF Connection using TopicMgr identity
+               AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
+               
+
+               
+               // create AAF namespace for this topic
+               AafNamespace ns = new AafNamespace( topic.getFqtn(), aaf.getIdentity());
+               {
+                       int rc = aaf.addNamespace( ns );
+                       if ( rc != 201 && rc != 409 ) {
+                               err.setCode(500);
+                               err.setMessage("Unexpected response from AAF:" + rc );
+                               err.setFields("namespace:" + topic.getFqtn() + " identity="+ aaf.getIdentity());
+                               return;
+                       }
+               }
+               
+               // create AAF Roles for MR clients of this topic
+               String rn = "publisher";
+               AafRole pubRole = new AafRole( topic.getFqtn(), rn );
+               int rc = aaf.addRole( pubRole );
+               if ( rc != 201 && rc != 409 ) {
+                       err.setCode(500);
+                       err.setMessage("Unexpected response from AAF:" + rc );
+                       err.setFields("topic:" + topic.getFqtn() + " role="+ rn);
+                       return;
+               }
+               topic.setPublisherRole( pubRole.getFullyQualifiedRole() );
+               
+               rn = "subscriber";
+               AafRole subRole = new AafRole( topic.getFqtn(), rn );
+               rc = aaf.addRole( subRole );
+               if ( rc != 201 && rc != 409 ) {
+                       err.setCode(500);
+                       err.setMessage("Unexpected response from AAF:" + rc );
+                       err.setFields("topic:" + topic.getFqtn() + " role="+ rn);
+                       return;
+               }
+               topic.setSubscriberRole( subRole.getFullyQualifiedRole() );
+       
+               
+               // create AAF perms checked by MR
+               String instance = ":topic." + topic.getFqtn();
+               String[] actions = { "pub", "sub", "view" };
+               for ( String action : actions ){
+                       DmaapPerm perm = new DmaapPerm( t, instance, action );
+                       rc = aaf.addPerm( perm );
+                       if ( rc != 201 && rc != 409 ) {
+                               err.setCode(500);
+                               err.setMessage("Unexpected response from AAF:" + rc );
+                               err.setFields("t="+t + " instance="+ instance + " action="+ action);
+                               return;
+                       }
+                       // Grant perms to our default Roles
+                       if ( action.equals( "pub") || action.equals( "view") ) {
+                               DmaapGrant g = new DmaapGrant( perm, pubRole.getFullyQualifiedRole() );
+                               rc = aaf.addGrant( g );
+                               if ( rc != 201 && rc != 409 ) {
+                                       err.setCode(rc);
+                                       err.setMessage( "Grant of " + perm.toString() + " failed for " + pubRole.getFullyQualifiedRole() );
+                                       logger.warn( err.getMessage());
+                                       return;
+                               } 
+                       }
+                       if ( action.equals( "sub") || action.equals( "view") ) {
+                               DmaapGrant g = new DmaapGrant( perm, subRole.getFullyQualifiedRole() );
+                               rc = aaf.addGrant( g );
+                               if ( rc != 201 && rc != 409 ) {
+                                       err.setCode(rc);
+                                       err.setMessage( "Grant of " + perm.toString() + " failed for " + subRole.getFullyQualifiedRole() );
+                                       logger.warn( err.getMessage());
+                                       return;
+                               } 
+                       }
+
+               }
+       }
 
        public Topic addTopic( Topic topic, ApiError err, Boolean useExisting ) {
                logger.info( "Entry: addTopic");
@@ -135,23 +225,11 @@ public class TopicService extends BaseLoggingClass {
 
                topic.setFqtn( nFqtn );
                
-               AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
-
-               String t = dmaapSvc.getTopicPerm();
-
-               String instance = ":topic." + topic.getFqtn();
+               aafTopicSetup( topic, err );
+               if ( err.getCode() >= 400 ) {
+                       return null;
+               }       
 
-               String[] actions = { "pub", "sub", "view" };
-               for ( String action : actions ){
-                       DmaapPerm perm = new DmaapPerm( t, instance, action );
-                       int rc = aaf.addPerm( perm );
-                       if ( rc != 201 && rc != 409 ) {
-                               err.setCode(500);
-                               err.setMessage("Unexpected response from AAF:" + rc );
-                               err.setFields("t="+t + " instance="+ instance + " action="+ action);
-                               return null;
-                       }
-               }
                if ( topic.getReplicationCase().involvesGlobal() ) {
                        if ( topic.getGlobalMrURL() == null ) {
                                topic.setGlobalMrURL(defaultGlobalMrHost);
@@ -179,6 +257,7 @@ public class TopicService extends BaseLoggingClass {
                                logger.info( "c fqtn=" + c.getFqtn() + " ID=" + c.getMrClientId() + " url=" + c.getTopicURL());
                                MR_Client nc = new MR_Client( c.getDcaeLocationName(), topic.getFqtn(), c.getClientRole(), c.getAction());
                                nc.setFqtn(topic.getFqtn());
+                               nc.setClientIdentity( c.getClientIdentity());
                                logger.info( "nc fqtn=" + nc.getFqtn() + " ID=" + nc.getMrClientId() + " url=" + nc.getTopicURL());
                                clients2.add( clientService.addMr_Client(nc, topic, err));
                                if ( ! err.is2xx()) {
index a7700a1..700c77f 100644 (file)
@@ -3,6 +3,8 @@
  * org.onap.dmaap
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.dmaap.dbcapi.util;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.onap.dmaap.dbcapi.database.DatabaseClass;
 import org.onap.dmaap.dbcapi.model.DcaeLocation;
 import org.onap.dmaap.dbcapi.model.MR_Client;
 import org.onap.dmaap.dbcapi.model.MR_Cluster;
 import org.onap.dmaap.dbcapi.service.MR_ClusterService;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 
 public class Graph {
        private HashMap<String, String> graph;
diff --git a/src/main/resources/schema_11.sql b/src/main/resources/schema_11.sql
new file mode 100644 (file)
index 0000000..3bf7b1f
--- /dev/null
@@ -0,0 +1,30 @@
+---
+-- ============LICENSE_START=======================================================
+-- OpenECOMP - org.onap.dbcapi
+-- ================================================================================
+-- Copyright (C) 2017 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=========================================================
+---
+
+
+@alter table topic
+       add column      publisher_role  varchar(100),
+       add column      subscriber_role varchar(100)
+;
+@alter table mr_client
+       add column      client_identity varchar(100)
+;
+
+update dmaapbc_sch_ver set version = 11 where version = 10;
index 48d1016..917507f 100644 (file)
@@ -21,6 +21,8 @@
 package org.onap.dmaap.dbcapi.resources;
 import org.onap.dmaap.dbcapi.model.*;
 import org.onap.dmaap.dbcapi.service.*;
+import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory;
+
 import static org.junit.Assert.*;
 
 import org.junit.After;
@@ -39,16 +41,44 @@ import javax.ws.rs.Path;
 import javax.ws.rs.GET;
 
 public class DR_SubResourceTest extends JerseyTest{
+       
+       static DmaapObjectFactory factory = new DmaapObjectFactory();
 
        @Override
        protected Application configure() {
                return new ResourceConfig()
                                .register( DR_SubResource.class )
-                               .register( FeedResource.class );
+                               .register( FeedResource.class )
+                               .register( DcaeLocationResource.class )
+                               .register( DmaapResource.class );
        }
 
-       private static final String  fmt = "%24s: %s%n";
        String d, un, up, f, p;
+       
+       @Before
+       public void preTest() throws Exception {
+               try {
+
+                       Dmaap dmaap = factory.genDmaap();
+                       Entity<Dmaap> reqEntity = Entity.entity( dmaap, MediaType.APPLICATION_JSON );
+                       Response resp = target( "dmaap").request().post( reqEntity, Response.class );
+                       System.out.println( resp.getStatus() );
+                       assertTrue( resp.getStatus() == 200 );
+               }catch (Exception e ) {
+               }
+               try {
+                       DcaeLocation loc = factory.genDcaeLocation( "central" );
+                       Entity<DcaeLocation> reqEntity = Entity.entity( loc, MediaType.APPLICATION_JSON );
+                       Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class );
+                       System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class ));
+                       if ( resp.getStatus() != 409 ) {
+                               assertTrue( resp.getStatus() == 201 );
+                       }
+               } catch (Exception e ) {
+               }
+       
+
+       }
 /*
        @Before
        public void setUp() throws Exception {
diff --git a/src/test/java/org/onap/dmaap/dbcapi/util/FqdnTest.java b/src/test/java/org/onap/dmaap/dbcapi/util/FqdnTest.java
new file mode 100644 (file)
index 0000000..7c7815f
--- /dev/null
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2019 IBM 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.dmaap.dbcapi.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class FqdnTest {
+
+    @Test
+    public void testIsValid() {
+        assertTrue(Fqdn.isValid("www.ibm.com"));
+        assertFalse(Fqdn.isValid("testuser@ibm.com"));
+    }
+}
\ No newline at end of file
index e09bb38..6623284 100644 (file)
@@ -27,7 +27,7 @@
 
 major=1
 minor=0
-patch=19
+patch=20
 base_version=${major}.${minor}.${patch}
 
 # Release must be completed with git revision # in Jenkins