Update the aai-resources to verify bulk limits 95/25495/1
authorMaharajh, Robby (rx2202) <rx2202@us.att.com>
Mon, 4 Dec 2017 21:43:59 +0000 (16:43 -0500)
committerMaharajh, Robby (rx2202) <rx2202@us.att.com>
Mon, 4 Dec 2017 21:44:06 +0000 (16:44 -0500)
Issue-ID: AAI-529
Change-Id: Ia87e3298ce9c46f3b409587df6e9bd6e2065ec8a
Signed-off-by: Maharajh, Robby (rx2202) <rx2202@us.att.com>
aai-resources/bundleconfig-local/etc/appprops/aaiconfig.properties
aai-resources/bundleconfig-local/etc/appprops/error.properties
aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java
aai-resources/src/test/java/org/onap/aai/rest/BulkAddConsumerTest.java
aai-resources/src/test/java/org/onap/aai/rest/BulkProcessConsumerTest.java
aai-resources/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties
aai-resources/src/test/resources/bundleconfig-local/etc/appprops/error.properties
aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-exceed.json [new file with mode: 0644]
aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-meet.json [new file with mode: 0644]

index 98d4c57..27a744c 100644 (file)
@@ -147,3 +147,7 @@ aai.server.rebind=g
 # This is a fake one just for test so please ignore
 ecm.auth.password.x=OBF:1igd1i9a1jnb1yte1vv11vu91yt81jk71i6o1idt
 aai.run.migrations=false
+aai.jms.enable=false
+
+#limit set for bulk consumer APIS
+aai.bulkconsumer.payloadlimit=30
index 9ad86ec..a20dce5 100644 (file)
@@ -114,6 +114,7 @@ AAI_6143=5:4:INFO:6143:400:3000:Ghost vertex found
 AAI_6144=5:4:WARN:6144:400:3000:Cycle found in graph
 AAI_6145=5:4:ERROR:6145:400:3000:Cannot create a nested/containment edge via relationship
 AAI_6146=5:4:ERROR:6146:400:3000:Ambiguous identity map found, use a URI instead
+AAI_6147=5:4:ERROR:6147:400:3000:Payload Limit Reached, reduce payload
 
 #--- aaicsvp: 7101-7199
 AAI_7101=5:4:ERROR:7101:500:3002:Unexpected error in CSV file processing
index 5591ae3..5ff0e35 100644 (file)
@@ -24,8 +24,11 @@ package org.onap.aai.rest;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import javax.servlet.http.HttpServletRequest;
@@ -60,6 +63,8 @@ import org.onap.aai.restcore.HttpMethod;
 import org.onap.aai.restcore.RESTAPI;
 import org.onap.aai.serialization.engines.QueryStyle;
 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
+import org.onap.aai.util.AAIConfig;
+import org.onap.aai.util.AAIConstants;
 import org.springframework.web.util.UriComponents;
 import org.springframework.web.util.UriComponentsBuilder;
 
@@ -250,12 +255,7 @@ public abstract class BulkConsumer extends RESTAPI {
                        throw new AAIException("AAI_6111", String.format("input payload does not follow %s interface", module));
                }
                JsonArray transactions = transactionsObj.getAsJsonArray();
-               if (transactions.size() == 0) {
-                       //case where user sends a validly formatted transactions object but
-                       //which has no actual things in it for A&AI to do anything with
-                       //assuming we should count this as a user error
-                       throw new AAIException("AAI_6118", "payload had no objects to operate on");
-               }
+               validateRequest(transactions);
                return transactions;
        }
        
@@ -531,6 +531,49 @@ public abstract class BulkConsumer extends RESTAPI {
                }
        }
 
+       /**
+        * Pulls the config value for the limit of operations allowed in a bulk add/process request
+        *
+        * @throws AAIException
+        */
+       private int getPayLoadLimit() throws AAIException{
+               return Integer.parseInt(AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_LIMIT));
+       }
+
+       /**
+        * Validates the amount of operations in a request payload is allowed
+        *
+        * @param transactions - a JsonArray of all the transactions in the request payload
+        * @throws AAIException
+        */
+       private void validateRequest(JsonArray transactions) throws AAIException{
+               if (transactions.size() == 0) {
+                       //case where user sends a validly formatted transactions object but
+                       //which has no actual things in it for A&AI to do anything with
+                       //assuming we should count this as a user error
+                       throw new AAIException("AAI_6118", "payload had no objects to operate on");
+               }else if(transactions.size() > getPayLoadLimit()) {
+                       throw new AAIException("AAI_6147", String.format("Payload limit of %s reached, please reduce payload.", getPayLoadLimit()));
+               }
+               int operationCount = 0;
+               int payLoadLimit = getPayLoadLimit();
+               for(int i = 0; i < transactions.size(); i++){
+                       Set<Entry<String, JsonElement>> entrySet = transactions.get(i).getAsJsonObject().entrySet();
+                       Iterator<Entry<String, JsonElement>> it = entrySet.iterator();
+                       while(it.hasNext()){
+                               Map.Entry<String, JsonElement> element = it.next();
+                               if(element.getValue() instanceof JsonArray) {
+                                       operationCount += ((JsonArray) element.getValue()).size();
+                               }else{
+                                       operationCount++;
+                               }
+                       }
+                       if(operationCount > payLoadLimit){
+                               throw new AAIException("AAI_6147", String.format("Payload limit of %s reached, please reduce payload.", payLoadLimit));
+                       }
+               }
+       }
+
        protected abstract String getModule();
        
        protected abstract boolean functionAllowed(HttpMethod method);
index 66afeeb..e734d98 100644 (file)
@@ -107,6 +107,30 @@ public class BulkAddConsumerTest extends BulkProcessorTestAbstraction {
         assertEquals("Bad Request", Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         assertEquals("Contains error code", true, response.getEntity().toString().contains("ERR.5.4.6111"));
     }
+
+    @Test
+    public void bulkAddCheckMeetsLimit() throws IOException{
+        when(uriInfo.getPath()).thenReturn(uri);
+        when(uriInfo.getPath(false)).thenReturn(uri);
+
+        String payload = getBulkPayload("pserver-bulk-limit-meet");
+        Response response = executeRequest(payload);
+
+        assertEquals("Created", Response.Status.CREATED.getStatusCode(), response.getStatus());
+        assertEquals("Contains 30 {\"201\":null}", 30, StringUtils.countMatches(response.getEntity().toString(), "{\"201\":null}"));
+    }
+
+    @Test
+    public void bulkAddCheckExceedsLimit() throws IOException{
+        when(uriInfo.getPath()).thenReturn(uri);
+        when(uriInfo.getPath(false)).thenReturn(uri);
+
+        String payload = getBulkPayload("pserver-bulk-limit-exceed");
+        Response response = executeRequest(payload);
+
+        assertEquals("Bad Request", Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+        assertEquals("Contains error code", true, response.getEntity().toString().contains("ERR.5.4.6147"));
+    }
     
     @Override
     protected BulkConsumer getConsumer(){
index 8a75a96..1e3a4e4 100644 (file)
@@ -246,6 +246,30 @@ public class BulkProcessConsumerTest extends BulkProcessorTestAbstraction {
         assertEquals("Bad Request", Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());\r
         assertEquals("Contains error code", true, response.getEntity().toString().contains("ERR.5.4.6111"));\r
     }\r
+    @Test\r
+    public void bulkProcessCheckMeetsLimit() throws IOException{\r
+        when(uriInfo.getPath()).thenReturn(uri);\r
+        when(uriInfo.getPath(false)).thenReturn(uri);\r
+\r
+        String payload = getBulkPayload("pserver-bulk-limit-meet");\r
+        Response response = executeRequest(payload);\r
+\r
+        assertEquals("Created", Response.Status.CREATED.getStatusCode(), response.getStatus());\r
+        //assertEquals("Contains error code", true, response.getEntity().toString().contains("ERR.5.4.6147"));\r
+        assertEquals("Contains 30 {\"201\":null}", 30, StringUtils.countMatches(response.getEntity().toString(), "{\"201\":null}"));\r
+    }\r
+\r
+    @Test\r
+    public void bulkProcessCheckExceedsLimit() throws IOException{\r
+        when(uriInfo.getPath()).thenReturn(uri);\r
+        when(uriInfo.getPath(false)).thenReturn(uri);\r
+\r
+        String payload = getBulkPayload("pserver-bulk-limit-exceed");\r
+        Response response = executeRequest(payload);\r
+\r
+        assertEquals("Bad Request", Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());\r
+        assertEquals("Contains error code", true, response.getEntity().toString().contains("ERR.5.4.6147"));\r
+    }\r
     \r
     @Override\r
     protected BulkConsumer getConsumer(){\r
index 5ba1e0f..d406c04 100644 (file)
@@ -144,3 +144,5 @@ aai.run.migrations=false
 ecm.auth.password.x=OBF:1igd1i9a1jnb1yte1vv11vu91yt81jk71i6o1idt
 
 aai.jms.enable=false
+#limit set for bulk consumer APIS
+aai.bulkconsumer.payloadlimit=30
index 11416ca..10f1177 100644 (file)
@@ -111,6 +111,7 @@ AAI_6143=5:4:INFO:6143:400:3000:Ghost vertex found
 AAI_6144=5:4:WARN:6144:400:3000:Cycle found in graph
 AAI_6145=5:4:ERROR:6145:400:3000:Cannot create a nested/containment edge via relationship
 AAI_6146=5:4:ERROR:6146:400:3000:Ambiguous identity map found, use a URI instead
+AAI_6147=5:4:ERROR:6147:400:3000:Payload Limit Reached, reduce payload
 
 #--- aaicsvp: 7101-7199
 AAI_7101=5:4:ERROR:7101:500:3002:Unexpected error in CSV file processing
diff --git a/aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-exceed.json b/aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-exceed.json
new file mode 100644 (file)
index 0000000..60a96dd
--- /dev/null
@@ -0,0 +1,229 @@
+{
+  "transactions": [
+    {
+      "put": [
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-1-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-1-<UUID>",
+            "fqdn": "fake-fqdn-1"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-2-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-2-<UUID>",
+            "fqdn": "fake-fqdn-2"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-3-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-3-<UUID>",
+            "fqdn": "fake-fqdn-3"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-4-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-4-<UUID>",
+            "fqdn": "fake-fqdn-4"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-5-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-5-<UUID>",
+            "fqdn": "fake-fqdn-5"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-6-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-6-<UUID>",
+            "fqdn": "fake-fqdn-6"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-7-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-7-<UUID>",
+            "fqdn": "fake-fqdn-7"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-8-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-8-<UUID>",
+            "fqdn": "fake-fqdn-8"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-9-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-9-<UUID>",
+            "fqdn": "fake-fqdn-9"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-10-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-10-<UUID>",
+            "fqdn": "fake-fqdn-10"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-11-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-11-<UUID>",
+            "fqdn": "fake-fqdn-11"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-12-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-12-<UUID>",
+            "fqdn": "fake-fqdn-12"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-13-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-13-<UUID>",
+            "fqdn": "fake-fqdn-13"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-14-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-14-<UUID>",
+            "fqdn": "fake-fqdn-14"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-15-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-15-<UUID>",
+            "fqdn": "fake-fqdn-15"
+          }
+        }
+      ]
+    },
+    {
+      "put": [
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-16-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-16-<UUID>",
+            "fqdn": "fake-fqdn-16"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-17-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-17-<UUID>",
+            "fqdn": "fake-fqdn-17"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-18-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-18-<UUID>",
+            "fqdn": "fake-fqdn-18"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-19-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-19-<UUID>",
+            "fqdn": "fake-fqdn-19"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-20-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-20-<UUID>",
+            "fqdn": "fake-fqdn-20"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-21-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-21-<UUID>",
+            "fqdn": "fake-fqdn-21"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-22-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-22-<UUID>",
+            "fqdn": "fake-fqdn-22"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-23-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-23-<UUID>",
+            "fqdn": "fake-fqdn-23"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-24-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-24-<UUID>",
+            "fqdn": "fake-fqdn-24"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-25-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-25-<UUID>",
+            "fqdn": "fake-fqdn-25"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-26-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-26-<UUID>",
+            "fqdn": "fake-fqdn-26"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-27-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-27-<UUID>",
+            "fqdn": "fake-fqdn-27"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-28-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-28-<UUID>",
+            "fqdn": "fake-fqdn-28"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-29-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-29-<UUID>",
+            "fqdn": "fake-fqdn-29"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-30-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-30-<UUID>",
+            "fqdn": "fake-fqdn-30"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-31-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-31-<UUID>",
+            "fqdn": "fake-fqdn-31"
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-meet.json b/aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-meet.json
new file mode 100644 (file)
index 0000000..b06a846
--- /dev/null
@@ -0,0 +1,222 @@
+{
+  "transactions": [
+    {
+      "put": [
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-1-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-1-<UUID>",
+            "fqdn": "fake-fqdn-1"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-2-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-2-<UUID>",
+            "fqdn": "fake-fqdn-2"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-3-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-3-<UUID>",
+            "fqdn": "fake-fqdn-3"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-4-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-4-<UUID>",
+            "fqdn": "fake-fqdn-4"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-5-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-5-<UUID>",
+            "fqdn": "fake-fqdn-5"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-6-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-6-<UUID>",
+            "fqdn": "fake-fqdn-6"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-7-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-7-<UUID>",
+            "fqdn": "fake-fqdn-7"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-8-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-8-<UUID>",
+            "fqdn": "fake-fqdn-8"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-9-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-9-<UUID>",
+            "fqdn": "fake-fqdn-9"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-10-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-10-<UUID>",
+            "fqdn": "fake-fqdn-10"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-11-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-11-<UUID>",
+            "fqdn": "fake-fqdn-11"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-12-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-12-<UUID>",
+            "fqdn": "fake-fqdn-12"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-13-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-13-<UUID>",
+            "fqdn": "fake-fqdn-13"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-14-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-14-<UUID>",
+            "fqdn": "fake-fqdn-14"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-15-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-15-<UUID>",
+            "fqdn": "fake-fqdn-15"
+          }
+        }
+      ]
+    },
+    {
+      "put": [
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-16-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-16-<UUID>",
+            "fqdn": "fake-fqdn-16"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-17-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-17-<UUID>",
+            "fqdn": "fake-fqdn-17"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-18-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-18-<UUID>",
+            "fqdn": "fake-fqdn-18"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-19-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-19-<UUID>",
+            "fqdn": "fake-fqdn-19"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-20-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-20-<UUID>",
+            "fqdn": "fake-fqdn-20"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-21-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-21-<UUID>",
+            "fqdn": "fake-fqdn-21"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-22-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-22-<UUID>",
+            "fqdn": "fake-fqdn-22"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-23-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-23-<UUID>",
+            "fqdn": "fake-fqdn-23"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-24-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-24-<UUID>",
+            "fqdn": "fake-fqdn-24"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-25-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-25-<UUID>",
+            "fqdn": "fake-fqdn-25"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-26-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-26-<UUID>",
+            "fqdn": "fake-fqdn-26"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-27-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-27-<UUID>",
+            "fqdn": "fake-fqdn-27"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-28-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-28-<UUID>",
+            "fqdn": "fake-fqdn-28"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-29-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-29-<UUID>",
+            "fqdn": "fake-fqdn-29"
+          }
+        },
+        {
+          "uri": "/cloud-infrastructure/pservers/pserver/pserver-transactions-30-<UUID>",
+          "body": {
+            "hostname": "pserver-transactions-30-<UUID>",
+            "fqdn": "fake-fqdn-30"
+          }
+        }
+      ]
+    }
+  ]
+}