API versioning supported and added different versions for POST APIs 06/132706/5
authorrajesh.kumar <rk00747546@techmahindra.com>
Wed, 14 Dec 2022 08:13:29 +0000 (08:13 +0000)
committerrajesh.kumar <rk00747546@techmahindra.com>
Fri, 16 Dec 2022 16:30:34 +0000 (16:30 +0000)
Issue-ID: CPS-1189
Change-ID: I73f97f986a817d423f92f8d922dcd9647b1214aa
Signed-off-by: rajesh.kumar <rk00747546@techmahindra.com>
13 files changed:
cps-rest/docs/openapi/components.yml
cps-rest/docs/openapi/cpsAdmin.yml
cps-rest/docs/openapi/cpsAdminV1Deprecated.yml [new file with mode: 0644]
cps-rest/docs/openapi/cpsAdminV2.yml [new file with mode: 0644]
cps-rest/docs/openapi/cpsData.yml
cps-rest/docs/openapi/cpsDataV1Deprecated.yml [new file with mode: 0644]
cps-rest/docs/openapi/cpsQuery.yml
cps-rest/docs/openapi/openapi.yml
cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java
cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
cps-rest/src/main/java/org/onap/cps/rest/controller/QueryRestController.java
cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy
docs/api/swagger/cps/openapi.yaml

index fb0947e..4f138fc 100644 (file)
@@ -211,6 +211,15 @@ components:
       schema:
         type: string
         example: '2021-03-21T00:10:34.030-0100'
+    apiVersionInPath:
+      name: apiVersion
+      in: path
+      description: apiVersion
+      required: true
+      schema:
+        type: string
+        enum: [v1, v2]
+        default: v2
 
   responses:
     NotFound:
@@ -279,6 +288,8 @@ components:
           schema:
             type: string
             example: my-resource
+    CreatedV2:
+      description: Created without response body
     InternalServerError:
       description: Internal Server Error
       content:
index 595f6d7..f60a9be 100644 (file)
 # ============LICENSE_END=========================================================
 
 dataspaces:
-  post:
-    description: Create a new dataspace
-    tags:
-      - cps-admin
-    summary: Create a dataspace
-    operationId: createDataspace
-    parameters:
-      - $ref: 'components.yml#/components/parameters/dataspaceNameInQuery'
-    responses:
-      '201':
-        $ref: 'components.yml#/components/responses/Created'
-      '400':
-        $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
-      '403':
-        $ref: 'components.yml#/components/responses/Forbidden'
-      '409':
-        $ref: 'components.yml#/components/responses/Conflict'
-      '500':
-        $ref: 'components.yml#/components/responses/InternalServerError'
   delete:
     description: Delete a dataspace
     tags:
@@ -47,6 +26,7 @@ dataspaces:
     summary: Delete a dataspace
     operationId: deleteDataspace
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInQuery'
     responses:
       '204':
@@ -63,34 +43,6 @@ dataspaces:
         $ref: 'components.yml#/components/responses/InternalServerError'
 
 schemaSet:
-  post:
-    description: Create a new schema set in the given dataspace
-    tags:
-      - cps-admin
-    summary: Create a schema set
-    operationId: createSchemaSet
-    parameters:
-      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
-      - $ref: 'components.yml#/components/parameters/schemaSetNameInQuery'
-    requestBody:
-      required: true
-      content:
-        multipart/form-data:
-          schema:
-            $ref: 'components.yml#/components/schemas/MultipartFile'
-    responses:
-      '201':
-        $ref: 'components.yml#/components/responses/Created'
-      '400':
-        $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
-      '403':
-        $ref: 'components.yml#/components/responses/Forbidden'
-      '409':
-        $ref: 'components.yml#/components/responses/Conflict'
-      '500':
-        $ref: 'components.yml#/components/responses/InternalServerError'
   get:
     description: Read all schema sets, given a dataspace
     tags:
@@ -98,6 +50,7 @@ schemaSet:
     summary: Get schema sets
     operationId: getSchemaSets
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
     responses:
       '200':
@@ -125,6 +78,7 @@ schemaSetBySchemaSetName:
     summary: Get a schema set
     operationId: getSchemaSet
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/schemaSetNameInPath'
     responses:
@@ -149,6 +103,7 @@ schemaSetBySchemaSetName:
     summary: Delete a schema set
     operationId: deleteSchemaSet
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/schemaSetNameInPath'
     responses:
@@ -173,6 +128,7 @@ anchorsByDataspace:
     summary: Get anchors
     operationId: getAnchors
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
     responses:
       '200':
@@ -191,29 +147,6 @@ anchorsByDataspace:
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
         $ref: 'components.yml#/components/responses/InternalServerError'
-  post:
-    description: Create a new anchor in the given dataspace
-    tags:
-      - cps-admin
-    summary: Create an anchor
-    operationId: createAnchor
-    parameters:
-      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
-      - $ref: 'components.yml#/components/parameters/schemaSetNameInQuery'
-      - $ref: 'components.yml#/components/parameters/anchorNameInQuery'
-    responses:
-      '201':
-        $ref: 'components.yml#/components/responses/Created'
-      '400':
-        $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
-      '403':
-        $ref: 'components.yml#/components/responses/Forbidden'
-      '409':
-        $ref: 'components.yml#/components/responses/Conflict'
-      '500':
-        $ref: 'components.yml#/components/responses/InternalServerError'
 
 anchorByDataspaceAndAnchorName:
   get:
@@ -223,6 +156,7 @@ anchorByDataspaceAndAnchorName:
     summary: Get an anchor
     operationId: getAnchor
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
     responses:
@@ -247,6 +181,7 @@ anchorByDataspaceAndAnchorName:
     summary: Delete an anchor
     operationId: deleteAnchor
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
     responses:
@@ -268,6 +203,8 @@ adminDataspaces:
      - cps-admin
    summary: Get all dataspaces
    operationId: getAllDataspaces
+   parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
    responses:
      '200':
        description: OK
@@ -294,6 +231,7 @@ adminDataspace:
    summary: Get a dataspace
    operationId: getDataspace
    parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
    responses:
      '200':
diff --git a/cps-rest/docs/openapi/cpsAdminV1Deprecated.yml b/cps-rest/docs/openapi/cpsAdminV1Deprecated.yml
new file mode 100644 (file)
index 0000000..56f7f1b
--- /dev/null
@@ -0,0 +1,98 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 TechMahindra Ltd.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+dataspaces:
+  post:
+    deprecated: true
+    description: Create a new dataspace
+    tags:
+      - cps-admin
+    summary: Create a dataspace
+    operationId: createDataspace
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInQuery'
+    responses:
+      '201':
+        $ref: 'components.yml#/components/responses/Created'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '409':
+        $ref: 'components.yml#/components/responses/Conflict'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
+
+anchorsByDataspace:
+  post:
+    deprecated: true
+    description: Create a new anchor in the given dataspace
+    tags:
+      - cps-admin
+    summary: Create an anchor
+    operationId: createAnchor
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
+      - $ref: 'components.yml#/components/parameters/schemaSetNameInQuery'
+      - $ref: 'components.yml#/components/parameters/anchorNameInQuery'
+    responses:
+      '201':
+        $ref: 'components.yml#/components/responses/Created'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '409':
+        $ref: 'components.yml#/components/responses/Conflict'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
+
+schemaSet:
+  post:
+    deprecated: true
+    description: Create a new schema set in the given dataspace
+    tags:
+      - cps-admin
+    summary: Create a schema set
+    operationId: createSchemaSet
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
+      - $ref: 'components.yml#/components/parameters/schemaSetNameInQuery'
+    requestBody:
+      required: true
+      content:
+        multipart/form-data:
+          schema:
+            $ref: 'components.yml#/components/schemas/MultipartFile'
+    responses:
+      '201':
+        $ref: 'components.yml#/components/responses/Created'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '409':
+        $ref: 'components.yml#/components/responses/Conflict'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
diff --git a/cps-rest/docs/openapi/cpsAdminV2.yml b/cps-rest/docs/openapi/cpsAdminV2.yml
new file mode 100644 (file)
index 0000000..14e2cfe
--- /dev/null
@@ -0,0 +1,95 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 TechMahindra Ltd.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+dataspaces:
+  post:
+    description: Create a new dataspace
+    tags:
+      - cps-admin
+    summary: Create a dataspace
+    operationId: createDataspaceV2
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInQuery'
+    responses:
+      '201':
+        $ref: 'components.yml#/components/responses/CreatedV2'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '409':
+        $ref: 'components.yml#/components/responses/Conflict'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
+
+anchorsByDataspace:
+  post:
+    description: Create a new anchor in the given dataspace
+    tags:
+      - cps-admin
+    summary: Create an anchor
+    operationId: createAnchorV2
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
+      - $ref: 'components.yml#/components/parameters/schemaSetNameInQuery'
+      - $ref: 'components.yml#/components/parameters/anchorNameInQuery'
+    responses:
+      '201':
+        $ref: 'components.yml#/components/responses/CreatedV2'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '409':
+        $ref: 'components.yml#/components/responses/Conflict'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
+
+schemaSet:
+  post:
+    description: Create a new schema set in the given dataspace
+    tags:
+      - cps-admin
+    summary: Create a schema set
+    operationId: createSchemaSetV2
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
+      - $ref: 'components.yml#/components/parameters/schemaSetNameInQuery'
+    requestBody:
+      required: true
+      content:
+        multipart/form-data:
+          schema:
+            $ref: 'components.yml#/components/schemas/MultipartFile'
+    responses:
+      '201':
+        $ref: 'components.yml#/components/responses/CreatedV2'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '409':
+        $ref: 'components.yml#/components/responses/Conflict'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
index 265ee23..9d940c3 100644 (file)
@@ -1,6 +1,7 @@
 # ============LICENSE_START=======================================================
 # Copyright (c) 2021-2022 Bell Canada.
 # Modifications Copyright (C) 2021-2022 Nordix Foundation
+# Modifications Copyright (C) 2022 TechMahindra Ltd.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -25,6 +26,7 @@ nodeByDataspaceAndAnchor:
     summary: Get a node
     operationId: getNodeByDataspaceAndAnchor
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/xpathInQuery'
@@ -57,6 +59,7 @@ listElementByDataspaceAndAnchor:
     summary: Add list element(s)
     operationId: addListElements
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/requiredXpathInQuery'
@@ -88,6 +91,7 @@ listElementByDataspaceAndAnchor:
     summary: Replace list content
     operationId: replaceListContent
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/requiredXpathInQuery'
@@ -112,29 +116,6 @@ listElementByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
         $ref: 'components.yml#/components/responses/InternalServerError'
-  delete:
-    description: Delete one or all list element(s) for a given anchor and dataspace
-    deprecated: true
-    tags:
-      - cps-data
-    summary: Delete one or all list element(s)
-    operationId: deleteListOrListElement
-    parameters:
-      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
-      - $ref: 'components.yml#/components/parameters/anchorNameInPath'
-      - $ref: 'components.yml#/components/parameters/requiredXpathInQuery'
-      - $ref: 'components.yml#/components/parameters/observedTimestampInQuery'
-    responses:
-      '204':
-        $ref: 'components.yml#/components/responses/NoContent'
-      '400':
-        $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
-      '403':
-        $ref: 'components.yml#/components/responses/Forbidden'
-      '500':
-        $ref: 'components.yml#/components/responses/InternalServerError'
 
 nodesByDataspaceAndAnchor:
   post:
@@ -144,6 +125,7 @@ nodesByDataspaceAndAnchor:
     summary: Create a node
     operationId: createNode
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/xpathInQuery'
@@ -177,6 +159,7 @@ nodesByDataspaceAndAnchor:
     summary: Update node leaves
     operationId: updateNodeLeaves
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/xpathInQuery'
@@ -208,6 +191,7 @@ nodesByDataspaceAndAnchor:
     summary: Delete a data node
     operationId: deleteDataNode
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/xpathInQuery'
@@ -230,6 +214,7 @@ nodesByDataspaceAndAnchor:
     summary: Replace a node with descendants
     operationId: replaceNode
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/xpathInQuery'
diff --git a/cps-rest/docs/openapi/cpsDataV1Deprecated.yml b/cps-rest/docs/openapi/cpsDataV1Deprecated.yml
new file mode 100644 (file)
index 0000000..194ca3e
--- /dev/null
@@ -0,0 +1,42 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 TechMahindra Ltd.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+listElementByDataspaceAndAnchor:
+  delete:
+    description: Delete one or all list element(s) for a given anchor and dataspace
+    deprecated: true
+    tags:
+      - cps-data
+    summary: Delete one or all list element(s)
+    operationId: deleteListOrListElement
+    parameters:
+      - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
+      - $ref: 'components.yml#/components/parameters/anchorNameInPath'
+      - $ref: 'components.yml#/components/parameters/requiredXpathInQuery'
+      - $ref: 'components.yml#/components/parameters/observedTimestampInQuery'
+    responses:
+      '204':
+        $ref: 'components.yml#/components/responses/NoContent'
+      '400':
+        $ref: 'components.yml#/components/responses/BadRequest'
+      '401':
+        $ref: 'components.yml#/components/responses/Unauthorized'
+      '403':
+        $ref: 'components.yml#/components/responses/Forbidden'
+      '500':
+        $ref: 'components.yml#/components/responses/InternalServerError'
index dc0402d..45fc70c 100644 (file)
@@ -1,6 +1,7 @@
 #  ============LICENSE_START=======================================================
 #  Copyright (C) 2021 Nordix Foundation
 #  Modifications Copyright (c) 2022 Bell Canada.
+#  Modifications Copyright (c) 2022 TechMahindra Ltd.
 #  ================================================================================
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -25,6 +26,7 @@ nodesByDataspaceAndAnchorAndCpsPath:
     summary: Query data nodes
     operationId: getNodesByDataspaceAndAnchorAndCpsPath
     parameters:
+      - $ref: 'components.yml#/components/parameters/apiVersionInPath'
       - $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
       - $ref: 'components.yml#/components/parameters/anchorNameInPath'
       - $ref: 'components.yml#/components/parameters/cpsPathInQuery'
index e02d6a6..0918b56 100644 (file)
@@ -51,36 +51,57 @@ tags:
 paths:
 
   /v1/dataspaces:
+    $ref: 'cpsAdminV1Deprecated.yml#/dataspaces'
+
+  /{apiVersion}/dataspaces:
     $ref: 'cpsAdmin.yml#/dataspaces'
 
-  /v1/admin/dataspaces:
+  /v2/dataspaces:
+    $ref: 'cpsAdminV2.yml#/dataspaces'
+
+  /{apiVersion}/admin/dataspaces:
     $ref: 'cpsAdmin.yml#/adminDataspaces'
 
-  /v1/admin/dataspaces/{dataspace-name}:
+  /{apiVersion}/admin/dataspaces/{dataspace-name}:
     $ref: 'cpsAdmin.yml#/adminDataspace'
 
   /v1/dataspaces/{dataspace-name}/anchors:
+    $ref: 'cpsAdminV1Deprecated.yml#/anchorsByDataspace'
+
+  /v2/dataspaces/{dataspace-name}/anchors:
+    $ref: 'cpsAdminV2.yml#/anchorsByDataspace'
+
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors:
     $ref: 'cpsAdmin.yml#/anchorsByDataspace'
 
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}:
     $ref: 'cpsAdmin.yml#/anchorByDataspaceAndAnchorName'
 
   /v1/dataspaces/{dataspace-name}/schema-sets:
+    $ref: 'cpsAdminV1Deprecated.yml#/schemaSet'
+
+  /v2/dataspaces/{dataspace-name}/schema-sets:
+    $ref: 'cpsAdminV2.yml#/schemaSet'
+
+  /{apiVersion}/dataspaces/{dataspace-name}/schema-sets:
     $ref: 'cpsAdmin.yml#/schemaSet'
 
-  /v1/dataspaces/{dataspace-name}/schema-sets/{schema-set-name}:
+  /{apiVersion}/dataspaces/{dataspace-name}/schema-sets/{schema-set-name}:
     $ref: 'cpsAdmin.yml#/schemaSetBySchemaSetName'
 
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/node:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/node:
     $ref: 'cpsData.yml#/nodeByDataspaceAndAnchor'
 
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes:
     $ref: 'cpsData.yml#/nodesByDataspaceAndAnchor'
 
   /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/list-nodes:
+    $ref: 'cpsDataV1Deprecated.yml#/listElementByDataspaceAndAnchor'
+
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/list-nodes:
     $ref: 'cpsData.yml#/listElementByDataspaceAndAnchor'
 
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes/query:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes/query:
     $ref: 'cpsQuery.yml#/nodesByDataspaceAndAnchorAndCpsPath'
 
 security:
index 285a15c..b8ba089 100755 (executable)
@@ -68,6 +68,18 @@ public class AdminRestController implements CpsAdminApi {
         return new ResponseEntity<>(dataspaceName, HttpStatus.CREATED);
     }
 
+    /**
+     * Create a dataspace without returning any response body.
+     *
+     * @param dataspaceName dataspace name
+     * @return a {@Link ResponseEntity} of created dataspace name & {@link HttpStatus} CREATED
+     */
+    @Override
+    public ResponseEntity<Void> createDataspaceV2(@NotNull @Valid final String dataspaceName) {
+        cpsAdminService.createDataspace(dataspaceName);
+        return new ResponseEntity<>(HttpStatus.CREATED);
+    }
+
     /**
      * Delete a dataspace.
      *
@@ -75,7 +87,7 @@ public class AdminRestController implements CpsAdminApi {
      * @return a {@Link ResponseEntity} of {@link HttpStatus} NO_CONTENT
      */
     @Override
-    public ResponseEntity<Void> deleteDataspace(final String dataspaceName) {
+    public ResponseEntity<Void> deleteDataspace(final String apiVersion, final String dataspaceName) {
         cpsAdminService.deleteDataspace(dataspaceName);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
@@ -95,15 +107,32 @@ public class AdminRestController implements CpsAdminApi {
         return new ResponseEntity<>(schemaSetName, HttpStatus.CREATED);
     }
 
+    /**
+     * Create a {@link SchemaSet}.
+     *
+     * @param multipartFile multipart file
+     * @param schemaSetName schemaset name
+     * @param dataspaceName dataspace name
+     * @return a {@Link ResponseEntity} of created schema set without any response body & {@link HttpStatus} CREATED
+     */
+    @Override
+    public ResponseEntity<Void> createSchemaSetV2(@NotNull @Valid final String schemaSetName,
+        final String dataspaceName, @Valid final MultipartFile multipartFile) {
+        cpsModuleService.createSchemaSet(dataspaceName, schemaSetName, extractYangResourcesMap(multipartFile));
+        return new ResponseEntity<>(HttpStatus.CREATED);
+    }
+
     /**
      * Get {@link SchemaSetDetails} based on dataspace name & {@link SchemaSet} name.
      *
+     * @param apiVersion api version
      * @param dataspaceName dataspace name
      * @param schemaSetName schemaset name
      * @return a {@Link ResponseEntity} of {@Link SchemaSetDetails} & {@link HttpStatus} OK
      */
     @Override
-    public ResponseEntity<SchemaSetDetails> getSchemaSet(final String dataspaceName, final String schemaSetName) {
+    public ResponseEntity<SchemaSetDetails> getSchemaSet(final String apiVersion,
+            final String dataspaceName, final String schemaSetName) {
         final var schemaSet = cpsModuleService.getSchemaSet(dataspaceName, schemaSetName);
         final var schemaSetDetails = cpsRestInputMapper.toSchemaSetDetails(schemaSet);
         return new ResponseEntity<>(schemaSetDetails, HttpStatus.OK);
@@ -112,11 +141,12 @@ public class AdminRestController implements CpsAdminApi {
     /**
      * Get list of schema sets for a given dataspace name.
      *
+     * @param apiVersion api version
      * @param dataspaceName dataspace name
      * @return a {@Link ResponseEntity} of schema sets & {@link HttpStatus} OK
      */
     @Override
-    public ResponseEntity<List<SchemaSetDetails>> getSchemaSets(final String dataspaceName) {
+    public ResponseEntity<List<SchemaSetDetails>> getSchemaSets(final String apiVersion, final String dataspaceName) {
         final Collection<SchemaSet> schemaSets = cpsModuleService.getSchemaSets(dataspaceName);
         final List<SchemaSetDetails> schemaSetDetails = schemaSets.stream().map(cpsRestInputMapper::toSchemaSetDetails)
                 .collect(Collectors.toList());
@@ -126,12 +156,14 @@ public class AdminRestController implements CpsAdminApi {
     /**
      * Delete a {@link SchemaSet} based on given dataspace name & schemaset name.
      *
+     * @param apiVersion api version
      * @param dataspaceName dataspace name
      * @param schemaSetName schemaset name
      * @return a {@Link ResponseEntity} of {@link HttpStatus} NO_CONTENT
      */
     @Override
-    public ResponseEntity<Void> deleteSchemaSet(final String dataspaceName, final String schemaSetName) {
+    public ResponseEntity<Void> deleteSchemaSet(final String apiVersion,
+            final String dataspaceName, final String schemaSetName) {
         cpsModuleService.deleteSchemaSet(dataspaceName, schemaSetName, CASCADE_DELETE_PROHIBITED);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
@@ -151,15 +183,32 @@ public class AdminRestController implements CpsAdminApi {
         return new ResponseEntity<>(anchorName, HttpStatus.CREATED);
     }
 
+    /**
+     * Create an anchor.
+     *
+     * @param dataspaceName dataspace name
+     * @param schemaSetName schema set name
+     * @param anchorName    anchorName
+     * @return a ResponseEntity without response body & {@link HttpStatus} CREATED
+     */
+    @Override
+    public ResponseEntity<Void> createAnchorV2(final String dataspaceName, @NotNull @Valid final String schemaSetName,
+        @NotNull @Valid final String anchorName) {
+        cpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName);
+        return new ResponseEntity<>(HttpStatus.CREATED);
+    }
+
     /**
      * Delete an {@link Anchor} based on given dataspace name & anchor name.
      *
+     * @param apiVersion api version
      * @param dataspaceName dataspace name
      * @param anchorName anchor name
      * @return a {@Link ResponseEntity} of {@link HttpStatus} NO_CONTENT
      */
     @Override
-    public ResponseEntity<Void> deleteAnchor(final String dataspaceName, final String anchorName) {
+    public ResponseEntity<Void> deleteAnchor(final String apiVersion,
+            final String dataspaceName, final String anchorName) {
         cpsAdminService.deleteAnchor(dataspaceName, anchorName);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
@@ -167,12 +216,14 @@ public class AdminRestController implements CpsAdminApi {
     /**
      * Get an {@link Anchor} based on given dataspace name & anchor name.
      *
+     * @param apiVersion api version
      * @param dataspaceName dataspace name
      * @param anchorName anchor name
      * @return a {@Link ResponseEntity} of an {@Link AnchorDetails} & {@link HttpStatus} OK
      */
     @Override
-    public ResponseEntity<AnchorDetails> getAnchor(final String dataspaceName, final String anchorName) {
+    public ResponseEntity<AnchorDetails> getAnchor(final String apiVersion,
+            final String dataspaceName, final String anchorName) {
         final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
         final var anchorDetails = cpsRestInputMapper.toAnchorDetails(anchor);
         return new ResponseEntity<>(anchorDetails, HttpStatus.OK);
@@ -181,11 +232,13 @@ public class AdminRestController implements CpsAdminApi {
     /**
      *  Get all {@link Anchor} based on given dataspace name.
      *
+     * @param apiVersion api version
      * @param dataspaceName dataspace name
      * @return a {@Link ResponseEntity} of all {@Link AnchorDetails} & {@link HttpStatus} OK
      */
     @Override
-    public ResponseEntity<List<AnchorDetails>> getAnchors(final String dataspaceName) {
+    public ResponseEntity<List<AnchorDetails>> getAnchors(final String apiVersion,
+            final String dataspaceName) {
         final Collection<Anchor> anchors = cpsAdminService.getAnchors(dataspaceName);
         final List<AnchorDetails> anchorDetails = anchors.stream().map(cpsRestInputMapper::toAnchorDetails)
             .collect(Collectors.toList());
@@ -193,7 +246,7 @@ public class AdminRestController implements CpsAdminApi {
     }
 
     @Override
-    public ResponseEntity<List<DataspaceDetails>> getAllDataspaces() {
+    public ResponseEntity<List<DataspaceDetails>> getAllDataspaces(final String apiVersion) {
         final Collection<Dataspace> dataspaces = cpsAdminService.getAllDataspaces();
         final List<DataspaceDetails> dataspaceDetails = dataspaces.stream().map(cpsRestInputMapper::toDataspaceDetails)
                 .collect(Collectors.toList());
@@ -201,7 +254,7 @@ public class AdminRestController implements CpsAdminApi {
     }
 
     @Override
-    public ResponseEntity<DataspaceDetails> getDataspace(final String dataspaceName) {
+    public ResponseEntity<DataspaceDetails> getDataspace(final String apiVersion, final String dataspaceName) {
         final Dataspace dataspace = cpsAdminService.getDataspace(dataspaceName);
         final DataspaceDetails dataspaceDetails = cpsRestInputMapper.toDataspaceDetails(dataspace);
         return new ResponseEntity<>(dataspaceDetails, HttpStatus.OK);
index fdce9be..c7d44b6 100755 (executable)
@@ -3,6 +3,7 @@
  *  Copyright (C) 2020-2022 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021-2022 Nordix Foundation
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -53,7 +54,8 @@ public class DataRestController implements CpsDataApi {
     private final PrefixResolver prefixResolver;
 
     @Override
-    public ResponseEntity<String> createNode(final String dataspaceName, final String anchorName,
+    public ResponseEntity<String> createNode(final String apiVersion,
+        final String dataspaceName, final String anchorName,
         final Object jsonData, final String parentNodeXpath, final String observedTimestamp) {
         final String jsonDataAsString = jsonObjectMapper.asJsonString(jsonData);
         if (isRootXpath(parentNodeXpath)) {
@@ -67,7 +69,8 @@ public class DataRestController implements CpsDataApi {
     }
 
     @Override
-    public ResponseEntity<Void> deleteDataNode(final String dataspaceName, final String anchorName,
+    public ResponseEntity<Void> deleteDataNode(final String apiVersion,
+        final String dataspaceName, final String anchorName,
         final String xpath, final String observedTimestamp) {
         cpsDataService.deleteDataNode(dataspaceName, anchorName, xpath,
             toOffsetDateTime(observedTimestamp));
@@ -75,7 +78,7 @@ public class DataRestController implements CpsDataApi {
     }
 
     @Override
-    public ResponseEntity<String> addListElements(final String parentNodeXpath,
+    public ResponseEntity<String> addListElements(final String parentNodeXpath, final String apiVersion,
         final String dataspaceName, final String anchorName, final Object jsonData, final String observedTimestamp) {
         cpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath,
                 jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
@@ -83,8 +86,8 @@ public class DataRestController implements CpsDataApi {
     }
 
     @Override
-    public ResponseEntity<Object> getNodeByDataspaceAndAnchor(final String dataspaceName, final String anchorName,
-        final String xpath, final Boolean includeDescendants) {
+    public ResponseEntity<Object> getNodeByDataspaceAndAnchor(final String apiVersion,
+        final String dataspaceName, final String anchorName, final String xpath, final Boolean includeDescendants) {
         final FetchDescendantsOption fetchDescendantsOption = Boolean.TRUE.equals(includeDescendants)
             ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS : FetchDescendantsOption.OMIT_DESCENDANTS;
         final DataNode dataNode = cpsDataService.getDataNode(dataspaceName, anchorName, xpath,
@@ -94,7 +97,7 @@ public class DataRestController implements CpsDataApi {
     }
 
     @Override
-    public ResponseEntity<Object> updateNodeLeaves(final String dataspaceName,
+    public ResponseEntity<Object> updateNodeLeaves(final String apiVersion, final String dataspaceName,
         final String anchorName, final Object jsonData, final String parentNodeXpath, final String observedTimestamp) {
         cpsDataService.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath,
                 jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
@@ -102,7 +105,8 @@ public class DataRestController implements CpsDataApi {
     }
 
     @Override
-    public ResponseEntity<Object> replaceNode(final String dataspaceName, final String anchorName,
+    public ResponseEntity<Object> replaceNode(final String apiVersion,
+        final String dataspaceName, final String anchorName,
         final Object jsonData, final String parentNodeXpath, final String observedTimestamp) {
         cpsDataService
                 .updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath,
@@ -112,7 +116,7 @@ public class DataRestController implements CpsDataApi {
 
     @Override
     public ResponseEntity<Object> replaceListContent(final String parentNodeXpath,
-        final String dataspaceName, final String anchorName, final Object jsonData,
+        final String apiVersion, final String dataspaceName, final String anchorName, final Object jsonData,
         final String observedTimestamp) {
         cpsDataService.replaceListContent(dataspaceName, anchorName, parentNodeXpath,
                 jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
index 577ad9c..3e162ae 100644 (file)
@@ -2,6 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021-2022 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada.
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -48,8 +49,8 @@ public class QueryRestController implements CpsQueryApi {
     private final PrefixResolver prefixResolver;
 
     @Override
-    public ResponseEntity<Object> getNodesByDataspaceAndAnchorAndCpsPath(final String dataspaceName,
-        final String anchorName, final String cpsPath, final Boolean includeDescendants) {
+    public ResponseEntity<Object> getNodesByDataspaceAndAnchorAndCpsPath(final String apiVersion,
+        final String dataspaceName, final String anchorName, final String cpsPath, final Boolean includeDescendants) {
         final FetchDescendantsOption fetchDescendantsOption = Boolean.TRUE.equals(includeDescendants)
             ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS : FetchDescendantsOption.OMIT_DESCENDANTS;
         final Collection<DataNode> dataNodes =
index 7120ce4..f81efd6 100755 (executable)
@@ -73,21 +73,23 @@ class AdminRestControllerSpec extends Specification {
     def anchor = new Anchor(name: anchorName, dataspaceName: dataspaceName, schemaSetName: schemaSetName)
     def dataspace = new Dataspace(name: dataspaceName)
 
-    def 'Create new dataspace.'() {
-        given: 'an endpoint'
-            def createDataspaceEndpoint = "$basePath/v1/dataspaces"
+    def 'Create new dataspace with #scenario.'() {
         when: 'post is invoked'
             def response =
                     mvc.perform(
-                            post(createDataspaceEndpoint)
+                            post("/cps/api/${apiVersion}/dataspaces")
                                     .param('dataspace-name', dataspaceName))
                             .andReturn().response
         then: 'service method is invoked with expected parameters'
             1 * mockCpsAdminService.createDataspace(dataspaceName)
         and: 'dataspace is create successfully'
             response.status == HttpStatus.CREATED.value()
-    }
-
+            assert response.getContentAsString() == expectedResponseBody
+        where: 'following cases are tested'
+            scenario | apiVersion  || expectedResponseBody
+            'V1 API' | 'v1'        || 'my_dataspace'
+            'V2 API' | 'v2'        || ''
+    } 
     def 'Create dataspace over existing with same name.'() {
         given: 'an endpoint'
             def createDataspaceEndpoint = "$basePath/v1/dataspaces"
@@ -129,16 +131,14 @@ class AdminRestControllerSpec extends Specification {
             response.getContentAsString().contains("dataspace-test2")
     }
 
-    def 'Create schema set from yang file.'() {
+    def 'Create schema set from yang file with #scenario.'() {
         def yangResourceMapCapture
         given: 'single yang file'
             def multipartFile = createMultipartFile("filename.yang", "content")
-        and: 'an endpoint'
-            def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets"
         when: 'file uploaded with schema set create request'
             def response =
                     mvc.perform(
-                            multipart(schemaSetEndpoint)
+                            multipart("/cps/api/${apiVersion}/dataspaces/my_dataspace/schema-sets")
                                     .file(multipartFile)
                                     .param('schema-set-name', schemaSetName))
                             .andReturn().response
@@ -147,19 +147,22 @@ class AdminRestControllerSpec extends Specification {
                     { args -> yangResourceMapCapture = args[2] }
             yangResourceMapCapture['filename.yang'] == 'content'
         and: 'response code indicates success'
-            response.status == HttpStatus.CREATED.value()
+            assert response.status == HttpStatus.CREATED.value()
+            assert response.getContentAsString() == expectedResponseBody
+        where: 'following cases are tested'
+            scenario | apiVersion || expectedResponseBody
+            'V1 API' | 'v1'       || 'my_schema_set'
+            'V2 API' | 'v2'       || ''
     }
 
-    def 'Create schema set from zip archive.'() {
+    def 'Create schema set from zip archive with #scenario.'() {
         def yangResourceMapCapture
         given: 'zip archive with multiple .yang files inside'
             def multipartFile = createZipMultipartFileFromResource("/yang-files-set.zip")
-        and: 'an endpoint'
-            def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets"
         when: 'file uploaded with schema set create request'
             def response =
                     mvc.perform(
-                            multipart(schemaSetEndpoint)
+                            multipart("/cps/api/${apiVersion}/dataspaces/my_dataspace/schema-sets")
                                     .file(multipartFile)
                                     .param('schema-set-name', schemaSetName))
                             .andReturn().response
@@ -169,25 +172,33 @@ class AdminRestControllerSpec extends Specification {
             yangResourceMapCapture['assembly.yang'] == "fake assembly content 1\n"
             yangResourceMapCapture['component.yang'] == "fake component content 1\n"
         and: 'response code indicates success'
-            response.status == HttpStatus.CREATED.value()
+            assert response.status == HttpStatus.CREATED.value()
+            assert response.getContentAsString() == expectedResponseBody
+        where: 'following cases are tested'
+            scenario | apiVersion || expectedResponseBody
+            'V1 API' | 'v1'       || 'my_schema_set'
+            'V2 API' | 'v2'       || ''
     }
 
-    def 'Create a schema set from a yang file that is greater than 1MB.'() {
+    def 'Create a schema set from a yang file that is greater than 1MB #scenario.'() {
         given: 'a yang file greater than 1MB'
             def multipartFile = createMultipartFileFromResource("/model-over-1mb.yang")
-        and: 'an endpoint'
-            def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets"
         when: 'a file is uploaded to the create schema set endpoint'
             def response =
                     mvc.perform(
-                            multipart(schemaSetEndpoint)
+                            multipart("/cps/api/${apiVersion}/dataspaces/my_dataspace/schema-sets")
                                     .file(multipartFile)
                                     .param('schema-set-name', schemaSetName))
                             .andReturn().response
         then: 'the associated service method is invoked'
             1 * mockCpsModuleService.createSchemaSet(dataspaceName, schemaSetName, _)
         and: 'the response code indicates success'
-            response.status == HttpStatus.CREATED.value()
+            assert response.status == HttpStatus.CREATED.value()
+            assert response.getContentAsString() == expectedResponseBody
+        where: 'following cases are tested'
+            scenario | apiVersion || expectedResponseBody
+            'V1 API' | 'v1'       || 'my_schema_set'
+            'V2 API' | 'v2'       || ''
     }
 
     def 'Create schema set from zip archive having #caseDescriptor.'() {
@@ -293,23 +304,26 @@ class AdminRestControllerSpec extends Specification {
                    '"my_schema_set"},{"dataspaceName":"my_dataspace","moduleReferences":[],"name":"test-schemaset"}]'
     }
 
-    def 'Create Anchor.'() {
+    def 'Create Anchor with #scenario.'() {
         given: 'request parameters'
             def requestParams = new LinkedMultiValueMap<>()
             requestParams.add('schema-set-name', schemaSetName)
             requestParams.add('anchor-name', anchorName)
-        and: 'an endpoint'
-            def anchorEndpoint = "$basePath/v1/dataspaces/$dataspaceName/anchors"
         when: 'post is invoked'
             def response =
                     mvc.perform(
-                            post(anchorEndpoint).contentType(MediaType.APPLICATION_JSON)
+                            post("/cps/api/${apiVersion}/dataspaces/my_dataspace/anchors")
+                                    .contentType(MediaType.APPLICATION_JSON)
                                     .params(requestParams as MultiValueMap))
-                            .andReturn().response
+                                    .andReturn().response
         then: 'anchor is created successfully'
             1 * mockCpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName)
-            response.status == HttpStatus.CREATED.value()
-            response.getContentAsString().contains(anchorName)
+            assert response.status == HttpStatus.CREATED.value()
+            assert response.getContentAsString() == expectedResponseBody
+        where: 'following cases are tested'
+            scenario | apiVersion || expectedResponseBody
+            'V1 API' | 'v1'       || 'my_anchor'
+            'V2 API' | 'v2'       || ''
     }
 
     def 'Get existing anchor.'() {
index 09ccbe1..ec7d295 100644 (file)
@@ -29,6 +29,7 @@ paths:
       summary: Create a dataspace
       description: Create a new dataspace
       operationId: createDataspace
+      deprecated: true
       parameters:
       - name: dataspace-name
         in: query
@@ -95,6 +96,75 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
+  /v2/dataspaces:
+    post:
+      tags:
+      - cps-admin
+      summary: Create a dataspace
+      description: Create a new dataspace
+      operationId: createDataspaceV2
+      parameters:
+      - name: dataspace-name
+        in: query
+        description: dataspace-name
+        required: true
+        schema:
+          type: string
+          example: my-dataspace
+      responses:
+        "201":
+          description: Created
+        "400":
+          description: Bad Request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 400
+                message: Bad Request
+                details: The provided request is not valid
+        "401":
+          description: Unauthorized
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 401
+                message: Unauthorized request
+                details: This request is unauthorized
+        "403":
+          description: Forbidden
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 403
+                message: Request Forbidden
+                details: This request is forbidden
+        "409":
+          description: Conflict
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 409
+                message: Conflicting request
+                details: The request cannot be processed as the resource is in use.
+        "500":
+          description: Internal Server Error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 500
+                message: Internal Server Error
+                details: Internal Server Error occurred
+  /{apiVersion}/dataspaces:
     delete:
       tags:
       - cps-admin
@@ -102,6 +172,7 @@ paths:
       description: Delete a dataspace
       operationId: deleteDataspace
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: query
         description: dataspace-name
@@ -163,13 +234,15 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
-  /v1/admin/dataspaces:
+  /{apiVersion}/admin/dataspaces:
     get:
       tags:
       - cps-admin
       summary: Get dataspaces
       description: "Read all dataspaces"
       operationId: getAllDataspaces
+      parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       responses:
         "200":
           description: OK
@@ -219,7 +292,7 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
-  /v1/admin/dataspaces/{dataspace-name}:
+  /{apiVersion}/admin/dataspaces/{dataspace-name}:
     get:
       tags:
       - cps-admin
@@ -227,6 +300,7 @@ paths:
       description: Read an dataspace given a dataspace name
       operationId: getDataspace
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -281,7 +355,7 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
-  /v1/dataspaces/{dataspace-name}/anchors:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors:
     get:
       tags:
       - cps-admin
@@ -289,6 +363,7 @@ paths:
       description: "Read all anchors, given a dataspace"
       operationId: getAnchors
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -345,10 +420,12 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
+  /v1/dataspaces/{dataspace-name}/anchors:
     post:
       tags:
       - cps-admin
       summary: Create an anchor
+      deprecated: true
       description: Create a new anchor in the given dataspace
       operationId: createAnchor
       parameters:
@@ -431,7 +508,89 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}:
+  /v2/dataspaces/{dataspace-name}/anchors:
+    post:
+      tags:
+      - cps-admin
+      summary: Create an anchor
+      description: Create a new anchor in the given dataspace
+      operationId: createAnchorV2
+      parameters:
+      - name: dataspace-name
+        in: path
+        description: dataspace-name
+        required: true
+        schema:
+          type: string
+          example: my-dataspace
+      - name: schema-set-name
+        in: query
+        description: schema-set-name
+        required: true
+        schema:
+          type: string
+          example: my-schema-set
+      - name: anchor-name
+        in: query
+        description: anchor-name
+        required: true
+        schema:
+          type: string
+          example: my-anchor
+      responses:
+        "201":
+          description: Created
+        "400":
+          description: Bad Request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 400
+                message: Bad Request
+                details: The provided request is not valid
+        "401":
+          description: Unauthorized
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 401
+                message: Unauthorized request
+                details: This request is unauthorized
+        "403":
+          description: Forbidden
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 403
+                message: Request Forbidden
+                details: This request is forbidden
+        "409":
+          description: Conflict
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 409
+                message: Conflicting request
+                details: The request cannot be processed as the resource is in use.
+        "500":
+          description: Internal Server Error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 500
+                message: Internal Server Error
+                details: Internal Server Error occurred
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}:
     get:
       tags:
       - cps-admin
@@ -439,6 +598,7 @@ paths:
       description: Read an anchor given an anchor name and a dataspace
       operationId: getAnchor
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -507,6 +667,7 @@ paths:
       description: Delete an anchor given an anchor name and a dataspace
       operationId: deleteAnchor
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -651,6 +812,88 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
+  /v2/dataspaces/{dataspace-name}/schema-sets:
+    post:
+      tags:
+      - cps-admin
+      summary: Create a schema set
+      description: Create a new schema set in the given dataspace
+      operationId: createSchemaSetV2
+      parameters:
+      - name: dataspace-name
+        in: path
+        description: dataspace-name
+        required: true
+        schema:
+          type: string
+          example: my-dataspace
+      - name: schema-set-name
+        in: query
+        description: schema-set-name
+        required: true
+        schema:
+          type: string
+          example: my-schema-set
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              $ref: '#/components/schemas/MultipartFile'
+        required: true
+      responses:
+        "201":
+          description: Created
+        "400":
+          description: Bad Request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 400
+                message: Bad Request
+                details: The provided request is not valid
+        "401":
+          description: Unauthorized
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 401
+                message: Unauthorized request
+                details: This request is unauthorized
+        "403":
+          description: Forbidden
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 403
+                message: Request Forbidden
+                details: This request is forbidden
+        "409":
+          description: Conflict
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 409
+                message: Conflicting request
+                details: The request cannot be processed as the resource is in use.
+        "500":
+          description: Internal Server Error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+              example:
+                status: 500
+                message: Internal Server Error
+                details: Internal Server Error occurred
+  /{apiVersion}/dataspaces/{dataspace-name}/schema-sets:
     get:
       tags:
       - cps-admin
@@ -658,13 +901,14 @@ paths:
       description: "Read schema sets for a given dataspace"
       operationId: getSchemaSets
       parameters:
-        - name: dataspace-name
-          in: path
-          description: dataspace-name
-          required: true
-          schema:
-            type: string
-            example: my-dataspace
+      - $ref: '#/components/parameters/apiVersionInPath'
+      - name: dataspace-name
+        in: path
+        description: dataspace-name
+        required: true
+        schema:
+          type: string
+          example: my-dataspace
       responses:
         "200":
           description: OK
@@ -714,7 +958,7 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
-  /v1/dataspaces/{dataspace-name}/schema-sets/{schema-set-name}:
+  /{apiVersion}/dataspaces/{dataspace-name}/schema-sets/{schema-set-name}:
     get:
       tags:
       - cps-admin
@@ -722,6 +966,7 @@ paths:
       description: Read a schema set given a schema set name and a dataspace
       operationId: getSchemaSet
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -790,6 +1035,7 @@ paths:
       description: Delete a schema set given a schema set name and a dataspace
       operationId: deleteSchemaSet
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -858,7 +1104,7 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/node:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/node:
     get:
       tags:
       - cps-data
@@ -867,6 +1113,7 @@ paths:
         anchor and dataspace
       operationId: getNodeByDataspaceAndAnchor
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -952,7 +1199,7 @@ paths:
                 message: Internal Server Error
                 details: Internal Server Error occurred
       x-codegen-request-body-name: xpath
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes:
     put:
       tags:
       - cps-data
@@ -961,6 +1208,7 @@ paths:
         \ and a parent node xpath"
       operationId: replaceNode
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1060,6 +1308,7 @@ paths:
       description: Create a node for a given anchor and dataspace
       operationId: createNode
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1168,6 +1417,7 @@ paths:
         xpath.
       operationId: deleteDataNode
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1253,6 +1503,7 @@ paths:
         a parent node xpath
       operationId: updateNodeLeaves
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1345,7 +1596,7 @@ paths:
                 status: 500
                 message: Internal Server Error
                 details: Internal Server Error occurred
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/list-nodes:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/list-nodes:
     put:
       tags:
       - cps-data
@@ -1353,6 +1604,7 @@ paths:
       description: "Replace list content under a given parent, anchor and dataspace"
       operationId: replaceListContent
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1451,6 +1703,7 @@ paths:
       description: Add list element(s) to a list for a given anchor and dataspace
       operationId: addListElements
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1547,6 +1800,7 @@ paths:
       description: Delete one or all list element(s) for a given anchor and dataspace
       operationId: deleteListOrListElement
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1624,7 +1878,7 @@ paths:
                 message: Internal Server Error
                 details: Internal Server Error occurred
       deprecated: true
-  /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes/query:
+  /{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes/query:
     get:
       tags:
       - cps-query
@@ -1632,6 +1886,7 @@ paths:
       description: Query data nodes for the given dataspace and anchor using CPS path
       operationId: getNodesByDataspaceAndAnchorAndCpsPath
       parameters:
+      - $ref: '#/components/parameters/apiVersionInPath'
       - name: dataspace-name
         in: path
         description: dataspace-name
@@ -1718,6 +1973,16 @@ paths:
                 details: Internal Server Error occurred
       x-codegen-request-body-name: xpath
 components:
+  parameters:
+    apiVersionInPath:
+      name: apiVersion
+      in: path
+      description: apiVersion
+      required: true
+      schema:
+        type: string
+        enum: [v1, v2]
+        default: v2
   securitySchemes:
     basicAuth:
       type: http