diff options
author | FrancescoFioraEst <francesco.fiora@est.tech> | 2023-11-22 16:32:07 +0000 |
---|---|---|
committer | Francesco Fiora <francesco.fiora@est.tech> | 2023-11-24 16:04:33 +0000 |
commit | d1f43390b090bbdb480c8da31e9fdae0c8e00be4 (patch) | |
tree | 5f61f94d9758dc3bbf4804247642008f6f4a9f15 /runtime-acm | |
parent | 61571e7b5119793bbbfb8942db5765d16fbd4fdf (diff) |
Allow semantic versioning in all templates in ACM
Issue-ID: POLICY-4886
Change-Id: I0c46397e86377e6f59f55121a60b8f2b5665a5d5
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
Diffstat (limited to 'runtime-acm')
5 files changed, 273 insertions, 39 deletions
diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java index 6c5417286..ed8badf8b 100755 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java @@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML; +import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_VERSIONING; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.Response; @@ -46,6 +47,7 @@ import org.onap.policy.clamp.models.acm.messages.rest.commissioning.Commissionin import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.models.base.PfKey; import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty; @@ -128,14 +130,11 @@ class CommissioningControllerTest extends CommonRestController { x.setVersion("1.0.wrong"); serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().put(x.getName(), x); - var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); - var resp = invocationBuilder.post(Entity.json(serviceTemplateCreate)); - - assertThat(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).isEqualTo(resp.getStatus()); - var commissioningResponse = resp.readEntity(CommissioningResponse.class); + var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.INTERNAL_SERVER_ERROR); assertThat(commissioningResponse.getErrorDetails()) .isEqualTo("java.lang.IllegalArgumentException Internal Server Error parameter " - + "\"version\": value \"1.0.wrong\", does not match regular expression \"^(\\d+.){2}\\d+$\""); + + "\"version\": value \"1.0.wrong\", does not match regular expression \"" + + PfKey.VERSION_REGEXP + "\""); assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull(); } @@ -143,11 +142,7 @@ class CommissioningControllerTest extends CommonRestController { void testCreate() { var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate); serviceTemplateCreate.setName("Create"); - - var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); - var resp = invocationBuilder.post(Entity.json(serviceTemplateCreate)); - assertEquals(Response.Status.CREATED.getStatusCode(), resp.getStatus()); - var commissioningResponse = resp.readEntity(CommissioningResponse.class); + var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.CREATED); assertNotNull(commissioningResponse); assertNull(commissioningResponse.getErrorDetails()); // Response should return the number of node templates present in the service template @@ -159,6 +154,29 @@ class CommissioningControllerTest extends CommonRestController { } @Test + void testVersioning() { + var serviceTemplateCreate = InstantiationUtils.getToscaServiceTemplate(TOSCA_VERSIONING); + var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.CREATED); + assertNotNull(commissioningResponse); + assertNull(commissioningResponse.getErrorDetails()); + // Response should return the number of node templates present in the service template + assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(11); + for (var nodeTemplateName : serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().keySet()) { + assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream() + .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); + } + } + + private CommissioningResponse createServiceTemplate(ToscaServiceTemplate serviceTemplateCreate, + Response.Status statusExpected) { + var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + try (var resp = invocationBuilder.post(Entity.json(serviceTemplateCreate))) { + assertEquals(statusExpected.getStatusCode(), resp.getStatus()); + return resp.readEntity(CommissioningResponse.class); + } + } + + @Test void testUpdate() { var toscaDataType = new ToscaDataType(); toscaDataType.setName("org.onap.datatypes.policy.clamp.Configuration"); @@ -173,10 +191,8 @@ class CommissioningControllerTest extends CommonRestController { var serviceTemplateUpdate = new ToscaServiceTemplate(serviceTemplate); serviceTemplateUpdate.getDataTypes().put(toscaDataType.getName(), toscaDataType); serviceTemplateUpdate.setMetadata(Map.of("compositionId", compositionId)); - var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); - var resp = invocationBuilder.post(Entity.json(serviceTemplateUpdate)); - assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); - var commissioningResponse = resp.readEntity(CommissioningResponse.class); + + var commissioningResponse = createServiceTemplate(serviceTemplateUpdate, Response.Status.OK); assertNotNull(commissioningResponse); assertNull(commissioningResponse.getErrorDetails()); // Response should return the number of node templates present in the service template @@ -186,13 +202,18 @@ class CommissioningControllerTest extends CommonRestController { .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); } - invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + compositionId); - resp = invocationBuilder.buildGet().invoke(); - assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); - var entity = resp.readEntity(AutomationCompositionDefinition.class); + var entity = getServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId, Response.Status.OK); assertThat(entity.getServiceTemplate().getDataTypes()).containsKey(toscaDataType.getName()); } + private AutomationCompositionDefinition getServiceTemplate(String url, Response.Status statusExpected) { + var invocationBuilder = super.sendRequest(url); + try (var resp = invocationBuilder.buildGet().invoke()) { + assertEquals(statusExpected.getStatusCode(), resp.getStatus()); + return resp.readEntity(AutomationCompositionDefinition.class); + } + } + @Test void testQuery_NoResultWithThisName() { var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=noResultWithThisName"); @@ -216,21 +237,20 @@ class CommissioningControllerTest extends CommonRestController { @Test void testDeleteBadRequest() { createEntryInDB("DeleteBadRequest"); + deleteServiceTemplate(COMMISSIONING_ENDPOINT + "/" + UUID.randomUUID(), Response.Status.NOT_FOUND); + } - var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + UUID.randomUUID()); - // Call delete with no info - var resp = invocationBuilder.delete(); - assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); + private void deleteServiceTemplate(String url, Response.Status statusExpected) { + var invocationBuilder = super.sendRequest(url); + try (var resp = invocationBuilder.delete()) { + assertEquals(statusExpected.getStatusCode(), resp.getStatus()); + } } @Test void testDelete() { var compositionId = createEntryInDB("forDelete"); - - var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + compositionId); - // Call delete with no info - var resp = invocationBuilder.delete(); - assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + deleteServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId, Response.Status.OK); var templatesInDB = acDefinitionProvider.findAcDefinition(compositionId); assertThat(templatesInDB).isEmpty(); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/InstantiationUtils.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/InstantiationUtils.java index 534762299..38c63fa9b 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/InstantiationUtils.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/InstantiationUtils.java @@ -64,6 +64,26 @@ public class InstantiationUtils { } /** + * Gets the AutomationComposition from Resource in yaml format. + * + * @param path path of the resource + * @param suffix suffix to add to all names in AutomationCompositions + * @return the AutomationComposition from Resource + */ + public static AutomationComposition getAutomationCompositionFromYaml(final String path, final String suffix) { + try { + var automationComposition = YAML_TRANSLATOR.decode(new File(path), AutomationComposition.class); + + // add suffix to name + automationComposition.setName(automationComposition.getName() + suffix); + return automationComposition; + } catch (CoderException e) { + fail("Cannot read or decode " + path); + return null; + } + } + + /** * Assert that Instantiation Response contains proper AutomationCompositions. * * @param response InstantiationResponse diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java index 1e5aa6c89..cd1a3856a 100755 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java @@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML; +import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_VERSIONING; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.Response; @@ -66,6 +67,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; class InstantiationControllerTest extends CommonRestController { private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json"; + private static final String AC_VERSIONING_YAML = "src/test/resources/rest/acm/AutomationCompositionVersioning.yaml"; private static final String AC_INSTANTIATION_UPDATE_JSON = "src/test/resources/rest/acm/AutomationCompositionUpdate.json"; @@ -144,10 +146,8 @@ class InstantiationControllerTest extends CommonRestController { InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Create"); automationCompositionFromRsc.setCompositionId(compositionId); - var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId)); - var resp = invocationBuilder.post(Entity.json(automationCompositionFromRsc)); - assertEquals(Response.Status.CREATED.getStatusCode(), resp.getStatus()); - var instResponse = resp.readEntity(InstantiationResponse.class); + var instResponse = createAutomationComposition(compositionId, automationCompositionFromRsc, + Response.Status.CREATED); InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc); automationCompositionFromRsc.setInstanceId(instResponse.getInstanceId()); automationCompositionFromRsc.getElements().values() @@ -160,6 +160,15 @@ class InstantiationControllerTest extends CommonRestController { assertEquals(automationCompositionFromRsc, automationCompositionFromDb); } + private InstantiationResponse createAutomationComposition(UUID compositionId, + AutomationComposition automationComposition, Response.Status statusExpected) { + var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId)); + try (var resp = invocationBuilder.post(Entity.json(automationComposition))) { + assertEquals(statusExpected.getStatusCode(), resp.getStatus()); + return resp.readEntity(InstantiationResponse.class); + } + } + @Test void testCreateBadRequest() { var compositionId = createAcDefinitionInDB("CreateBadRequest"); @@ -167,19 +176,28 @@ class InstantiationControllerTest extends CommonRestController { .getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "CreateBadRequest"); automationCompositionFromRsc.setCompositionId(compositionId); - var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId)); - var resp = invocationBuilder.post(Entity.json(automationCompositionFromRsc)); - assertEquals(Response.Status.CREATED.getStatusCode(), resp.getStatus()); + createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED); // testing Bad Request: AC already defined - resp = invocationBuilder.post(Entity.json(automationCompositionFromRsc)); - assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); - var instResponse = resp.readEntity(InstantiationResponse.class); + var instResponse = createAutomationComposition(compositionId, automationCompositionFromRsc, + Response.Status.BAD_REQUEST); assertNotNull(instResponse.getErrorDetails()); assertNull(instResponse.getAffectedAutomationComposition()); } @Test + void testVersioning() { + var serviceTemplateVer = InstantiationUtils.getToscaServiceTemplate(TOSCA_VERSIONING); + var compositionId = createAcDefinitionInDB(serviceTemplateVer); + var automationCompositionFromRsc = InstantiationUtils + .getAutomationCompositionFromYaml(AC_VERSIONING_YAML, "Versioning"); + automationCompositionFromRsc.setCompositionId(compositionId); + var instResponse = + createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED); + InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc); + } + + @Test void testQuery_NoResultWithThisName() { var invocationBuilder = super.sendRequest(getInstanceEndPoint(UUID.randomUUID()) + "?name=noResultWithThisName"); @@ -339,7 +357,11 @@ class InstantiationControllerTest extends CommonRestController { private UUID createAcDefinitionInDB(String name) { var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate); serviceTemplateCreate.setName(name); - var acmDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + return createAcDefinitionInDB(serviceTemplateCreate); + } + + private UUID createAcDefinitionInDB(ToscaServiceTemplate serviceTemplateCreate) { + var acmDefinition = CommonTestData.createAcDefinition(serviceTemplateCreate, AcTypeState.PRIMED); acDefinitionProvider.updateAcDefinition(acmDefinition, NODE_TYPE); saveDummyParticipantInDb(); return acmDefinition.getCompositionId(); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java index 54d312477..8329d050b 100755 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java @@ -46,6 +46,8 @@ public class CommonTestData { private static final Coder CODER = new StandardCoder(); public static final String TOSCA_SERVICE_TEMPLATE_YAML = "clamp/acm/pmsh/funtional-pmsh-usecase.yaml"; + public static final String TOSCA_VERSIONING = "clamp/acm/test/tosca-versioning.yaml"; + public static final String TOSCA_COMP_NAME = "org.onap.policy.clamp.acm.AutomationComposition"; public static final String TOSCA_ELEMENT_NAME = "org.onap.policy.clamp.acm.AutomationCompositionElement"; diff --git a/runtime-acm/src/test/resources/rest/acm/AutomationCompositionVersioning.yaml b/runtime-acm/src/test/resources/rest/acm/AutomationCompositionVersioning.yaml new file mode 100755 index 000000000..db93c261c --- /dev/null +++ b/runtime-acm/src/test/resources/rest/acm/AutomationCompositionVersioning.yaml @@ -0,0 +1,170 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2023 Nordix Foundation. +# ================================================================================ +# 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========================================================= +name: DemoInstance0 +version: 1.0.1+1 +compositionId: 709c62b3-8918-41b9-a747-d21eb79c6c40 +description: Demo automation composition instance 0 +elements: + + 709c62b3-8918-41b9-a747-d21eb79c6c20: + id: 709c62b3-8918-41b9-a747-d21eb79c6c20 + definition: + name: onap.policy.clamp.ac.element.Policy_AutomationCompositionElement + version: 1.2.3+build1 + description: Starter Automation Composition Element for the Demo + properties: + policy_type_id: + name: onap.policies.operational.pm-subscription-handler + version: 1.0.0 + policy_id: + get_input: acm_element_policy + + 709c62b3-8918-41b9-a747-d21eb79c6c21: + id: 709c62b3-8918-41b9-a747-d21eb79c6c21 + definition: + name: onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement + version: 1.2.3+build1 + description: Starter Automation Composition Element for the Demo + properties: + chart: + chartId: + name: acelement + version: 0.1.0 + namespace: default + releaseName: acm-starter + podName: acm-starter + repository: + repoName: chartmuseum + address: 'http://cluster-ip:8080' + overrideParams: + acelement.elementId.name: onap.policy.clamp.ac.starter + service.nodeport: 30800 + + 709c62b3-8918-41b9-a747-d21eb79c6c22: + id: 709c62b3-8918-41b9-a747-d21eb79c6c22 + definition: + name: onap.policy.clamp.ac.element.K8S_BridgeAutomationCompositionElement + version: 1.2.3+build1 + description: Bridge Automation Composition Element for the Demo + properties: + chart: + chartId: + name: acelement + version: 0.1.0 + namespace: default + releaseName: acm-bridge + podName: acm-bridge + repository: + repoName: chartmuseum + address: 'http://cluster-ip:8080' + overrideParams: + acelement.elementId.name: onap.policy.clamp.ac.bridge + service.nodeport: 30801 + + 709c62b3-8918-41b9-a747-d21eb79c6c23: + id: 709c62b3-8918-41b9-a747-d21eb79c6c23 + definition: + name: onap.policy.clamp.ac.element.K8S_SinkAutomationCompositionElement + version: 1.2.3+build1 + description: Sink Automation Composition Element for the Demo + properties: + chart: + chartId: + name: acelement + version: 0.1.0 + namespace: default + releaseName: acm-sink + podName: acm-sink + repository: + repoName: chartmuseum + address: 'http://cluster-ip:8080' + overrideParams: + acelement.elementId.name: onap.policy.clamp.ac.sink + service.nodeport: 30802 + + 709c62b3-8918-41b9-a747-d21eb79c6c24: + id: 709c62b3-8918-41b9-a747-d21eb79c6c24 + definition: + name: onap.policy.clamp.ac.element.Http_StarterAutomationCompositionElement + version: 1.2.3+build1 + description: Starter Automation Composition Element for the Demo + properties: + baseUrl: http://cluster-ip:30800 + httpHeaders: + Content-Type: application/json + Authorization: Basic YWNtVXNlcjp6YiFYenRHMzQ= + configurationEntities: + - configurationEntityId: + name: onap.policy.clamp.ac.starter + version: 1.0.0 + restSequence: + - restRequestId: + name: request1 + version: 1.0.1 + httpMethod: POST + path: /onap/policy/clamp/acelement/v2/activate + body: '{ "receiverId": { "name": "onap.policy.clamp.ac.startertobridge", "version": "1.0.0" }, "timerMs": 20000, "elementType": "STARTER", "topicParameterGroup": { "server": "message-router:3904", "listenerTopic": "POLICY_UPDATE_MSG", "publisherTopic": "AC_ELEMENT_MSG", "fetchTimeout": 15000, "topicCommInfrastructure": "dmaap" } }' + expectedResponse: 201 + + 709c62b3-8918-41b9-a747-d21eb79c6c25: + id: 709c62b3-8918-41b9-a747-d21eb79c6c25 + definition: + name: onap.policy.clamp.ac.element.Http_BridgeAutomationCompositionElement + version: 1.2.3+build1 + description: Bridge Automation Composition Element for the Demo + properties: + baseUrl: http://cluster-ip:30801 + httpHeaders: + Content-Type: application/json + Authorization: Basic YWNtVXNlcjp6YiFYenRHMzQ= + configurationEntities: + - configurationEntityId: + name: onap.policy.clamp.ac.bridge + version: 1.0.0 + restSequence: + - restRequestId: + name: request2 + version: 1.0.1 + httpMethod: POST + path: /onap/policy/clamp/acelement/v2/activate + body: '{ "receiverId": { "name": "onap.policy.clamp.ac.bridgetosink", "version": "1.0.0" }, "timerMs": 20000, "elementType": "BRIDGE", "topicParameterGroup": { "server": "message-router:3904", "listenerTopic": "POLICY_UPDATE_MSG", "publisherTopic": "AC_ELEMENT_MSG", "fetchTimeout": 15000, "topicCommInfrastructure": "dmaap" } }' + expectedResponse: 201 + + 709c62b3-8918-41b9-a747-d21eb79c6c26: + id: 709c62b3-8918-41b9-a747-d21eb79c6c26 + definition: + name: onap.policy.clamp.ac.element.Http_SinkAutomationCompositionElement + version: 1.2.3+build1 + description: Sink Automation Composition Element for the Demo + properties: + baseUrl: http://cluster-ip:30802 + httpHeaders: + Content-Type: application/json + Authorization: Basic YWNtVXNlcjp6YiFYenRHMzQ= + configurationEntities: + - configurationEntityId: + name: onap.policy.clamp.ac.sink + version: 1.0.0 + restSequence: + - restRequestId: + name: request3 + version: 1.0.1 + httpMethod: POST + path: /onap/policy/clamp/acelement/v2/activate + body: '{ "receiverId": { "name": "onap.policy.clamp.ac.sink", "version": "1.0.0" }, "timerMs": 20000, "elementType": "SINK", "topicParameterGroup": { "server": "message-router", "listenerTopic": "POLICY_UPDATE_MSG", "publisherTopic": "AC_ELEMENT_MSG", "fetchTimeout": 15000, "topicCommInfrastructure": "dmaap" } }' + expectedResponse: 201 |