diff options
Diffstat (limited to 'bpmn')
6 files changed, 394 insertions, 15 deletions
diff --git a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/UserParamsServiceTraversal.java b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/UserParamsServiceTraversal.java index 3556cc024c..6c6bd61041 100644 --- a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/UserParamsServiceTraversal.java +++ b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/UserParamsServiceTraversal.java @@ -104,7 +104,8 @@ public class UserParamsServiceTraversal { if ((vfModuleCustomization.getVfModule() != null) && ((vfModuleCustomization.getVfModule().getModuleHeatTemplate() != null && vfModuleCustomization.getHeatEnvironment() != null)) - || (vfModuleCustomization.getVfModule().getModelName() != null + || (vfModuleCustomization.getVfModule() != null + && vfModuleCustomization.getVfModule().getModelName() != null && vfModuleCustomization.getVfModule().getModelName() .contains("helm"))) { foundVfModuleOrVG = true; diff --git a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java index ccefc772c3..ec2ca74fa7 100644 --- a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java +++ b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java @@ -420,18 +420,25 @@ public class WorkflowActionBBTasks { } public void postProcessingExecuteBB(DelegateExecution execution) { - List<ExecuteBuildingBlock> flowsToExecute = - (List<ExecuteBuildingBlock>) execution.getVariable("flowsToExecute"); - String handlingCode = (String) execution.getVariable(HANDLINGCODE); - final boolean aLaCarte = (boolean) execution.getVariable(G_ALACARTE); - int currentSequence = (int) execution.getVariable(G_CURRENT_SEQUENCE); - ExecuteBuildingBlock ebb = flowsToExecute.get(currentSequence - 1); - String bbFlowName = ebb.getBuildingBlock().getBpmnFlowName(); - if ("ActivateVfModuleBB".equalsIgnoreCase(bbFlowName) && aLaCarte && "Success".equalsIgnoreCase(handlingCode)) { - postProcessingExecuteBBActivateVfModule(execution, ebb, flowsToExecute); - } + try { + List<ExecuteBuildingBlock> flowsToExecute = + (List<ExecuteBuildingBlock>) execution.getVariable("flowsToExecute"); + String handlingCode = (String) execution.getVariable(HANDLINGCODE); + final boolean aLaCarte = (boolean) execution.getVariable(G_ALACARTE); + int currentSequence = (int) execution.getVariable(G_CURRENT_SEQUENCE); + logger.debug("Current Sequence: {}", currentSequence); + ExecuteBuildingBlock ebb = flowsToExecute.get(currentSequence - 1); + String bbFlowName = ebb.getBuildingBlock().getBpmnFlowName(); + if ("ActivateVfModuleBB".equalsIgnoreCase(bbFlowName) && aLaCarte + && "Success".equalsIgnoreCase(handlingCode)) { + postProcessingExecuteBBActivateVfModule(execution, ebb, flowsToExecute); + } - flowManipulatorListenerRunner.postModifyFlows(flowsToExecute, new DelegateExecutionImpl(execution)); + flowManipulatorListenerRunner.postModifyFlows(flowsToExecute, new DelegateExecutionImpl(execution)); + } catch (Exception ex) { + logger.error("Exception in postProcessingExecuteBB", ex); + workflowAction.buildAndThrowException(execution, "Failed to post process Execute BB"); + } } protected void postProcessingExecuteBBActivateVfModule(DelegateExecution execution, ExecuteBuildingBlock ebb, diff --git a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/decisionpoint/impl/buildingblock/controller/sdnc/prepare/PrepareSdncUpgradePreCheckPnfBBTest.java b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/decisionpoint/impl/buildingblock/controller/sdnc/prepare/PrepareSdncUpgradePreCheckPnfBBTest.java index 0ba1e27f5e..5a070aff4a 100644 --- a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/decisionpoint/impl/buildingblock/controller/sdnc/prepare/PrepareSdncUpgradePreCheckPnfBBTest.java +++ b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/decisionpoint/impl/buildingblock/controller/sdnc/prepare/PrepareSdncUpgradePreCheckPnfBBTest.java @@ -55,16 +55,40 @@ public class PrepareSdncUpgradePreCheckPnfBBTest { } @Test - public void prepare_jsonWithoutActionPayload() { + public void prepareJson_payloadWithoutAction() { String payloadWithoutActionArray = "{\"json name\": \"test1\"}"; ControllerContext<BuildingBlockExecution> controllerContext = - createControllerContext(payloadWithoutActionArray); + createControllerContext(payloadWithoutActionArray, "action1"); testedObject.prepare(controllerContext); assertThat((String) controllerContext.getExecution().getVariable("payload")) .isEqualTo(payloadWithoutActionArray); } + @Test + public void prepareJson_payloadWithActionJsonObject() { + String jsonActionObjectKey = "action1"; + String jsonActionObject = String.format("{\"%s\":\"act1\"}", jsonActionObjectKey); + String payloadWithActionArray = String.format("{\"json name\":\"test1\",\"action\": [%s]}", jsonActionObject); + ControllerContext<BuildingBlockExecution> controllerContext = + createControllerContext(payloadWithActionArray, jsonActionObjectKey); + + testedObject.prepare(controllerContext); + + assertThat((String) controllerContext.getExecution().getVariable("payload")).isEqualTo(jsonActionObject); + } + + @Test + public void prepareJson_payloadWithActionJsonObjectButDifferentKey() { + String payloadWithActionArray = ("{\"json name\":\"test1\",\"action\": [{\"action1\":\"act1\"}]}"); + ControllerContext<BuildingBlockExecution> controllerContext = + createControllerContext(payloadWithActionArray, "otherAction"); + + testedObject.prepare(controllerContext); + + assertThat((String) controllerContext.getExecution().getVariable("payload")).isEqualTo(payloadWithActionArray); + } + private ControllerContext<BuildingBlockExecution> createControllerContext(String actor, String action, String scope) { ControllerContext<BuildingBlockExecution> controllerContext = new ControllerContext<>(); @@ -74,9 +98,10 @@ public class PrepareSdncUpgradePreCheckPnfBBTest { return controllerContext; } - private ControllerContext<BuildingBlockExecution> createControllerContext(String payload) { + private ControllerContext<BuildingBlockExecution> createControllerContext(String payload, String action) { ControllerContext<BuildingBlockExecution> controllerContext = new ControllerContext<>(); controllerContext.setExecution(prepareBuildingBlockExecution(payload)); + controllerContext.setControllerAction(action); return controllerContext; } diff --git a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/service/level/ServiceLevelTest.java b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/service/level/ServiceLevelTest.java new file mode 100644 index 0000000000..cfaa4040c7 --- /dev/null +++ b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/service/level/ServiceLevelTest.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * 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========================================================= + */ + +package org.onap.so.bpmn.infrastructure.service.level; + +import static org.assertj.core.api.Assertions.assertThat; +import java.util.ArrayList; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.extension.mockito.delegate.DelegateExecutionFake; +import org.junit.Test; +import java.util.List; +import org.onap.so.bpmn.infrastructure.service.level.impl.ServiceLevelConstants; + +public class ServiceLevelTest { + + private static final String EXECUTION_KEY_PNF_NAME_LIST = "pnfNameList"; + private static final String EXECUTION_KEY_PNF_COUNTER = "pnfCounter"; + + @Test + public void pnfCounterExecution_success() { + // given + String pnfName = "pnfName1"; + DelegateExecution execution = new DelegateExecutionFake(); + execution.setVariable(EXECUTION_KEY_PNF_NAME_LIST, createPnfNameList(pnfName)); + execution.setVariable(EXECUTION_KEY_PNF_COUNTER, 0); + // when + new ServiceLevel().pnfCounterExecution(execution); + // then + assertThat(execution.getVariable(ServiceLevelConstants.PNF_NAME)).isEqualTo(pnfName); + assertThat(execution.getVariable(EXECUTION_KEY_PNF_COUNTER)).isEqualTo(1); + } + + private List<String> createPnfNameList(String pnfName) { + List<String> pnfNameList = new ArrayList<>(); + pnfNameList.add(pnfName); + return pnfNameList; + } +} diff --git a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/UserParamsServiceTraversalTest.java b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/UserParamsServiceTraversalTest.java new file mode 100644 index 0000000000..99f17a3628 --- /dev/null +++ b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/UserParamsServiceTraversalTest.java @@ -0,0 +1,219 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Modifications Copyright (c) 2020 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.so.bpmn.infrastructure.workflow.tasks; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.extension.mockito.delegate.DelegateExecutionFake; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.so.bpmn.BaseTaskTest; +import org.onap.so.bpmn.common.BBConstants; +import org.onap.so.client.exception.ExceptionBuilder; +import org.onap.so.db.catalog.beans.ConfigurationResource; +import org.onap.so.db.catalog.beans.CvnfcCustomization; +import org.onap.so.db.catalog.beans.HeatTemplate; +import org.onap.so.db.catalog.beans.NetworkCollectionResourceCustomization; +import org.onap.so.db.catalog.beans.VfModuleCustomization; +import org.onap.so.db.catalog.beans.Service; +import org.onap.so.db.catalog.beans.VfModule; +import org.onap.so.db.catalog.beans.CollectionResourceCustomization; +import org.onap.so.db.catalog.beans.CvnfcConfigurationCustomization; +import org.onap.so.db.catalog.beans.HeatEnvironment; +import org.onap.so.db.catalog.client.CatalogDbClient; +import org.onap.so.serviceinstancebeans.ServiceInstancesRequest; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; + +public class UserParamsServiceTraversalTest extends BaseTaskTest { + + private static final String MACRO_ASSIGN_JSON = "Macro/ServiceMacroAssign.json"; + private static final String MACRO_ASSIGN_PNF_JSON = "Macro/ServiceMacroAssignPnf.json"; + private static final String NETWORK_COLLECTION_JSON = "Macro/CreateNetworkCollection.json"; + private static final String serviceInstanceId = "123"; + private DelegateExecution execution; + private CatalogDbClient mockCatalogDbClient; + private UserParamsServiceTraversal userParamsServiceTraversal; + private String requestAction; + + @Before + public void before() throws Exception { + execution = new DelegateExecutionFake(); + mockCatalogDbClient = mock(CatalogDbClient.class); + userParamsServiceTraversal = new UserParamsServiceTraversal(mockCatalogDbClient, mock(ExceptionBuilder.class)); + requestAction = "assignInstance"; + } + + @Test + public void getResourceListFromUserParamsForVnfs() throws Exception { + initExecution(requestAction, readBpmnRequestFromFile(MACRO_ASSIGN_JSON), false); + Mockito.doReturn(getVfModuleCustomization()).when(mockCatalogDbClient) + .getVfModuleCustomizationByModelCuztomizationUUID("a25e8e8c-58b8-4eec-810c-97dcc1f5cb7f"); + Mockito.doReturn(getCvnfcCustomizations()).when(mockCatalogDbClient).getCvnfcCustomization(anyString(), + anyString(), anyString()); + + List<Resource> resourceListFromUserParams = userParamsServiceTraversal.getResourceListFromUserParams(execution, + getUserParams(), serviceInstanceId, requestAction); + List<WorkflowType> expected = List.of(WorkflowType.SERVICE, WorkflowType.VNF, WorkflowType.VOLUMEGROUP, + WorkflowType.VFMODULE, WorkflowType.CONFIGURATION); + List<WorkflowType> result = + resourceListFromUserParams.stream().map(Resource::getResourceType).collect(Collectors.toList()); + + assertEquals(5, resourceListFromUserParams.size()); + assertThat(expected, is(result)); + } + + @Test + public void getResourceListFromUserParamsForPnfs() throws Exception { + initExecution(requestAction, readBpmnRequestFromFile(MACRO_ASSIGN_PNF_JSON), false); + Mockito.doReturn(getVfModuleCustomization()).when(mockCatalogDbClient) + .getVfModuleCustomizationByModelCuztomizationUUID("a25e8e8c-58b8-4eec-810c-97dcc1f5cb7f"); + Mockito.doReturn(getCvnfcCustomizations()).when(mockCatalogDbClient).getCvnfcCustomization(anyString(), + anyString(), anyString()); + + List<Resource> resourceListFromUserParams = userParamsServiceTraversal.getResourceListFromUserParams(execution, + getUserParams(), serviceInstanceId, requestAction); + List<WorkflowType> expected = List.of(WorkflowType.SERVICE, WorkflowType.PNF); + List<WorkflowType> result = + resourceListFromUserParams.stream().map(Resource::getResourceType).collect(Collectors.toList()); + + assertEquals(2, resourceListFromUserParams.size()); + assertThat(expected, is(result)); + } + + @Test + public void getResourceListFromUserParamsForNetworks() throws Exception { + requestAction = "createInstance"; + initExecution(requestAction, readBpmnRequestFromFile(NETWORK_COLLECTION_JSON), false); + Mockito.doReturn(getVfModuleCustomization()).when(mockCatalogDbClient) + .getVfModuleCustomizationByModelCuztomizationUUID("a25e8e8c-58b8-4eec-810c-97dcc1f5cb7f"); + Mockito.doReturn(getCvnfcCustomizations()).when(mockCatalogDbClient).getCvnfcCustomization(anyString(), + anyString(), anyString()); + Mockito.doReturn(getService()).when(mockCatalogDbClient).getServiceByID(anyString()); + Mockito.doReturn(new NetworkCollectionResourceCustomization()).when(mockCatalogDbClient) + .getNetworkCollectionResourceCustomizationByID(anyString()); + + List<Resource> resourceListFromUserParams = userParamsServiceTraversal.getResourceListFromUserParams(execution, + getUserParams(), serviceInstanceId, requestAction); + List<WorkflowType> expected = List.of(WorkflowType.SERVICE, WorkflowType.NETWORK, WorkflowType.NETWORK, + WorkflowType.NETWORKCOLLECTION); + List<WorkflowType> result = + resourceListFromUserParams.stream().map(Resource::getResourceType).collect(Collectors.toList()); + + assertEquals(4, resourceListFromUserParams.size()); + assertThat(expected, is(result)); + } + + @Test + public void getResourceListFromUserParamsBuildAndThrowExceptionWhenVfModuleAreEmpty() throws Exception { + initExecution(requestAction, readBpmnRequestFromFile(MACRO_ASSIGN_JSON), false); + VfModuleCustomization vfModuleCustomization = new VfModuleCustomization(); + vfModuleCustomization.setVfModule(null); + Mockito.doReturn(vfModuleCustomization).when(mockCatalogDbClient) + .getVfModuleCustomizationByModelCuztomizationUUID("a25e8e8c-58b8-4eec-810c-97dcc1f5cb7f"); + + List<Resource> resourceListFromUserParams = userParamsServiceTraversal.getResourceListFromUserParams(execution, + getUserParams(), serviceInstanceId, requestAction); + List<WorkflowType> expected = List.of(WorkflowType.SERVICE, WorkflowType.VNF); + List<WorkflowType> result = + resourceListFromUserParams.stream().map(Resource::getResourceType).collect(Collectors.toList()); + + assertEquals(2, resourceListFromUserParams.size()); + assertThat(expected, is(result)); + } + + private List<Map<String, Object>> getUserParams() throws IOException { + String bpmnRequest = (String) execution.getVariable(BBConstants.G_BPMN_REQUEST); + ServiceInstancesRequest sIRequest = new ObjectMapper().readValue(bpmnRequest, ServiceInstancesRequest.class); + return sIRequest.getRequestDetails().getRequestParameters().getUserParams(); + } + + @Test + public void getResourceListFromUserParamsWhenUserParamsAreNull() throws Exception { + List<Resource> expectedResourceList = new ArrayList<>(); + List<Resource> resultResourceList = userParamsServiceTraversal.getResourceListFromUserParams(execution, null, + serviceInstanceId, requestAction); + + assertEquals(expectedResourceList, resultResourceList); + } + + private String readBpmnRequestFromFile(String fileName) throws IOException { + return new String(Files.readAllBytes(Paths.get("src/test/resources/__files/" + fileName))); + } + + private void initExecution(String gAction, String bpmnRequest, boolean isAlaCarte) { + execution.setVariable("mso-request-id", "00f704ca-c5e5-4f95-a72c-6889db7b0688"); + execution.setVariable("requestAction", gAction); + execution.setVariable("bpmnRequest", bpmnRequest); + execution.setVariable("aLaCarte", isAlaCarte); + execution.setVariable("apiVersion", "7"); + } + + private Service getService() { + Service service = new Service(); + List<CollectionResourceCustomization> collectionResourceCustomizations = new ArrayList<>(); + CollectionResourceCustomization collectionResourceCustomization = new CollectionResourceCustomization(); + collectionResourceCustomization.setModelCustomizationUUID("123"); + collectionResourceCustomizations.add(collectionResourceCustomization); + service.setCollectionResourceCustomizations(collectionResourceCustomizations); + return service; + } + + private VfModuleCustomization getVfModuleCustomization() { + VfModuleCustomization vfModuleCustomization = new VfModuleCustomization(); + vfModuleCustomization.setVolumeHeatEnv(new HeatEnvironment()); + vfModuleCustomization.setModelCustomizationUUID("a25e8e8c-58b8-4eec-810c-97dcc1f5cb7f"); + VfModule vfModule = new VfModule(); + vfModule.setVolumeHeatTemplate(new HeatTemplate()); + vfModule.setModelName("helm"); + vfModule.setModuleHeatTemplate(new HeatTemplate()); + vfModuleCustomization.setVfModule(vfModule); + return vfModuleCustomization; + } + + private List<CvnfcCustomization> getCvnfcCustomizations() { + ConfigurationResource configurationResource = new ConfigurationResource(); + configurationResource.setToscaNodeType("FabricConfiguration"); + + CvnfcConfigurationCustomization cvnfcConfigurationCustomization = new CvnfcConfigurationCustomization(); + cvnfcConfigurationCustomization.setConfigurationResource(configurationResource); + CvnfcCustomization cvnfcCustomization = new CvnfcCustomization(); + + List<CvnfcConfigurationCustomization> cvnfcConfigurationCustomizations = new ArrayList<>(); + cvnfcConfigurationCustomizations.add(cvnfcConfigurationCustomization); + cvnfcCustomization.setCvnfcConfigurationCustomization(cvnfcConfigurationCustomizations); + + List<CvnfcCustomization> cvnfcCustomizations = new ArrayList<>(); + cvnfcCustomizations.add(cvnfcCustomization); + return cvnfcCustomizations; + } +} diff --git a/bpmn/so-bpmn-tasks/src/test/resources/__files/Macro/ServiceMacroAssignPnf.json b/bpmn/so-bpmn-tasks/src/test/resources/__files/Macro/ServiceMacroAssignPnf.json new file mode 100644 index 0000000000..4be44e0c1f --- /dev/null +++ b/bpmn/so-bpmn-tasks/src/test/resources/__files/Macro/ServiceMacroAssignPnf.json @@ -0,0 +1,72 @@ +{ + "requestDetails": { + "modelInfo": { + "modelType": "service", + "modelInvariantId": "5d48acb5-097d-4982-aeb2-f4a3bd87d31b", + "modelVersionId": "3c40d244-808e-42ca-b09a-256d83d19d0a", + "modelName": "Sample Service Model", + "modelVersion": "10.0" + }, + "cloudConfiguration": { + "cloudOwner" : "my-custom-cloud-owner" + }, + "owningEntity": { + "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", + "owningEntityName": "PACKET CORE" + }, + "project": { + "projectName": "{some project name}" + }, + "subscriberInfo": { + "globalSubscriberId": "{some subscriber id}" + }, + "requestInfo": { + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "suppressRollback": true, + "requestorId": "xxxxxx", + "instanceName": "test" + }, + "requestParameters": { + "subscriptionServiceType": "VMX", + "aLaCarte": false, + "userParams": [ + { + "service": { + "modelInfo": { + "modelType": "service", + "modelName": "Sample Service Model", + "modelVersionId": "3c40d244-808e-42ca-b09a-256d83d19d0a" + }, + "instanceParams": [], + "resources": { + "pnfs": [ + { + "modelInfo": { + "modelType": "pnf", + "modelName": "2016-73_MOW-AVPN-vPE-BV-L", + "modelVersionId": "7f40c192-f63c-463e-ba94-286933b895f8", + "modelCustomizationName": "2016-73_MOW-AVPN-vPE-BV-L 0", + "modelCustomizationId": "ab153b6e-c364-44c0-bef6-1f2982117f04" + }, + "cloudConfiguration": { + "lcpCloudRegionId": "mdt1", + "tenantId": "88a6ca3ee0394ade9403f075db23167e" + }, + "platform": { + "platformName": "test" + }, + "lineOfBusiness": { + "lineOfBusinessName": "someValue" + }, + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "instanceParams": [] + } + ] + } + } + } + ] + } + } +} |