diff options
author | Maharajh, Robby (rx2202) <rx2202@us.att.com> | 2017-12-04 16:43:59 -0500 |
---|---|---|
committer | Maharajh, Robby (rx2202) <rx2202@us.att.com> | 2017-12-04 16:44:06 -0500 |
commit | 944224b1a452ba90913bac6bee842f5a6bd61770 (patch) | |
tree | a9c58365afea882ff9ddfdea33ea1f5bea35b53f /aai-resources/src | |
parent | 4febf4b4c10d435e2a12e4df34d590254263e38b (diff) |
Update the aai-resources to verify bulk limits
Issue-ID: AAI-529
Change-Id: Ia87e3298ce9c46f3b409587df6e9bd6e2065ec8a
Signed-off-by: Maharajh, Robby (rx2202) <rx2202@us.att.com>
Diffstat (limited to 'aai-resources/src')
7 files changed, 551 insertions, 6 deletions
diff --git a/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java index 5591ae3..5ff0e35 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java @@ -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); diff --git a/aai-resources/src/test/java/org/onap/aai/rest/BulkAddConsumerTest.java b/aai-resources/src/test/java/org/onap/aai/rest/BulkAddConsumerTest.java index 66afeeb..e734d98 100644 --- a/aai-resources/src/test/java/org/onap/aai/rest/BulkAddConsumerTest.java +++ b/aai-resources/src/test/java/org/onap/aai/rest/BulkAddConsumerTest.java @@ -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(){ diff --git a/aai-resources/src/test/java/org/onap/aai/rest/BulkProcessConsumerTest.java b/aai-resources/src/test/java/org/onap/aai/rest/BulkProcessConsumerTest.java index 8a75a96..1e3a4e4 100644 --- a/aai-resources/src/test/java/org/onap/aai/rest/BulkProcessConsumerTest.java +++ b/aai-resources/src/test/java/org/onap/aai/rest/BulkProcessConsumerTest.java @@ -246,6 +246,30 @@ public class BulkProcessConsumerTest 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 bulkProcessCheckMeetsLimit() 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 error code", true, response.getEntity().toString().contains("ERR.5.4.6147"));
+ assertEquals("Contains 30 {\"201\":null}", 30, StringUtils.countMatches(response.getEntity().toString(), "{\"201\":null}"));
+ }
+
+ @Test
+ public void bulkProcessCheckExceedsLimit() 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(){
diff --git a/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties b/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties index 5ba1e0f..d406c04 100644 --- a/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties +++ b/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties @@ -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 diff --git a/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/error.properties b/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/error.properties index 11416ca..10f1177 100644 --- a/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/error.properties +++ b/aai-resources/src/test/resources/bundleconfig-local/etc/appprops/error.properties @@ -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 index 0000000..60a96dd --- /dev/null +++ b/aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-exceed.json @@ -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 index 0000000..b06a846 --- /dev/null +++ b/aai-resources/src/test/resources/payloads/bulk/pserver-bulk-limit-meet.json @@ -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" + } + } + ] + } + ] +} |